diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2e07674..d3ede97 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,8 +15,30 @@ env: CARGO_TERM_COLOR: always jobs: + network-stress-test: + name: Network Stress Test (Docker) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run Stress Test + # Run test for 2 minutes to ensure stability + run: | + export GAME_TEST_DURATION=2 + make stress-test + + approve-build: + name: Approve Build + needs: network-stress-test + runs-on: ubuntu-latest + environment: ui-build + steps: + - run: echo "Manual approval received." + build-tauri: name: Build Tauri ${{ matrix.platform.name }} + needs: approve-build runs-on: ${{ matrix.platform.runs-on }} strategy: fail-fast: false @@ -104,12 +126,6 @@ jobs: - name: Install Tauri CLI run: cargo install tauri-cli --version '^2.0.0' - - name: Cache Rust build artifacts - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.platform.target }}-tauri - workspaces: ui/src-tauri - - name: Install frontend dependencies working-directory: ui run: pnpm install diff --git a/.gitignore b/.gitignore index c451ece..1cb1c66 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,8 @@ target # Added by cargo /target -.DS_Store \ No newline at end of file +.DS_Store + +docker_test/results_* +netns_tests/reliability_test/results +netns_tests/reliability_test/archives \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e55b5ee..995b0a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,53 +4,27 @@ version = 4 [[package]] name = "actor-helper" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9378545a9ebea2fb1aee5a06030736ccb4d64e6558e96ac056e77fc7ac13d4b2" +checksum = "e27b633e8510b190e2a968f872136b8a53b38d855089f56030ce0ead131b3377" dependencies = [ "anyhow", - "flume", + "flume 0.12.0", "futures-executor", "futures-util", "tokio", ] -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "aead" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "generic-array", ] -[[package]] -name = "aead" -version = "0.6.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" -dependencies = [ - "bytes", - "crypto-common 0.2.0-rc.4", - "inout 0.2.1", -] - [[package]] name = "aes" version = "0.8.4" @@ -58,8 +32,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", - "cipher 0.4.4", - "cpufeatures", + "cipher", + "cpufeatures 0.2.17", ] [[package]] @@ -68,9 +42,9 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ - "aead 0.5.2", + "aead", "aes", - "cipher 0.4.4", + "cipher", "ctr", "ghash", "subtle", @@ -78,9 +52,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -91,12 +65,6 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -106,13 +74,78 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "arc-swap" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" dependencies = [ - "backtrace", + "rustversion", ] [[package]] @@ -123,9 +156,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "async-channel" @@ -139,19 +172,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-compat" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bab94bde396a3f7b4962e396fdad640e241ed797d4d8d77fc8c237d14c58fc0" -dependencies = [ - "futures-core", - "futures-io", - "once_cell", - "pin-project-lite", - "tokio", -] - [[package]] name = "async-task" version = "4.7.1" @@ -166,7 +186,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] @@ -180,6 +200,15 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -209,108 +238,78 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "backon" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592277618714fbcecda9a02ba7a8781f319d26532a88553bbacc77ba5d2b3a8d" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ "fastrand", "gloo-timers", "tokio", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "bao-tree" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06384416b1825e6e04fde63262fda2dc408f5b64c02d04e0d8b70ae72c17a52b" -dependencies = [ - "blake3", - "bytes", - "futures-lite", - "genawaiter", - "iroh-io", - "positioned-io", - "range-collections", - "self_cell", - "serde", - "smallvec", - "tokio", -] - [[package]] name = "base16ct" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] -name = "base16ct" -version = "0.3.0" +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base32" -version = "0.5.1" +name = "base64ct" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] -name = "base64" -version = "0.22.1" +name = "bit-set" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] [[package]] -name = "base64ct" -version = "1.8.0" +name = "bit-vec" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] -name = "binary-merge" -version = "0.1.2" +name = "bitflags" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.2" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "blake3" -version = "1.8.2" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", + "cpufeatures 0.3.0", ] [[package]] @@ -324,12 +323,20 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0-rc.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ "hybrid-array", - "zeroize", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", ] [[package]] @@ -346,16 +353,22 @@ dependencies = [ ] [[package]] -name = "btparse" -version = "0.2.0" +name = "bumpalo" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387e80962b798815a2b5c4bcfdb6bf626fa922ffe9f74e373103b858738e9f31" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] -name = "bumpalo" -version = "3.19.0" +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + +[[package]] +name = "bytemuck" +version = "1.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "d6aedf8ae72766347502cf3cb4f41cf5e9cc37d28bee90f1fdaaae15f9cf9424" [[package]] name = "byteorder" @@ -365,39 +378,29 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" dependencies = [ "serde", ] [[package]] -name = "c2rust-bitfields" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcee50917f9de1a018e3f4f9a8f2ff3d030a288cffa4b18d9b391e97c12e4cfb" -dependencies = [ - "c2rust-bitfields-derive", -] - -[[package]] -name = "c2rust-bitfields-derive" -version = "0.21.0" +name = "castaway" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b457277798202ccd365b9c112ebee08ddd57f1033916c8b8ea52f222e5b715d" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "rustversion", ] [[package]] name = "cc" -version = "1.2.33" +version = "1.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -409,109 +412,111 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" -version = "0.9.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", - "cipher 0.4.4", - "cpufeatures", + "cpufeatures 0.3.0", + "rand_core 0.10.1", ] [[package]] -name = "chacha20" -version = "0.10.0-rc.2" +name = "chrono" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ - "cfg-if", - "cipher 0.5.0-rc.1", - "cpufeatures", - "zeroize", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link 0.2.1", ] [[package]] -name = "chacha20poly1305" -version = "0.10.1" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "aead 0.5.2", - "chacha20 0.9.1", - "cipher 0.4.4", - "poly1305 0.8.0", - "zeroize", + "crypto-common 0.1.7", + "inout", ] [[package]] -name = "chrono" -version = "0.4.41" +name = "clap" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "dd059f9da4f5c36b3787f65d38ccaab1cc315f07b01f89abc8359ee6a8205011" dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link 0.1.3", + "clap_builder", + "clap_derive", ] [[package]] -name = "cipher" -version = "0.4.4" +name = "clap_builder" +version = "4.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" dependencies = [ - "crypto-common 0.1.6", - "inout 0.1.4", - "zeroize", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "cipher" -version = "0.5.0-rc.1" +name = "clap_derive" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ - "block-buffer 0.11.0-rc.5", - "crypto-common 0.2.0-rc.4", - "inout 0.2.1", - "zeroize", + "heck", + "proc-macro2", + "quote", + "syn 2.0.119", ] +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" + [[package]] name = "cobs" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.15", + "thiserror 2.0.18", ] [[package]] -name = "color-backtrace" -version = "0.7.0" +name = "colorchoice" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2123a5984bd52ca861c66f66a9ab9883b27115c607f801f86c1bc2a84eb69f0f" -dependencies = [ - "backtrace", - "btparse", - "termcolor", -] +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" @@ -523,6 +528,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -534,21 +553,24 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.6" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] -name = "const-oid" -version = "0.10.1" +name = "constant_time_eq" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] -name = "constant_time_eq" -version = "0.3.1" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "cordyceps" @@ -595,20 +617,29 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" dependencies = [ "crc-catalog", ] [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "critical-section" @@ -618,100 +649,100 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] -name = "crypto-bigint" -version = "0.5.5" +name = "crossterm" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", + "bitflags 2.13.1", + "crossterm_winapi", + "derive_more", + "document-features", + "mio", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", ] [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", - "rand_core 0.6.4", "typenum", ] [[package]] name = "crypto-common" -version = "0.2.0-rc.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", - "rand_core 0.9.3", ] [[package]] -name = "crypto_box" -version = "0.10.0-pre.0" +name = "csscolorparser" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bda4de3e070830cf3a27a394de135b6709aefcc54d1e16f2f029271254a6ed9" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" dependencies = [ - "aead 0.6.0-rc.2", - "chacha20 0.10.0-rc.2", - "crypto_secretbox", - "curve25519-dalek 5.0.0-pre.1", - "salsa20", - "serdect", - "subtle", - "zeroize", + "lab", + "phf", ] [[package]] -name = "crypto_secretbox" -version = "0.2.0-pre.0" +name = "ctr" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54532aae6546084a52cef855593daf9555945719eeeda9974150e0def854873e" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "aead 0.6.0-rc.2", - "chacha20 0.10.0-rc.2", - "cipher 0.5.0-rc.1", - "hybrid-array", - "poly1305 0.9.0-rc.2", - "salsa20", - "subtle", - "zeroize", + "cipher", ] [[package]] -name = "ctr" -version = "0.9.2" +name = "ctutils" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" dependencies = [ - "cipher 0.4.4", + "cmov", ] [[package]] @@ -721,26 +752,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "fiat-crypto 0.2.9", + "rand_core 0.6.4", "rustc_version", "subtle", - "zeroize", ] [[package]] name = "curve25519-dalek" -version = "5.0.0-pre.1" +version = "5.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" +checksum = "4f359e08ca85e7bd759e1fd933ff2bccd81864c60a8fba0e259c7f822b0924bf" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.3.0", "curve25519-dalek-derive", - "digest 0.11.0-rc.3", + "digest 0.11.3", "fiat-crypto 0.3.0", - "rand_core 0.9.3", + "rand_core 0.10.1", "rustc_version", "serde", "subtle", @@ -755,85 +786,201 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.119", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.119", ] [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] -name = "der" -version = "0.7.10" +name = "data-encoding-macro" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" dependencies = [ - "const-oid 0.9.6", - "zeroize", + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" +dependencies = [ + "data-encoding", + "syn 2.0.119", ] +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + [[package]] name = "der" -version = "0.8.0-rc.9" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" +checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d" dependencies = [ - "const-oid 0.10.1", + "const-oid", "pem-rfc7468", "zeroize", ] [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "powerfmt", + "derive_builder_macro", ] [[package]] -name = "derive_more" -version = "1.0.0" +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "derive_more-impl 1.0.0", + "derive_builder_core", + "syn 2.0.119", ] [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "1.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version", + "syn 2.0.119", "unicode-xid", ] [[package]] -name = "derive_more-impl" -version = "2.0.1" +name = "dht" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "bf85ef918f33294d98b8833ab7bd095700480b095295b275d36c8fdd86daafdd" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "unicode-xid", + "crc", + "document-features", + "dyn-clone", + "ed25519-dalek", + "flume 0.11.1", + "futures-lite", + "getrandom 0.3.4", + "lru 0.13.0", + "serde", + "serde_bencode", + "serde_bytes", + "sha1_smol", + "thiserror 2.0.18", + "tracing", ] [[package]] @@ -849,61 +996,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "crypto-common 0.1.6", + "crypto-common 0.1.7", "subtle", ] [[package]] name = "digest" -version = "0.11.0-rc.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer 0.11.0-rc.5", - "const-oid 0.10.1", - "crypto-common 0.2.0-rc.4", + "block-buffer 0.12.1", + "const-oid", + "crypto-common 0.2.2", + "ctutils", ] [[package]] -name = "displaydoc" -version = "0.2.5" +name = "dispatch2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "bitflags 2.13.1", + "block2", + "libc", + "objc2", ] [[package]] -name = "distributed-topic-tracker" -version = "0.2.5" +name = "displaydoc" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c1ed9a2484b742d78d0a1e1cc93cbc1a5de784e1138a2e69414851a9fe39bc" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ - "actor-helper", - "anyhow", - "chrono", - "ed25519-dalek", - "ed25519-dalek-hpke", - "futures-lite", - "iroh", - "iroh-gossip", - "mainline", - "postcard", - "rand 0.9.2", - "serde", - "sha2 0.10.9", - "tokio", - "tracing", - "tracing-subscriber", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] name = "dlopen2" -version = "0.5.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" dependencies = [ "libc", "once_cell", @@ -912,9 +1048,9 @@ dependencies = [ [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -927,67 +1063,36 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ed25519" -version = "3.0.0-rc.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef49c0b20c0ad088893ad2a790a29c06a012b3f05bcfc66661fd22a94b32129" +checksum = "29fcf32e6c73d1079f83ab4d782de2d81620346a5f38c6237a86a22f8368980a" dependencies = [ "pkcs8", - "serde", + "serdect", "signature", ] [[package]] name = "ed25519-dalek" -version = "3.0.0-pre.1" +version = "3.0.0-rc.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" +checksum = "b011170fe4f04665565b4110afef66774fe9ffff278f3eb5b81cc73d26e27d60" dependencies = [ - "curve25519-dalek 5.0.0-pre.1", + "curve25519-dalek 5.0.0-rc.0", "ed25519", - "rand_core 0.9.3", + "rand_core 0.10.1", "serde", - "sha2 0.11.0-rc.2", + "sha2 0.11.0", "signature", "subtle", "zeroize", ] -[[package]] -name = "ed25519-dalek-hpke" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3553f25a4e38b5ca64b26c54f34e1dd5092d18a5dea03797ac235baab53eaf8f" -dependencies = [ - "ed25519-dalek", - "hpke", - "rand 0.9.2", - "x25519-dalek", -] - [[package]] name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "elliptic-curve" -version = "0.13.8" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "hkdf", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "embedded-io" @@ -1011,15 +1116,14 @@ dependencies = [ ] [[package]] -name = "enum-as-inner" -version = "0.6.1" +name = "enum-assoc" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +checksum = "3ed8956bd5c1f0415200516e78ff07ec9e16415ade83c056c230d7b7ea0d55b7" dependencies = [ - "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] @@ -1030,12 +1134,21 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", ] [[package]] @@ -1060,19 +1173,40 @@ dependencies = [ ] [[package]] -name = "fastrand" -version = "2.3.0" +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "fast-srgb8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" [[package]] -name = "ff" -version = "0.13.1" +name = "fastbloom" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8" dependencies = [ - "rand_core 0.6.4", - "subtle", + "foldhash", + "libm", + "portable-atomic", + "siphasher", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +dependencies = [ + "getrandom 0.3.4", ] [[package]] @@ -1087,6 +1221,35 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "finl_unicode" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -1101,8 +1264,19 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "nanorand", - "spin 0.9.8", + "spin 0.9.9", +] + +[[package]] +name = "flume" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" +dependencies = [ + "fastrand", + "futures-core", + "futures-sink", + "spin 0.9.9", ] [[package]] @@ -1119,18 +1293,18 @@ checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "form_urlencoded" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ "percent-encoding", ] [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1143,22 +1317,22 @@ dependencies = [ [[package]] name = "futures-buffered" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd" +checksum = "4421cb78ee172b6b06080093479d3c50f058e7c81b7d577bbb8d118d551d4cd5" dependencies = [ "cordyceps", "diatomic-waker", "futures-core", "pin-project-lite", - "spin 0.10.0", + "spin 0.10.1", ] [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1166,30 +1340,28 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.3" +version = "7.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" +checksum = "175cd8cca9e1d45b87f18ffa75088f2099e3c4fe5e2f83e42de112560bea8ea6" dependencies = [ - "fixedbitset", - "futures-buffered", + "fixedbitset 0.5.7", "futures-core", "futures-lite", "pin-project", - "slab", "smallvec", ] [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1198,9 +1370,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -1217,32 +1389,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1252,53 +1424,22 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] -[[package]] -name = "genawaiter" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" -dependencies = [ - "futures-core", - "genawaiter-macro", - "genawaiter-proc-macro", - "proc-macro-hack", -] - -[[package]] -name = "genawaiter-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" - -[[package]] -name = "genawaiter-proc-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738" -dependencies = [ - "proc-macro-error", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "generator" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +checksum = "b3b854b0e584ead1a33f18b2fcad7cf7be18b3875c78816b753639aa501513ae" dependencies = [ "cc", "cfg-if", "libc", "log", "rustversion", - "windows 0.61.3", + "windows-link 0.2.1", + "windows-result 0.4.1", ] [[package]] @@ -1309,44 +1450,57 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] name = "getifaddrs" -version = "0.2.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c016cebf305060d144de015c98191ede05c210af588857bc2d4f8611c04663" +checksum = "a542e1b7ac1f3d62c5777d430d66eca9cb59e813c46b86e29fa9ce94ff9a4810" dependencies = [ - "bitflags", + "bitflags 2.13.1", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "r-efi 6.0.0", + "rand_core 0.10.1", "wasm-bindgen", ] @@ -1360,12 +1514,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -1384,22 +1532,11 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "h2" -version = "0.4.12" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -1425,15 +1562,20 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ "allocator-api2", "equivalent", @@ -1450,7 +1592,7 @@ dependencies = [ "hash32", "rustc_version", "serde", - "spin 0.9.8", + "spin 0.9.9", "stable_deref_trait", ] @@ -1467,28 +1609,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "hickory-proto" -version = "0.25.2" +name = "hickory-net" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183" dependencies = [ "async-trait", "bytes", "cfg-if", "data-encoding", - "enum-as-inner", "futures-channel", "futures-io", "futures-util", "h2", + "hickory-proto", "http", "idna", "ipnet", - "once_cell", - "rand 0.9.2", - "ring", + "jni 0.22.4", + "rand 0.10.2", "rustls", - "thiserror 2.0.15", + "thiserror 2.0.18", "tinyvec", "tokio", "tokio-rustls", @@ -1496,24 +1637,49 @@ dependencies = [ "url", ] +[[package]] +name = "hickory-proto" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni 0.22.4", + "once_cell", + "prefix-trie", + "rand 0.10.2", + "ring", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "url", +] + [[package]] name = "hickory-resolver" -version = "0.25.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c" dependencies = [ "cfg-if", "futures-util", + "hickory-net", "hickory-proto", "ipconfig", + "ipnet", + "jni 0.22.4", "moka", + "ndk-context", "once_cell", "parking_lot", - "rand 0.9.2", + "rand 0.10.2", "resolv-conf", "rustls", "smallvec", - "thiserror 2.0.15", + "system-configuration", + "thiserror 2.0.18", "tokio", "tokio-rustls", "tracing", @@ -1525,7 +1691,16 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ - "hmac", + "hmac 0.12.1", +] + +[[package]] +name = "hkdf" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aaa26c720c68b866f2c96ef5c1264b3e6f473fe5d4ce61cd44bbe913e553018" +dependencies = [ + "hmac 0.13.0", ] [[package]] @@ -1538,51 +1713,38 @@ dependencies = [ ] [[package]] -name = "home" -version = "0.5.11" +name = "hmac" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ - "windows-sys 0.59.0", + "digest 0.11.3", ] [[package]] -name = "hpke" -version = "0.13.0" +name = "home" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65d16b699dd1a1fa2d851c970b0c971b388eeeb40f744252b8de48860980c8f" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "aead 0.5.2", - "aes-gcm", - "chacha20poly1305", - "digest 0.10.7", - "generic-array", - "hkdf", - "hmac", - "p256", - "rand_core 0.9.3", - "sha2 0.10.9", - "subtle", - "x25519-dalek", - "zeroize", + "windows-sys 0.61.2", ] [[package]] name = "http" -version = "1.3.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", - "fnv", "itoa", ] [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -1590,9 +1752,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2" dependencies = [ "bytes", "futures-core", @@ -1613,25 +1775,31 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" + [[package]] name = "hybrid-array" -version = "0.4.5" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", - "zeroize", ] [[package]] name = "hyper" -version = "1.6.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -1646,31 +1814,28 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", - "webpki-roots", ] [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -1679,7 +1844,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2", "tokio", "tower-service", "tracing", @@ -1687,9 +1852,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1697,7 +1862,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -1711,12 +1876,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -1724,9 +1890,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -1737,11 +1903,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -1752,42 +1917,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -1795,11 +1956,23 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "identity-hash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdd7caa900436d8f13b2346fe10257e0c05c1f1f9e351f4f5d57c03bd5f45da" + [[package]] name = "idna" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1808,21 +1981,30 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", ] +[[package]] +name = "if-addrs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0a05c691e1fae256cf7013d99dad472dc52d5543322761f83ec8d47eab40d2b" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "igd-next" -version = "0.16.2" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516893339c97f6011282d5825ac94fc1c7aad5cad26bdc2d0cee068c0bf97f97" +checksum = "de7238d487a9aff61f81b5ab41c0a841532a115a398b5fa92a2fadd0885e2581" dependencies = [ - "async-trait", "attohttpc", "bytes", "futures", @@ -1831,7 +2013,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.9.2", + "rand 0.10.2", "tokio", "url", "xmltree", @@ -1839,136 +2021,109 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.17.1", ] [[package]] -name = "inout" -version = "0.1.4" +name = "indoc" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" dependencies = [ - "generic-array", + "rustversion", ] [[package]] name = "inout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "inplace-vec-builder" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" -dependencies = [ - "smallvec", -] - -[[package]] -name = "instant" -version = "0.1.13" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", + "generic-array", ] [[package]] -name = "io-uring" -version = "0.7.9" +name = "instability" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" dependencies = [ - "bitflags", - "cfg-if", - "libc", + "darling 0.23.0", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] name = "ipconfig" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.5.10", + "socket2", "widestring", - "windows-sys 0.48.0", - "winreg 0.50.0", + "windows-registry", + "windows-result 0.4.1", + "windows-sys 0.61.2", ] [[package]] name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" dependencies = [ - "memchr", "serde", ] [[package]] name = "iroh" -version = "0.95.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2374ba3cdaac152dc6ada92d971f7328e6408286faab3b7350842b2ebbed4789" +checksum = "5fca9b4b462c343ff88fc0af4096c186f939b602a0bc08723536ef2c31c93971" dependencies = [ - "aead 0.6.0-rc.2", "backon", + "blake3", "bytes", "cfg_aliases", - "crypto_box", + "ctutils", "data-encoding", - "derive_more 2.0.1", + "derive_more", "ed25519-dalek", "futures-util", - "getrandom 0.3.3", + "getrandom 0.4.3", "hickory-resolver", "http", - "igd-next", - "instant", + "ipnet", "iroh-base", + "iroh-dns", "iroh-metrics", - "iroh-quinn", - "iroh-quinn-proto", - "iroh-quinn-udp", "iroh-relay", "n0-error", "n0-future", "n0-watcher", - "netdev", "netwatch", + "noq", + "noq-proto", + "noq-udp", + "papaya", "pin-project", - "pkarr", - "pkcs8", + "portable-atomic", "portmapper", - "rand 0.9.2", + "rand 0.10.2", "reqwest", + "rustc-hash", "rustls", "rustls-pki-types", - "rustls-platform-verifier", - "rustls-webpki", "serde", "smallvec", - "strum 0.27.2", + "strum", "time", "tokio", "tokio-stream", @@ -1976,125 +2131,82 @@ dependencies = [ "tracing", "url", "wasm-bindgen-futures", - "webpki-roots", - "z32", +] + +[[package]] +name = "iroh-auth" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3158ecea750fbdd3a24e2bf5a45a6b8db3f032c78ea63c3f9efd1e85160093a0" +dependencies = [ + "hkdf 0.13.0", + "iroh", + "lru 0.18.1", + "n0-future", + "n0-watcher", + "rand 0.10.2", + "secrecy", + "sha2 0.11.0", + "spake2", + "subtle", + "tokio", + "tracing", ] [[package]] name = "iroh-base" -version = "0.95.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a8c5fb1cc65589f0d7ab44269a76f615a8c4458356952c9b0ef1c93ea45ff8" +checksum = "830a582cd54410dc1aa71d4786a82c3297d7b0165accd8b6dbbb3b240b48140d" dependencies = [ - "curve25519-dalek 5.0.0-pre.1", + "curve25519-dalek 5.0.0-rc.0", "data-encoding", - "derive_more 2.0.1", + "data-encoding-macro", + "derive_more", "ed25519-dalek", + "getrandom 0.4.3", "n0-error", - "rand_core 0.9.3", + "rand 0.10.2", "serde", "url", "zeroize", - "zeroize_derive", ] [[package]] -name = "iroh-blobs" -version = "0.97.0" +name = "iroh-dns" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c901304c1c28f257fcf9aae8c9149e54e0baf62f5eb2788cecde3bf1206a04e6" +checksum = "516e4eedc38e33ab69a6bd325520332dc3d67b25454e2d590ebb84a25240dd9a" dependencies = [ - "anyhow", - "arrayvec", - "bao-tree", - "bytes", + "arc-swap", "cfg_aliases", - "chrono", - "data-encoding", - "derive_more 2.0.1", - "futures-lite", - "genawaiter", - "hex", - "iroh", + "derive_more", + "hickory-resolver", "iroh-base", - "iroh-io", - "iroh-metrics", - "iroh-quinn", - "iroh-tickets", - "irpc", - "n0-error", - "n0-future", - "n0-snafu", - "nested_enum_utils", - "postcard", - "rand 0.9.2", - "range-collections", - "redb", - "ref-cast", - "reflink-copy", - "self_cell", - "serde", - "smallvec", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "iroh-docs" -version = "0.95.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fe6dc5524c65b401ebb5de204af8921c8cb329316eb972538622d708b4636c" -dependencies = [ - "anyhow", - "async-channel", - "blake3", - "bytes", - "derive_more 2.0.1", - "ed25519-dalek", - "futures-buffered", - "futures-lite", - "futures-util", - "hex", - "iroh", - "iroh-blobs", - "iroh-gossip", - "iroh-metrics", - "iroh-quinn", - "iroh-tickets", - "irpc", "n0-error", "n0-future", - "num_enum", - "postcard", - "rand 0.9.2", - "redb", - "self_cell", - "serde", - "serde-error", - "strum 0.26.3", - "tempfile", - "thiserror 2.0.15", + "ndk-context", + "portable-atomic", + "rand 0.10.2", + "rustls", + "simple-dns", + "strum", "tokio", - "tokio-stream", - "tokio-util", "tracing", + "url", ] [[package]] name = "iroh-gossip" -version = "0.95.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "026dd31b487ec5e80ac0240f4eb70cd6c0a2800f6ef44beca5329443c194bb22" +checksum = "4e1dc4b05f73e7a1b9e83b531eb63c3fd671b0af3aeb13b59c546dd7ca747515" dependencies = [ "blake3", "bytes", "data-encoding", - "derive_more 2.0.1", - "ed25519-dalek", + "derive_more", "futures-concurrency", - "futures-lite", - "futures-util", "hex", "indexmap", "iroh", @@ -2104,64 +2216,63 @@ dependencies = [ "n0-error", "n0-future", "postcard", - "rand 0.9.2", + "rand 0.10.2", "serde", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "iroh-io" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a5feb781017b983ff1b155cd1faf8174da2acafd807aa482876da2d7e6577a" -dependencies = [ - "bytes", - "futures-lite", - "pin-project", - "smallvec", - "tokio", -] - [[package]] name = "iroh-lan" -version = "0.1.2" +version = "1.0.0-pre.1" dependencies = [ "actor-helper", "anyhow", - "distributed-topic-tracker", + "blake3", + "bytes", + "chrono", + "clap", + "crossterm", "ed25519-dalek", "futures", + "futures-lite", + "if-addrs", + "ipnet", "iroh", - "iroh-blobs", - "iroh-docs", + "iroh-auth", "iroh-gossip", - "nix 0.30.1", + "iroh-topic-tracker", + "n0-watcher", + "netwatch", + "noq-proto", "pnet_packet", "postcard", - "rand 0.9.2", + "rand 0.9.5", + "ratatui", "runas", "self-runas", "serde", "sha2 0.10.9", + "thiserror 1.0.69", "tokio", "tracing", "tracing-subscriber", "tun-rs", + "url", "z32", ] [[package]] name = "iroh-metrics" -version = "0.37.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e3381da7c93c12d353230c74bba26131d1c8bf3a4d8af0fec041546454582e" +checksum = "291065721ad7c477b972e581bbc528df031dc8eb5e39fe1ff3300ae5dfb157ef" dependencies = [ "iroh-metrics-derive", "itoa", "n0-error", - "postcard", + "portable-atomic", "ryu", "serde", "tracing", @@ -2169,149 +2280,99 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" -version = "0.4.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e12bd0763fd16062f5cc5e8db15dd52d26e75a8af4c7fb57ccee3589b344b8" +checksum = "1ae5f0c4405d1fbc9fb16ff422ca40620e93dc36c30ecaba0c2aee3992b7bd48" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] -name = "iroh-quinn" -version = "0.14.0" +name = "iroh-relay" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde160ebee7aabede6ae887460cd303c8b809054224815addf1469d54a6fcf7" +checksum = "8149bb6a57126225a07d6928846d82dcedfd24ea0f863ef7b2eb475e1d726354" dependencies = [ + "blake3", "bytes", "cfg_aliases", - "iroh-quinn-proto", - "iroh-quinn-udp", - "pin-project-lite", - "rustc-hash", + "data-encoding", + "derive_more", + "getrandom 0.4.3", + "hickory-resolver", + "http", + "http-body-util", + "hyper", + "hyper-util", + "iroh-base", + "iroh-dns", + "iroh-metrics", + "lru 0.18.1", + "n0-error", + "n0-future", + "noq", + "noq-proto", + "num_enum", + "pin-project", + "postcard", + "rand 0.10.2", + "reqwest", "rustls", - "socket2 0.5.10", - "thiserror 2.0.15", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "iroh-quinn-proto" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "929d5d8fa77d5c304d3ee7cae9aede31f13908bd049f9de8c7c0094ad6f7c535" -dependencies = [ - "bytes", - "getrandom 0.2.16", - "rand 0.8.5", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "slab", - "thiserror 2.0.15", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "iroh-quinn-udp" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53afaa1049f7c83ea1331f5ebb9e6ebc5fdd69c468b7a22dd598b02c9bcc973" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.5.10", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "iroh-relay" -version = "0.95.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fbdf2aeffa7d6ede1a31f6570866c2199b1cee96a0b563994623795d1bac2c" -dependencies = [ - "blake3", - "bytes", - "cfg_aliases", - "data-encoding", - "derive_more 2.0.1", - "getrandom 0.3.3", - "hickory-resolver", - "http", - "http-body-util", - "hyper", - "hyper-util", - "iroh-base", - "iroh-metrics", - "iroh-quinn", - "iroh-quinn-proto", - "lru 0.16.2", - "n0-error", - "n0-future", - "num_enum", - "pin-project", - "pkarr", - "postcard", - "rand 0.9.2", - "reqwest", - "rustls", - "rustls-pki-types", - "serde", - "serde_bytes", - "sha1", - "strum 0.27.2", + "rustls-pki-types", + "serde", + "serde_bytes", + "strum", "tokio", "tokio-rustls", "tokio-util", "tokio-websockets", "tracing", "url", + "vergen-gitcl", "webpki-roots", "ws_stream_wasm", - "z32", ] [[package]] -name = "iroh-tickets" +name = "iroh-topic-tracker" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a322053cacddeca222f0999ce3cf6aa45c64ae5ad8c8911eac9b66008ffbaa5" +checksum = "5c7e42dab05470ae0ae7c9b3ce19fbbe6cf60c1ee62a54df4f451e57d3e565f6" dependencies = [ - "data-encoding", - "derive_more 2.0.1", - "iroh-base", - "n0-error", + "anyhow", + "bytes", + "dht", + "ed25519-dalek", + "futures-lite", + "hex", + "iroh", + "iroh-gossip", + "n0-future", + "n0-watcher", "postcard", + "rand 0.10.2", "serde", + "serde_json", + "sha2 0.11.0", + "tokio", + "tracing", + "tracing-subscriber", ] [[package]] name = "irpc" -version = "0.11.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bee97aaa18387c4f0aae61058195dc9f9dea3e41c0e272973fe3e9bf611563d" +checksum = "3623d6ff582b415904b29bbe6ebcb4a4f9a262ccdee05a45fdd003ef0950c386" dependencies = [ - "futures-buffered", "futures-util", - "iroh-quinn", "irpc-derive", "n0-error", "n0-future", - "postcard", - "rcgen", - "rustls", "serde", - "smallvec", "tokio", "tokio-util", "tracing", @@ -2319,20 +2380,35 @@ dependencies = [ [[package]] name = "irpc-derive" -version = "0.9.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58148196d2230183c9679431ac99b57e172000326d664e8456fa2cd27af6505a" +checksum = "35c254013736de16472140d26904e6ac98e8f3887284dcf4af40f88c77411b56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", ] [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" @@ -2343,29 +2419,99 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] +[[package]] +name = "kasuari" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.18", +] + +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + [[package]] name = "lazy_static" version = "1.5.0" @@ -2374,18 +2520,33 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.177" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" -version = "0.8.8" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link 0.2.1", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "line-clipping" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" +dependencies = [ + "bitflags 2.13.1", ] [[package]] @@ -2396,37 +2557,36 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "loom" @@ -2449,11 +2609,11 @@ checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" [[package]] name = "lru" -version = "0.16.2" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +checksum = "0b6180140927ee907000b0aa540091f6ea512ead4447c92b8fc35bc72788a5a6" dependencies = [ - "hashbrown 0.16.0", + "hashbrown 0.17.1", ] [[package]] @@ -2462,6 +2622,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mac-addr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d25b0e0b648a86960ac23b7ad4abb9717601dec6f66c165f5b037f3f03065f" + [[package]] name = "mac_address" version = "1.1.8" @@ -2473,41 +2639,25 @@ dependencies = [ ] [[package]] -name = "mainline" -version = "6.0.0" +name = "matchers" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be6c12ff79bfbf65bcbec84882a4bf700177df6d83a7b866c6a01cda7db4777" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "crc", - "document-features", - "dyn-clone", - "ed25519-dalek", - "flume", - "futures-lite", - "getrandom 0.3.3", - "lru 0.16.2", - "serde", - "serde_bencode", - "serde_bytes", - "sha1_smol", - "thiserror 2.0.15", - "tracing", + "regex-automata", ] [[package]] -name = "matchers" -version = "0.1.0" +name = "memchr" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] -name = "memchr" -version = "2.7.5" +name = "memmem" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" [[package]] name = "memoffset" @@ -2519,49 +2669,45 @@ dependencies = [ ] [[package]] -name = "miniz_oxide" -version = "0.8.9" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "1.0.4" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "log", + "wasi", + "windows-sys 0.61.2", ] [[package]] name = "moka" -version = "0.12.10" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "loom", + "equivalent", "parking_lot", "portable-atomic", - "rustc_version", "smallvec", "tagptr", - "thiserror 1.0.69", "uuid", ] [[package]] name = "n0-error" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d5969a2f40e9d9ed121a789c415f4114ac2b28e5731c080bdefee217d3b3fb" +checksum = "c37e81176a83a77d2514528b91bdafc70ef88aab428f0e1b91aebb8d99888895" dependencies = [ "anyhow", "n0-error-macros", @@ -2570,23 +2716,23 @@ dependencies = [ [[package]] name = "n0-error-macros" -version = "0.1.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a6908df844696d9af91c7c3950d50e52d67df327d02a95367f95bbf177d6556" +checksum = "e2acd8b070213b0299282f884b4beba4e7b52d624fdcd504a3ad3665390c11e1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "n0-future" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c0709ac8235ce13b82bc4d180ee3c42364b90c1a8a628c3422d991d75a728b5" +checksum = "e2ab99dfb861450e68853d34ae665243a88b8c493d01ba957321a1e9b2312bbe" dependencies = [ "cfg_aliases", - "derive_more 1.0.0", + "derive_more", "futures-buffered", "futures-lite", "futures-util", @@ -2601,97 +2747,81 @@ dependencies = [ ] [[package]] -name = "n0-snafu" -version = "0.2.2" +name = "n0-qlog" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1815107e577a95bfccedb4cfabc73d709c0db6d12de3f14e0f284a8c5036dc4f" +checksum = "bb1c2fc610d1facce51b0bf5d8245b309c91996a933defdf7742c92ac78a58cb" dependencies = [ - "anyhow", - "btparse", - "color-backtrace", - "snafu", - "tracing-error", + "humantime", + "serde", + "serde_json", + "serde_with", + "strum", ] [[package]] name = "n0-watcher" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38acf13c1ddafc60eb7316d52213467f8ccb70b6f02b65e7d97f7799b1f50be4" +checksum = "bbc618745ad0b7414b149d0517ad8b5573b2fb4d4e2717add3d2446ce1fdd826" dependencies = [ - "derive_more 2.0.1", + "derive_more", "n0-error", "n0-future", ] [[package]] -name = "nanorand" -version = "0.7.0" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "nested_enum_utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fa9161ed44d30e9702fe42bd78693bceac0fed02f647da749f36109023d3a3" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "netconfig-rs" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207561c8758738388c2fd851c3e759f503583d8dd70ddc895baae806753ad4c9" +checksum = "733ad7a1352f0748a620368f2ea5cd94f0e449c5108fbac86ace31df1601bf6f" dependencies = [ "cfg-if", - "core-foundation 0.9.4", + "core-foundation 0.10.1", "ipnet", "libc", - "netlink-packet-core 0.7.0", - "netlink-packet-route 0.24.0", + "netlink-packet-core", + "netlink-packet-route 0.25.1", "netlink-sys", "nix 0.30.1", "scopeguard", - "system-configuration-sys 0.5.0", - "thiserror 2.0.15", + "system-configuration-sys", + "thiserror 2.0.18", "widestring", "windows 0.61.3", ] [[package]] name = "netdev" -version = "0.38.2" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ab878b4c90faf36dab10ea51d48c69ae9019bcca47c048a7c9b273d5d7a823" +checksum = "569dfbdd2efd771b24ec9bb57f956e04d4fbfc72f62b2f11961723f9b3f4b020" dependencies = [ + "block2", + "dispatch2", "dlopen2", "ipnet", + "jni 0.21.1", "libc", - "netlink-packet-core 0.8.1", - "netlink-packet-route 0.25.1", + "mac-addr", + "ndk-context", + "netlink-packet-core", + "netlink-packet-route 0.31.0", "netlink-sys", + "objc2", + "objc2-core-foundation", + "objc2-core-wlan", + "objc2-foundation", + "objc2-system-configuration", "once_cell", - "system-configuration", - "windows-sys 0.59.0", -] - -[[package]] -name = "netlink-packet-core" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" -dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-utils", + "plist", + "windows-sys 0.61.2", ] [[package]] @@ -2705,41 +2835,38 @@ dependencies = [ [[package]] name = "netlink-packet-route" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d83370a96813d7c977f8b63054f1162df6e5784f1c598d689236564fb5a6f2" +checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef" dependencies = [ - "anyhow", - "bitflags", - "byteorder", + "bitflags 2.13.1", "libc", "log", - "netlink-packet-core 0.7.0", - "netlink-packet-utils", + "netlink-packet-core", ] [[package]] name = "netlink-packet-route" -version = "0.25.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef" +checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" dependencies = [ - "bitflags", + "bitflags 2.13.1", "libc", "log", - "netlink-packet-core 0.8.1", + "netlink-packet-core", ] [[package]] -name = "netlink-packet-utils" -version = "0.5.2" +name = "netlink-packet-route" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +checksum = "e2288fcb784eb3defd5fb16f4c4160d5f477de192eac730f43e1d11c24d9a007" dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror 1.0.69", + "bitflags 2.13.1", + "libc", + "log", + "netlink-packet-core", ] [[package]] @@ -2751,19 +2878,19 @@ dependencies = [ "bytes", "futures", "log", - "netlink-packet-core 0.8.1", + "netlink-packet-core", "netlink-sys", - "thiserror 2.0.15", + "thiserror 2.0.18", ] [[package]] name = "netlink-sys" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" +checksum = "cd6c30ed10fa69cc491d491b85cc971f6bdeb8e7367b7cde2ee6cc878d583fae" dependencies = [ "bytes", - "futures", + "futures-util", "libc", "log", "tokio", @@ -2771,28 +2898,29 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f2acd376ef48b6c326abf3ba23c449e0cb8aa5c2511d189dd8a8a3bfac889b" +version = "0.19.1" dependencies = [ "atomic-waker", "bytes", "cfg_aliases", - "derive_more 2.0.1", - "iroh-quinn-udp", + "derive_more", + "ipnet", "js-sys", "libc", "n0-error", "n0-future", "n0-watcher", "netdev", - "netlink-packet-core 0.8.1", - "netlink-packet-route 0.25.1", + "netlink-packet-core", + "netlink-packet-route 0.31.0", "netlink-proto", "netlink-sys", + "noq-udp", + "objc2-core-foundation", + "objc2-system-configuration", "pin-project-lite", "serde", - "socket2 0.6.0", + "socket2", "time", "tokio", "tokio-util", @@ -2809,7 +2937,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags", + "bitflags 2.13.1", "cfg-if", "cfg_aliases", "libc", @@ -2822,7 +2950,20 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags", + "bitflags 2.13.1", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags 2.13.1", "cfg-if", "cfg_aliases", "libc", @@ -2836,35 +2977,101 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" [[package]] -name = "ntimestamp" -version = "1.0.0" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50f94c405726d3e0095e89e72f75ce7f6587b94a8bd8dc8054b73f65c0fd68c" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "base32", - "document-features", - "getrandom 0.2.16", - "httpdate", - "js-sys", - "once_cell", - "serde", + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noq" +version = "1.1.0" +source = "git+https://github.com/n0-computer/noq?rev=0a445ddf828d3be8c973877d3053043998146f36#0a445ddf828d3be8c973877d3053043998146f36" +dependencies = [ + "bytes", + "cfg_aliases", + "derive_more", + "noq-proto", + "noq-udp", + "pin-project-lite", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "web-time", +] + +[[package]] +name = "noq-proto" +version = "1.1.0" +source = "git+https://github.com/n0-computer/noq?rev=0a445ddf828d3be8c973877d3053043998146f36#0a445ddf828d3be8c973877d3053043998146f36" +dependencies = [ + "aes-gcm", + "bytes", + "derive_more", + "enum-assoc", + "fastbloom", + "getrandom 0.4.3", + "identity-hash", + "lru-slab", + "n0-qlog", + "rand 0.10.2", + "rand_pcg", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "sorted-index-buffer", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "noq-udp" +version = "1.1.0" +source = "git+https://github.com/n0-computer/noq?rev=0a445ddf828d3be8c973877d3053043998146f36#0a445ddf828d3be8c973877d3053043998146f36" +dependencies = [ + "cfg_aliases", + "libc", + "socket2", + "tracing", + "windows-sys 0.61.2", ] [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys 0.61.2", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] name = "num-traits" @@ -2877,9 +3084,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -2887,35 +3094,131 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] -name = "object" -version = "0.36.7" +name = "num_threads" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ - "memchr", + "libc", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.1", + "block2", + "dispatch2", + "libc", + "objc2", +] + +[[package]] +name = "objc2-core-wlan" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e34919aba0d701380d911702455038a8a3587467fe0141d6a71501e7ffe48" +dependencies = [ + "bitflags 2.13.1", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-security", + "objc2-security-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.1", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags 2.13.1", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-security-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef76382e9cedd18123099f17638715cc3d81dba3637d4c0d39ab69df2ef345a5" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-system-configuration" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" +dependencies = [ + "bitflags 2.13.1", + "dispatch2", + "libc", + "objc2", + "objc2-core-foundation", + "objc2-security", ] [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -2924,24 +3227,51 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] -name = "overload" -version = "0.1.1" +name = "ordered-float" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] [[package]] -name = "p256" -version = "0.13.2" +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "papaya" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" dependencies = [ - "elliptic-curve", - "primeorder", + "equivalent", + "seize", ] [[package]] @@ -2952,9 +3282,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2962,15 +3292,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -2980,29 +3310,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] -name = "pem" -version = "3.0.5" +name = "pem-rfc7468" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" dependencies = [ - "base64", - "serde", + "base64ct", ] [[package]] -name = "pem-rfc7468" -version = "1.0.0-rc.3" +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ - "base64ct", + "memchr", + "ucd-trie", ] [[package]] -name = "percent-encoding" -version = "2.3.1" +name = "pest_derive" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pest_meta" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" +dependencies = [ + "pest", +] [[package]] name = "pharos" @@ -3014,43 +3376,89 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.7", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -3058,44 +3466,26 @@ dependencies = [ ] [[package]] -name = "pkarr" -version = "5.0.0" +name = "pkcs8" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "792c1328860f6874e90e3b387b4929819cc7783a6bd5a4728e918706eb436a48" +checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7" dependencies = [ - "async-compat", - "base32", - "bytes", - "cfg_aliases", - "document-features", - "dyn-clone", - "ed25519-dalek", - "futures-buffered", - "futures-lite", - "getrandom 0.3.3", - "log", - "lru 0.13.0", - "ntimestamp", - "reqwest", - "self_cell", - "serde", - "sha1_smol", - "simple-dns", - "thiserror 2.0.15", - "tokio", - "tracing", - "url", - "wasm-bindgen-futures", + "der", + "spki", ] [[package]] -name = "pkcs8" -version = "0.11.0-rc.7" +name = "plist" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ - "der 0.8.0-rc.9", - "spki", + "base64", + "indexmap", + "quick-xml", + "serde", + "time", ] [[package]] @@ -3116,7 +3506,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] @@ -3140,27 +3530,6 @@ dependencies = [ "pnet_macros_support", ] -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash 0.5.1", -] - -[[package]] -name = "poly1305" -version = "0.9.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" -dependencies = [ - "cpufeatures", - "universal-hash 0.6.0-rc.2", -] - [[package]] name = "polyval" version = "0.6.2" @@ -3168,39 +3537,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", - "universal-hash 0.5.1", + "universal-hash", ] [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" +dependencies = [ + "serde", +] [[package]] name = "portmapper" -version = "0.12.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b575f975dcf03e258b0c7ab3f81497d7124f508884c37da66a7314aa2a8d467" +checksum = "eb3713e4977408279158444a18c1a01ac9bf2e7eaf1fbfd1a19ac9cd18d90721" dependencies = [ "base64", "bytes", - "derive_more 2.0.1", - "futures-lite", - "futures-util", + "derive_more", "hyper-util", "igd-next", "iroh-metrics", "libc", "n0-error", + "n0-future", "netwatch", "num_enum", - "rand 0.9.2", + "rand 0.10.2", "serde", "smallvec", - "socket2 0.6.0", + "socket2", "time", "tokio", "tokio-util", @@ -3209,16 +3580,6 @@ dependencies = [ "url", ] -[[package]] -name = "positioned-io" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ec4b80060f033312b99b6874025d9503d2af87aef2dd4c516e253fbfcdada7" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "postcard" version = "1.1.3" @@ -3241,14 +3602,14 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -3269,124 +3630,48 @@ dependencies = [ ] [[package]] -name = "primeorder" -version = "0.13.6" +name = "prefix-trie" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7" dependencies = [ - "elliptic-curve", + "either", + "ipnet", + "num-traits", ] [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "syn-mid", - "version_check", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] -name = "quinn" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2 0.5.10", - "thiserror 2.0.15", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" -dependencies = [ - "bytes", - "getrandom 0.3.3", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.15", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.13" +name = "quick-xml" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.5.10", - "tracing", - "windows-sys 0.59.0", + "memchr", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -3397,35 +3682,40 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" -version = "0.8.5" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" dependencies = [ - "libc", - "rand_chacha 0.3.1", "rand_core 0.6.4", ] [[package]] name = "rand" -version = "0.9.2" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_chacha", + "rand_core 0.9.5", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "rand" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -3435,7 +3725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -3444,143 +3734,177 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" dependencies = [ - "getrandom 0.3.3", + "rand_core 0.10.1", ] [[package]] -name = "range-collections" -version = "0.4.6" +name = "ratatui" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861706ea9c4aded7584c5cd1d241cec2ea7f5f50999f236c22b65409a1f1a0d0" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" dependencies = [ - "binary-merge", - "inplace-vec-builder", - "ref-cast", + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termina", + "ratatui-termwiz", + "ratatui-widgets", "serde", - "smallvec", ] [[package]] -name = "rcgen" -version = "0.14.5" +name = "ratatui-core" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fae430c6b28f1ad601274e78b7dffa0546de0b73b4cd32f46723c0c2a16f7a5" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "pem", - "ring", - "rustls-pki-types", - "time", - "yasna", + "bitflags 2.13.1", + "compact_str", + "critical-section", + "hashbrown 0.17.1", + "itertools", + "kasuari", + "lru 0.18.1", + "palette", + "serde", + "strum", + "thiserror 2.0.18", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", ] [[package]] -name = "redb" -version = "2.6.3" +name = "ratatui-crossterm" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eca1e9d98d5a7e9002d0013e18d5a9b000aee942eb134883a82f06ebffb6c01" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" dependencies = [ - "libc", + "cfg-if", + "crossterm", + "instability", + "ratatui-core", ] [[package]] -name = "redox_syscall" -version = "0.5.17" +name = "ratatui-macros" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" dependencies = [ - "bitflags", + "ratatui-core", + "ratatui-widgets", ] [[package]] -name = "ref-cast" -version = "1.0.24" +name = "ratatui-termina" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" dependencies = [ - "ref-cast-impl", + "instability", + "ratatui-core", + "termina", ] [[package]] -name = "ref-cast-impl" -version = "1.0.24" +name = "ratatui-termwiz" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "ratatui-core", + "termwiz", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" +dependencies = [ + "bitflags 2.13.1", + "hashbrown 0.17.1", + "indoc", + "instability", + "itertools", + "line-clipping", + "ratatui-core", + "serde", + "strum", + "time", + "unicode-segmentation", + "unicode-width", ] [[package]] -name = "reflink-copy" -version = "0.1.27" +name = "redox_syscall" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd34aed05de14a9001009dbffc2a6843095dcd8fe3d1207016192717a449d218" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "cfg-if", - "libc", - "rustix 1.0.8", - "windows 0.62.2", + "bitflags 2.13.1", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.12.23" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", @@ -3596,12 +3920,9 @@ dependencies = [ "log", "percent-encoding", "pin-project-lite", - "quinn", "rustls", "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", + "rustls-platform-verifier", "sync_wrapper", "tokio", "tokio-rustls", @@ -3614,14 +3935,13 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", ] [[package]] name = "resolv-conf" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "ring" @@ -3631,7 +3951,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -3639,16 +3959,16 @@ dependencies = [ [[package]] name = "route_manager" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb012980f7bfadc330cc5b99e2a93bda641717554338b6ddb0e86de4188af65b" +checksum = "1de4a73da5e20c4e521c395e21918034624165c31511e86b03e494bf0afa56ef" dependencies = [ - "flume", + "flume 0.12.0", "libc", - "netlink-packet-core 0.7.0", - "netlink-packet-route 0.24.0", + "netlink-packet-core", + "netlink-packet-route 0.28.0", "netlink-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3675,17 +3995,11 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -3702,7 +4016,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.13.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3711,22 +4025,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.13.1", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138" dependencies = [ "log", "once_cell", @@ -3739,9 +4053,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -3751,9 +4065,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -3761,13 +4075,13 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.5.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.22.4", "log", "once_cell", "rustls", @@ -3776,8 +4090,8 @@ dependencies = [ "rustls-webpki", "security-framework", "security-framework-sys", - "webpki-root-certs 0.26.11", - "windows-sys 0.59.0", + "webpki-root-certs", + "windows-sys 0.61.2", ] [[package]] @@ -3788,9 +4102,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -3799,25 +4113,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "salsa20" -version = "0.11.0-rc.1" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ff3b81c8a6e381bc1673768141383f9328048a60edddcfc752a8291a138443" -dependencies = [ - "cfg-if", - "cipher 0.5.0-rc.1", -] +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -3830,11 +4134,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3850,25 +4154,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "sec1" -version = "0.7.3" +name = "secrecy" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" dependencies = [ - "base16ct 0.2.0", - "der 0.7.10", - "generic-array", - "subtle", "zeroize", ] [[package]] name = "security-framework" -version = "3.3.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.13.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3877,14 +4177,24 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "seize" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "self-runas" version = "0.1.0" @@ -3897,17 +4207,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "self_cell" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" - [[package]] name = "semver" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "send_wrapper" @@ -3925,15 +4229,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342110fb7a5d801060c885da03bf91bfa7c7ca936deafcc64bb6706375605d47" -dependencies = [ - "serde", -] - [[package]] name = "serde_bencode" version = "0.2.4" @@ -3946,11 +4241,12 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -3970,52 +4266,53 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ + "indexmap", "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "serde_with" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "76a5c54c7310e7b8b9577c286d7e399ddd876c3e12b3ed917a8aabc4b96e9e8c" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", + "serde_core", + "serde_with_macros", ] [[package]] -name = "serdect" -version = "0.4.1" +name = "serde_with_macros" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ - "base16ct 0.3.0", - "serde", + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "sha1" -version = "0.11.0-rc.2" +name = "serdect" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e046edf639aa2e7afb285589e5405de2ef7e61d4b0ac1e30256e3eab911af9" +checksum = "66cf8fedced2fcf12406bcb34223dffb92eaf34908ede12fed414c82b7f00b3e" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.3", + "base16ct", + "serde", ] [[package]] @@ -4031,19 +4328,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] [[package]] name = "sha2" -version = "0.11.0-rc.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.3", + "cpufeatures 0.3.0", + "digest 0.11.3", ] [[package]] @@ -4057,24 +4354,56 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio", + "signal-hook", +] [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "signature" -version = "3.0.0-rc.4" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d567dcbaf0049cb8ac2608a76cd95ff9e4412e1899d389ee400918ca7537f5" + +[[package]] +name = "simd_cesu8" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] name = "simdutf8" @@ -4084,68 +4413,57 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "simple-dns" -version = "0.9.3" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" +checksum = "7a75cbde1bf934313596a004973e462f9a82caa814dcf1a5f507bdf51597eeb4" dependencies = [ - "bitflags", + "bitflags 2.13.1", ] [[package]] -name = "slab" -version = "0.4.11" +name = "siphasher" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] -name = "smallvec" -version = "1.15.1" +name = "slab" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -dependencies = [ - "serde", -] +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] -name = "snafu" -version = "0.8.6" +name = "smallvec" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320b01e011bf8d5d7a4a4a4be966d9160968935849c83b918827f6a435e7f627" -dependencies = [ - "backtrace", - "snafu-derive", -] +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] -name = "snafu-derive" -version = "0.8.6" +name = "socket2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.106", + "libc", + "windows-sys 0.61.2", ] [[package]] -name = "socket2" -version = "0.5.10" +name = "sorted-index-buffer" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] +checksum = "ea06cc588e43c632923a55450401b8f25e628131571d4e1baea1bdfdb2b5ed06" [[package]] -name = "socket2" -version = "0.6.0" +name = "spake2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "c5482afe85a0b6ce956c945401598dbc527593c77ba51d0a87a586938b1b893a" dependencies = [ - "libc", - "windows-sys 0.59.0", + "curve25519-dalek 4.1.3", + "hkdf 0.12.4", + "rand_core 0.6.4", + "sha2 0.10.9", ] [[package]] @@ -4156,81 +4474,71 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "spin" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" dependencies = [ "lock_api", ] [[package]] name = "spin" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" [[package]] name = "spki" -version = "0.8.0-rc.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" +checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f" dependencies = [ "base64ct", - "der 0.8.0-rc.9", + "der", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "strum" -version = "0.26.3" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros 0.26.4", -] +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "strum" -version = "0.27.2" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros 0.27.2", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "strum_macros" -version = "0.26.4" +name = "strum" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.106", + "strum_macros", ] [[package]] name = "strum_macros" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] @@ -4252,26 +4560,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn-mid" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea305d57546cc8cd04feb14b62ec84bf17f50e3f7b12560d7bfa9265f39d9ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -4289,28 +4586,18 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags", + "bitflags 2.13.1", "core-foundation 0.9.4", - "system-configuration-sys 0.6.0", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", + "system-configuration-sys", ] [[package]] @@ -4330,25 +4617,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] -name = "tempfile" -version = "3.21.0" +name = "termina" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.0.8", - "windows-sys 0.60.2", + "bitflags 2.13.1", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "windows-sys 0.61.2", ] [[package]] -name = "termcolor" -version = "1.4.1" +name = "terminfo" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" dependencies = [ - "winapi-util", + "fnv", + "nom", + "phf", + "phf_codegen", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +dependencies = [ + "anyhow", + "base64", + "bitflags 2.13.1", + "fancy-regex", + "filedescriptor", + "finl_unicode", + "fixedbitset 0.4.2", + "hex", + "lazy_static", + "libc", + "log", + "memmem", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "phf", + "sha2 0.10.9", + "signal-hook", + "siphasher", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", ] [[package]] @@ -4362,11 +4703,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.15" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.15", + "thiserror-impl 2.0.18", ] [[package]] @@ -4377,54 +4718,67 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "thiserror-impl" -version = "2.0.15" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "thread_local" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" dependencies = [ "cfg-if", ] [[package]] name = "time" -version = "0.3.41" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", "js-sys", + "libc", "num-conv", + "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", + "time-macros", ] [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" +dependencies = [ + "num-conv", + "time-core", +] [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -4432,9 +4786,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" dependencies = [ "tinyvec_macros", ] @@ -4447,39 +4801,37 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "d988bcd52dbe076d3d46903332f58c912b87a2c49b1428419a5845154762ffee" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -4487,9 +4839,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -4499,9 +4851,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -4513,20 +4865,21 @@ dependencies = [ [[package]] name = "tokio-websockets" -version = "0.12.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f29ba084eb43becc9864ba514b4a64f5f65b82f9a6ffbafa5436c1c80605f03" +checksum = "d52efb639344a7c6adb8e62c6f3d2c19c001ff1b79a5041ba1c6ed42e19c6aa5" dependencies = [ "base64", "bytes", "futures-core", "futures-sink", - "getrandom 0.3.3", + "getrandom 0.4.3", "http", "httparse", - "rand 0.9.2", + "rand 0.10.2", "ring", "rustls-pki-types", + "sha1_smol", "simdutf8", "tokio", "tokio-rustls", @@ -4535,26 +4888,39 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.13+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] [[package]] -name = "toml_edit" -version = "0.22.27" +name = "toml_parser" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "indexmap", - "toml_datetime", "winnow", ] [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -4567,20 +4933,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags", + "bitflags 2.13.1", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -4597,9 +4963,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -4609,35 +4975,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -4651,14 +5007,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -4675,66 +5031,83 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tun-rs" -version = "2.7.7" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1842070c95f1e34f5563748c1218448899ea5ed9b76d8ba20b9c24b100f16f" +checksum = "ea75f145e8f32c72b1afdf137f2181810b0232be9930519e8d82071b4a3b3bdf" dependencies = [ "blocking", "byteorder", "bytes", - "c2rust-bitfields", "encoding_rs", "getifaddrs", "ipnet", "libc", "libloading", "log", - "mac_address", "netconfig-rs", - "nix 0.30.1", + "nix 0.31.3", "route_manager", "scopeguard", "tokio", "widestring", "windows-sys 0.61.2", - "winreg 0.55.0", + "winreg", ] [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "ucd-trie" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "unicode-segmentation" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] -name = "universal-hash" -version = "0.5.1" +name = "unicode-truncate" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ - "crypto-common 0.1.6", - "subtle", + "itertools", + "unicode-segmentation", + "unicode-width", ] +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "universal-hash" -version = "0.6.0-rc.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.1.7", "subtle", ] @@ -4746,14 +5119,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -4762,13 +5136,20 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.18.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239" dependencies = [ - "getrandom 0.3.3", + "atomic", + "getrandom 0.4.3", "js-sys", "wasm-bindgen", ] @@ -4779,12 +5160,58 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "vergen" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "vergen-lib", +] + +[[package]] +name = "vergen-gitcl" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ff3b5300a085d6bcd8fc96a507f706a28ae3814693236c9b409db71a1d15b9" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vtparse" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +dependencies = [ + "utf8parse", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -4811,58 +5238,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4870,31 +5281,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -4905,9 +5316,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -4925,29 +5336,92 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "0.26.11" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ - "webpki-root-certs 1.0.2", + "rustls-pki-types", ] [[package]] -name = "webpki-root-certs" -version = "1.0.2" +name = "webpki-roots" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" dependencies = [ "rustls-pki-types", ] [[package]] -name = "webpki-roots" -version = "1.0.4" +name = "wezterm-bidi" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" dependencies = [ - "rustls-pki-types", + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +dependencies = [ + "getrandom 0.3.4", + "mac_address", + "sha2 0.10.9", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +dependencies = [ + "csscolorparser", + "deltae", + "lazy_static", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +dependencies = [ + "log", + "ordered-float", + "strsim", + "thiserror 1.0.69", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "lazy_static", + "serde", + "wezterm-dynamic", ] [[package]] @@ -4964,9 +5438,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi" @@ -4986,11 +5460,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5098,7 +5572,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] @@ -5109,7 +5583,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] @@ -5144,6 +5618,17 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.3.4" @@ -5216,15 +5701,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.3", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -5273,30 +5749,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 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]] -name = "windows-targets" -version = "0.53.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" -dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows-threading" version = "0.1.0" @@ -5333,12 +5792,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -5357,12 +5810,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -5381,24 +5828,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[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_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -5417,12 +5852,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -5441,12 +5870,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -5465,12 +5888,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -5489,70 +5906,51 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" -version = "0.7.12" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.55.0" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10" dependencies = [ "cfg-if", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "wmi" -version = "0.17.2" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3de777dce4cbcdc661d5d18e78ce4b46a37adc2bb7c0078a556c7f07bcce2f" +checksum = "7c81b85c57a57500e56669586496bf2abd5cf082b9d32995251185d105208b64" dependencies = [ "chrono", "futures", "log", "serde", - "thiserror 2.0.15", - "windows 0.61.3", - "windows-core 0.61.2", + "thiserror 2.0.18", + "windows 0.62.2", + "windows-core 0.62.2", ] [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "ws_stream_wasm" @@ -5567,29 +5965,17 @@ dependencies = [ "pharos", "rustc_version", "send_wrapper", - "thiserror 2.0.15", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek 4.1.3", - "rand_core 0.6.4", - "serde", - "zeroize", -] - [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmltree" @@ -5600,22 +5986,12 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -5623,13 +5999,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", "synstructure", ] @@ -5641,70 +6017,70 @@ checksum = "2164e798d9e3d84ee2c91139ace54638059a3b23e361f5c11781c2c6459bde0f" [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -5713,9 +6089,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -5724,11 +6100,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.119", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 98717c3..eada137 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,47 +7,70 @@ repository = "https://github.com/rustonbsd/iroh-lan" readme = "README.md" keywords = ["networking"] categories = ["network-programming"] -version = "0.1.2" +version = "1.0.0-pre.1" edition = "2024" [dependencies] anyhow = "1" -distributed-topic-tracker = "0.2.5" -ed25519-dalek = "3.0.0-pre.1" -iroh = "0.95.1" -iroh-gossip = "0.95.0" -iroh-docs = "0.95.0" -iroh-blobs = "0.97.0" +iroh-topic-tracker = "0.2.0" +ed25519-dalek = "3.0.0-pre.7" +iroh = { version="1.0.2", features=["qlog", "tls-ring"] } +netwatch = "0.19.1" +iroh-gossip = "0.101.0" runas = "1" tokio = "1" -nix = { version = "0.30", features = ["process"] } +#nix = { version = "0.31.3", features = ["process"] } self-runas = "0.1" rand = "0.9" pnet_packet = "0.35" -tun-rs = { version = "2.7.7", features = ["async"] } +tun-rs = { version = "2.8", features = ["async"] } serde = "1" futures = "0.3" +futures-lite = "2" postcard = { version = "1", features = ["use-std"] } sha2 = "0.10" z32 = "1" tracing = { version = "0.1", default-features = false, features = ["std"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] } +bytes = "1" +chrono = { version = "0.4" } +n0-watcher = "1.0.0" +if-addrs = "0.15" +ipnet = "2" -actor-helper = "0.2" - +iroh-auth = "0.2.0" +actor-helper = { version="0.3.0", features=["anyhow", "tokio"]} +clap = { version = "4.6", features = ["derive"] } +ratatui = "0.30.0" +crossterm = "0.29.0" +noq-proto = { git = "https://github.com/n0-computer/noq", rev = "0a445ddf828d3be8c973877d3053043998146f36" }#{ version = "1.0.1" } +url = "2" +thiserror = "1" +blake3 = "1" [lib] path = "src/lib.rs" crate-type = ["lib"] bench = false +[[bin]] +name = "iroh-lan" +path = "src/bin/main.rs" + [[example]] name = "participant" path = "examples/participant.rs" crate-type = ["bin"] -[[example]] -name = "creator" -path = "examples/creator.rs" -crate-type = ["bin"] + +[patch.crates-io] +noq-proto = { git = "https://github.com/n0-computer/noq", rev = "0a445ddf828d3be8c973877d3053043998146f36" } +noq = { git = "https://github.com/n0-computer/noq", rev = "0a445ddf828d3be8c973877d3053043998146f36" } +noq-udp = { git = "https://github.com/n0-computer/noq", rev = "0a445ddf828d3be8c973877d3053043998146f36" } + +#iroh = { path = "../iroh/iroh" } +#iroh-base = { path = "../iroh/iroh-base" } +#iroh-dns = { path = "../iroh/iroh-dns" } +#iroh-relay = { path = "../iroh/iroh-relay" } +netwatch = { path = "../net-tools/netwatch" } \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..67a2e43 --- /dev/null +++ b/Makefile @@ -0,0 +1,56 @@ +SHELL := /bin/bash + +.PHONY: build stress-test clean-test reliability-test clean-reliability + +build: + cargo build + cargo build --example tcp_client + cargo build --example tcp_server + cargo build --example game_check + cargo build --example mesh_check + +long-stress-test: build + TOPIC="test_topic_$$RANDOM"; \ + GAME_TEST_DURATION=530; \ + echo "Using TOPIC=$$TOPIC"; \ + sudo -E TOPIC=$$TOPIC docker compose -f docker_test/compose-stress.yaml up --build --abort-on-container-exit --remove-orphans + +stress-test: build + TOPIC="test_topic_$$RANDOM"; \ + echo "Using TOPIC=$$TOPIC"; \ + sudo -E WIFI_SIM_DELAY=100 TOPIC=$$TOPIC docker compose -f docker_test/compose-stress.yaml up --build --abort-on-container-exit --remove-orphans; \ + echo ""; \ + ./docker_test/check_logs.sh + +clean-test: + sudo docker compose -f docker_test/compose-stress.yaml down -v + +reliability-test: build + mkdir -p docker_test/results_reliability/node0 docker_test/results_reliability/node1 docker_test/results_reliability/node2 docker_test/results_reliability/node3 docker_test/results_reliability/node4; \ + TOPIC="reliability_$$RANDOM"; \ + RUN_ID=$$(date +%Y%m%d_%H%M%S); \ + echo "Using TOPIC=$$TOPIC"; \ + echo "Using RUN_ID=$$RUN_ID"; \ + sudo -E TOPIC=$$TOPIC RUN_ID=$$RUN_ID RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ + echo ""; \ + chmod +x ./docker_test/check_reliability_logs.sh; \ + ./docker_test/check_reliability_logs.sh + +clean-reliability: + sudo docker compose -f docker_test/compose-reliability.yaml down -v + +.PHONY: reliability-netns clean-netns + +reliability-netns: build + chmod +x netns_tests/netns_lab.sh netns_tests/reliability_test/run.sh netns_tests/reliability_test/check_logs.sh + sudo -E ./netns_tests/reliability_test/run.sh; \ + status=$$?; \ + ./netns_tests/reliability_test/check_logs.sh; \ + exit $$status + +clean-netns: + sudo ./netns_tests/netns_lab.sh teardown + +reliability-netns-archive-entrypoint: + mkdir -p netns_tests/reliability_test/archives + find netns_tests -type f -name "entrypoint.log" -print0 | xargs -0 7z a -spf netns_tests/reliability_test/archives/entrypoint_logs.7z \ No newline at end of file diff --git a/docker_test/Dockerfile b/docker_test/Dockerfile new file mode 100644 index 0000000..4f24fa8 --- /dev/null +++ b/docker_test/Dockerfile @@ -0,0 +1,16 @@ +FROM ubuntu:24.04 +RUN apt-get update && apt-get install -y \ + iproute2 \ + ethtool \ + procps \ + netcat-openbsd \ + iputils-ping \ + iperf3 \ + gdb \ + && rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY entrypoint_stress.sh /app/entrypoint_stress.sh +COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +COPY check_reliability_logs.sh /app/check_reliability_logs.sh +RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +ENTRYPOINT ["/app/entrypoint_stress.sh"] diff --git a/docker_test/check_logs.sh b/docker_test/check_logs.sh new file mode 100755 index 0000000..419d0dd --- /dev/null +++ b/docker_test/check_logs.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# docker_test/check_logs.sh + +# Find the latest server log directory (handling root ownership if needed) +LOG_DIR=$(sudo ls -td docker_test/results_stress/server/*/ 2>/dev/null | head -1) + +if [ -z "$LOG_DIR" ]; then + echo "No log directory found in docker_test/results_stress/server/" + exit 0 +fi + +LOG_FILE="$LOG_DIR/iroh.log" +echo "Analyzing logs in: $LOG_DIR" + +if sudo [ ! -f "$LOG_FILE" ]; then + echo "Log file not found: $LOG_FILE" + exit 0 +fi + +echo "========================================================" +echo " DATA/CONTROL PLANE MISMATCH ANALYSIS" +echo "========================================================" + +BLOB_MISS_COUNT=$(sudo grep -c "Pending blob sync for assignment" "$LOG_FILE") +LIVENESS_COUNT=$(sudo grep -c "Data-Plane Liveness" "$LOG_FILE") +DISCONNECT_COUNT=$(sudo grep -c "Peer disconnected" "$LOG_FILE") + +if [ "$BLOB_MISS_COUNT" -gt 0 ]; then + echo -e "\033[0;33m[!] CAUSE DETECTED:\033[0m Router skipped $BLOB_MISS_COUNT updates due to missing blobs." + echo " (This confirms the Metadata-Data race condition exists)" +else + echo -e "\033[0;32m[OK]\033[0m Router Sync: No missing blobs detected." +fi + +if [ "$LIVENESS_COUNT" -gt 0 ]; then + echo -e "\033[0;32m[SUCCESS]\033[0m PROTECTION ENGAGED: Data-Plane Liveness saved $LIVENESS_COUNT routes." + echo " (Connections were preserved despite Router/Doc temporary sync state)" +else + echo "[INFO] Protection Idle: Data-Plane Liveness logic not required this run." +fi + +if [ "$DISCONNECT_COUNT" -gt 0 ]; then + echo -e "\033[0;31m[FAIL]\033[0m Connectivity Unstable: $DISCONNECT_COUNT Disconnects detected." +else + echo -e "\033[0;32m[PASS]\033[0m Connectivity Stable: 0 Disconnects." +fi +echo "========================================================" diff --git a/docker_test/check_reliability_logs.sh b/docker_test/check_reliability_logs.sh new file mode 100755 index 0000000..d5ecd20 --- /dev/null +++ b/docker_test/check_reliability_logs.sh @@ -0,0 +1,68 @@ +#!/bin/bash +set -euo pipefail + +echo "========================================================" +echo " 5-NODE RELIABILITY TEST REPORT" +echo "========================================================" + +overall_fail=0 +phases=(baseline degraded post_rolling post_simultaneous post_outage_recovery recovery) +optional_phases=(post_outage_recovery) + +is_optional_phase() { + local phase="$1" + for optional in "${optional_phases[@]}"; do + if [ "$optional" = "$phase" ]; then + return 0 + fi + done + return 1 +} + +for node in 0 1 2 3 4; do + base="docker_test/results_reliability/node${node}" + latest=$(find "$base" -mindepth 1 -maxdepth 1 -type d -name '20[0-9][0-9][0-1][0-9][0-3][0-9]_[0-2][0-9][0-5][0-9][0-5][0-9]' -printf '%T@ %p\n' 2>/dev/null | sort -nr | head -n1 | cut -d' ' -f2- || true) + + if [ -z "$latest" ]; then + echo "[FAIL] node${node}: no timestamped log directory found" + overall_fail=1 + continue + fi + + echo "node${node}: $latest" + + for phase in "${phases[@]}"; do + log="$latest/mesh_${phase}.log" + if [ ! -f "$log" ]; then + if is_optional_phase "$phase"; then + echo " [INFO] ${phase}: missing log" + else + echo " [FAIL] ${phase}: missing log" + overall_fail=1 + fi + continue + fi + + if grep -q "MESH_CHECK: PASS" "$log"; then + echo " [PASS] ${phase}" + else + if is_optional_phase "$phase"; then + echo " [INFO] ${phase}" + else + echo " [FAIL] ${phase}" + overall_fail=1 + fi + tail -n 20 "$log" || true + fi + done + +done + +echo "========================================================" +if [ "$overall_fail" -eq 0 ]; then + echo "RELIABILITY RESULT: PASS" + exit 0 +else + echo "RELIABILITY RESULT: FAIL" + exit 1 +fi diff --git a/docker_test/compose-reliability.yaml b/docker_test/compose-reliability.yaml new file mode 100644 index 0000000..729287a --- /dev/null +++ b/docker_test/compose-reliability.yaml @@ -0,0 +1,123 @@ +services: + node0: + build: + context: . + dockerfile: Dockerfile + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + entrypoint: ["/app/entrypoint_reliability.sh"] + environment: + - NODE_INDEX=0 + - NODE_COUNT=5 + - TOPIC=${TOPIC} + - RECONNECT_MAX_SEC=${RECONNECT_MAX_SEC:-60} + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + - MESH_TICK_MS=${MESH_TICK_MS:-100} + volumes: + - ./results_reliability/node0:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + + node1: + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + entrypoint: ["/app/entrypoint_reliability.sh"] + environment: + - NODE_INDEX=1 + - NODE_COUNT=5 + - TOPIC=${TOPIC} + - RECONNECT_MAX_SEC=${RECONNECT_MAX_SEC:-60} + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + - MESH_TICK_MS=${MESH_TICK_MS:-100} + volumes: + - ./results_reliability/node1:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + + node2: + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + entrypoint: ["/app/entrypoint_reliability.sh"] + environment: + - NODE_INDEX=2 + - NODE_COUNT=5 + - TOPIC=${TOPIC} + - RECONNECT_MAX_SEC=${RECONNECT_MAX_SEC:-60} + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + - MESH_TICK_MS=${MESH_TICK_MS:-100} + volumes: + - ./results_reliability/node2:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + + node3: + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + entrypoint: ["/app/entrypoint_reliability.sh"] + environment: + - NODE_INDEX=3 + - NODE_COUNT=5 + - TOPIC=${TOPIC} + - RECONNECT_MAX_SEC=${RECONNECT_MAX_SEC:-60} + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + - MESH_TICK_MS=${MESH_TICK_MS:-100} + volumes: + - ./results_reliability/node3:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + + node4: + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + entrypoint: ["/app/entrypoint_reliability.sh"] + environment: + - NODE_INDEX=4 + - NODE_COUNT=5 + - TOPIC=${TOPIC} + - RECONNECT_MAX_SEC=${RECONNECT_MAX_SEC:-60} + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + - MESH_TICK_MS=${MESH_TICK_MS:-100} + volumes: + - ./results_reliability/node4:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + +volumes: + coord: + +networks: + testnet: + driver: bridge + ipam: + config: + - subnet: 10.60.0.0/16 diff --git a/docker_test/compose-stress.yaml b/docker_test/compose-stress.yaml new file mode 100644 index 0000000..399ac3b --- /dev/null +++ b/docker_test/compose-stress.yaml @@ -0,0 +1,59 @@ +services: + node0: + build: + context: . + dockerfile: Dockerfile + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + command: ["server"] + healthcheck: + test: ["CMD", "grep", "-q", "AssignedIp(", "/app/results/iroh.log"] + interval: 2s + timeout: 30s + retries: 60 + entrypoint: ["/app/entrypoint_stress.sh", "server"] + environment: + - GAME_TEST_DURATION=${GAME_TEST_DURATION:-1} + - TOPIC=${TOPIC} + - STRESS_VERBOSE=1 + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + volumes: + - ./results_stress/server:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + node1: + image: iroh-lan-test + cap_add: + - NET_ADMIN + - SYS_PTRACE + devices: + - /dev/net/tun:/dev/net/tun + command: ["client"] + entrypoint: ["/app/entrypoint_stress.sh", "client"] + environment: + - GAME_TEST_DURATION=${GAME_TEST_DURATION:-1} + - TOPIC=${TOPIC} + - STRESS_VERBOSE=1 + - RUST_LOG=${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info} + volumes: + - ./results_stress/client:/app/results + - ../target/debug:/app/bin + - coord:/coord + networks: + testnet: + +volumes: + coord: + +networks: + testnet: + driver: bridge + ipam: + config: + - subnet: 10.50.0.0/16 \ No newline at end of file diff --git a/docker_test/entrypoint_reliability.sh b/docker_test/entrypoint_reliability.sh new file mode 100644 index 0000000..4d5cd8b --- /dev/null +++ b/docker_test/entrypoint_reliability.sh @@ -0,0 +1,498 @@ +#!/bin/bash +set -e +set -o pipefail + +RESULTS_DIR="/app/results" +RUN_ID="${RUN_ID:-$(date +%Y%m%d_%H%M%S)}" +LOG_DIR="$RESULTS_DIR/$RUN_ID" +QLOG_DIR="$LOG_DIR/qlog.log" +COORD_DIR="/coord" +mkdir -p "$LOG_DIR" "$QLOG_DIR" "$COORD_DIR" + +NODE_INDEX="${NODE_INDEX:-0}" +NODE_COUNT="${NODE_COUNT:-5}" +EXPECTED_PEERS="${EXPECTED_PEERS:-4}" +TOPIC="${TOPIC:-test_topic_default}" +RECONNECT_MAX_SEC="${RECONNECT_MAX_SEC:-60}" +MESH_TICK_MS="${MESH_TICK_MS:-100}" + +BASELINE_SEC="${BASELINE_SEC:-35}" +DEGRADED_SEC="${DEGRADED_SEC:-40}" +POST_ROLLING_SEC="${POST_ROLLING_SEC:-45}" +POST_SIM_SEC="${POST_SIM_SEC:-45}" +RECOVERY_SEC="${RECOVERY_SEC:-35}" +POST_OUTAGE_RECOVERY_SEC="${POST_OUTAGE_RECOVERY_SEC:-45}" + +ROLLING_SLOT_SEC="${ROLLING_SLOT_SEC:-10}" +SIM_JITTER_MAX_SEC="${SIM_JITTER_MAX_SEC:-5}" +OUTAGE_SEC="${OUTAGE_SEC:-25}" +OUTAGE_RECOVERY_MAX_SEC="${OUTAGE_RECOVERY_MAX_SEC:-30}" + + +IROH_PID="" +MY_IP="" +TUN_DEV="" +LOGS_COLLECTED=0 + +# echo the mesh_check durations and max_reconnect to make sure they make sense +echo "Mesh phase durations and settings:" +echo " baseline: ${BASELINE_SEC}s" +echo " degraded: ${DEGRADED_SEC}s (with netem profile)" +echo " post_rolling: ${POST_ROLLING_SEC}s (with netem profile)" +echo " post_simultaneous: ${POST_SIM_SEC}s (with netem profile)" +echo " post_outage_recovery: ${POST_OUTAGE_RECOVERY_SEC}s (nonfatal, with clean netem profile)" +echo " recovery: ${RECOVERY_SEC}s (with clean netem profile)" +echo " max_reconnect: ${RECONNECT_MAX_SEC}s" +echo " rolling_slot_sec: ${ROLLING_SLOT_SEC}s" +echo " sim_jitter_max_sec: ${SIM_JITTER_MAX_SEC}s" +echo " outage_sec: ${OUTAGE_SEC}s" +echo " outage_recovery_max_sec: ${OUTAGE_RECOVERY_MAX_SEC}s" +echo " netem profile for degraded/rolling/simultaneous phases: delay ${NETEM_DELAY_MS}ms ±${NETEM_JITTER_MS}ms, loss ${NETEM_LOSS_PCT}%, reorder ${NETEM_REORDER_PCT}% with gap ${NETEM_REORDER_GAP}, duplicate ${NETEM_DUP_PCT}%" +echo "" + + +#tc qdisc add dev eth0 root netem delay 300ms 100ms distribution normal loss 1.5% 2.5% reorder 0.5% 5% duplicate 0.1% corrupt 0.01% rate 10mbit +#tc qdisc replace dev eth0 root netem delay 1200ms 400ms reorder 35% 50% loss 35% 10% rate 6mbit limit 4000 + +collect_logs() { + local exit_code="${1:-$?}" + + if [ "$LOGS_COLLECTED" -eq 1 ]; then + return + fi + LOGS_COLLECTED=1 + + sync "$LOG_DIR" 2>/dev/null || true + echo "[node${NODE_INDEX}] Saved logs to $LOG_DIR (exit=$exit_code)" +} + +finalize_and_exit() { + local exit_code="$1" + + trap - EXIT TERM INT + + stop_iroh + tc qdisc del dev eth0 root 2>/dev/null || true + collect_logs "$exit_code" + + exit "$exit_code" +} + +handle_term() { + local exit_code=143 + + if [ -f "$COORD_DIR/TEST_PASS" ]; then + exit_code=0 + fi + + echo "[node${NODE_INDEX}] received SIGTERM" + finalize_and_exit "$exit_code" +} + +handle_int() { + echo "[node${NODE_INDEX}] received SIGINT" + finalize_and_exit 130 +} + +handle_exit() { + local exit_code=$? + + trap - EXIT + collect_logs "$exit_code" + exit "$exit_code" +} + +trap handle_exit EXIT +trap handle_term TERM +trap handle_int INT + +signal() { + local name="$1" + touch "$COORD_DIR/$name" + echo "[node${NODE_INDEX}] signal: $name" +} + +wait_signal() { + local name="$1" + local timeout_sec="${2:-300}" + local start + start=$(date +%s) + + echo "[node${NODE_INDEX}] waiting for $name (${timeout_sec}s)" + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + if [ -f "$COORD_DIR/$name" ]; then + return 0 + fi + if [ -f "$COORD_DIR/FAIL" ]; then + echo "[node${NODE_INDEX}] observed global FAIL" + exit 1 + fi + sleep 0.5 + done + + echo "[node${NODE_INDEX}] timeout waiting for $name" + signal "FAIL" + touch "$COORD_DIR/FAIL" + exit 1 +} + +wait_all_signals() { + local prefix="$1" + local timeout_sec="${2:-300}" + local start + start=$(date +%s) + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + local count + count=$(ls "$COORD_DIR"/${prefix}_* 2>/dev/null | wc -l || true) + if [ "$count" -ge "$NODE_COUNT" ]; then + return 0 + fi + if [ -f "$COORD_DIR/FAIL" ]; then + echo "[node${NODE_INDEX}] observed global FAIL" + exit 1 + fi + sleep 0.5 + done + + echo "[node${NODE_INDEX}] timeout waiting for all ${prefix}_* signals" + touch "$COORD_DIR/FAIL" + exit 1 +} + +start_iroh() { + local logfile="$1" + > "$logfile" + echo "Backtrace will be logged to $logfile" + export RUST_BACKTRACE=full + /app/bin/iroh-lan "$TOPIC" -t --qlog-dir "$QLOG_DIR" >> "$logfile" 2>&1 & + IROH_PID=$! + echo "[node${NODE_INDEX}] started iroh pid=$IROH_PID log=$logfile" +} + +stop_iroh() { + if [ -n "$IROH_PID" ]; then + kill "$IROH_PID" 2>/dev/null || true + wait "$IROH_PID" 2>/dev/null || true + IROH_PID="" + fi +} + +wait_assigned_ip() { + local logfile="$1" + local timeout_sec="${2:-180}" + local start + start=$(date +%s) + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + local ip + ip=$(grep "My IP is " "$logfile" 2>/dev/null | tail -n1 | sed -n 's/My IP is \([0-9.]*\).*/\1/p' || true) + if [ -n "$ip" ]; then + MY_IP="$ip" + echo "[node${NODE_INDEX}] My IP=$MY_IP" + break + fi + sleep 1 + done + + if [ -z "$MY_IP" ]; then + echo "[node${NODE_INDEX}] timeout waiting My IP" + touch "$COORD_DIR/FAIL" + exit 1 + fi + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + local count + count=$(grep "Peer connected:" "$logfile" 2>/dev/null | grep -v "Peer connected: $MY_IP " | sed -n 's/Peer connected: \([0-9.]*\).*/\1/p' | sort -u | wc -l || true) + if [ "$count" -ge "$EXPECTED_PEERS" ]; then + echo "[node${NODE_INDEX}] Peer connected count=$count" + return 0 + fi + sleep 1 + done + + echo "[node${NODE_INDEX}] timeout waiting Peer connected (expected $EXPECTED_PEERS)" + touch "$COORD_DIR/FAIL" + exit 1 +} + +wait_tun_for_ip() { + local timeout_sec="${1:-120}" + local start + start=$(date +%s) + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + TUN_DEV=$(ip -o -4 addr show | awk -v ip="$MY_IP" '$4 ~ ip"/" {print $2; exit}') + if [ -n "$TUN_DEV" ]; then + echo "[node${NODE_INDEX}] TUN_DEV=$TUN_DEV" + return 0 + fi + sleep 0.5 + done + + echo "[node${NODE_INDEX}] timeout waiting TUN for $MY_IP" + ip -o -4 addr show || true + touch "$COORD_DIR/FAIL" + exit 1 +} + +rebuild_peers_list() { + local out="$COORD_DIR/peers.list" + ls "$COORD_DIR"/node*.ip 2>/dev/null | sort | while read -r f; do cat "$f"; done | sed '/^$/d' | sort -u > "$out" || true + echo "[node${NODE_INDEX}] peers.list=$(tr '\n' ',' < "$out")" +} + +get_peers_csv() { + if [ ! -f "$COORD_DIR/peers.list" ]; then + echo "" + return + fi + grep -v "^$MY_IP$" "$COORD_DIR/peers.list" | paste -sd, - || true +} + +#NETEM_DELAY_MS=600 +#NETEM_JITTER_MS=200 +#NETEM_LOSS="gemodel 5% 15% 100% 0%" +#NETEM_RATE="128kbit" +#NETEM_REORDER_PCT=8 +#NETEM_REORDER_CORR=50 +#NETEM_DUP_PCT=3 +#NETEM_CORRUPT_PCT=0.5 +#NETEM_SLOT="100ms 500ms" + + + +apply_netem_profile() { + local profile="$1" + + tc qdisc del dev eth0 root 2>/dev/null || true + + case "$profile" in + clean) + echo "[node${NODE_INDEX}] netem clean" + ;; + degraded) + echo "[node${NODE_INDEX}] netem degraded on eth0" + + # Build the tc command piecewise so each feature + # can be independently toggled via empty vars + local cmd="tc qdisc add dev eth0 root netem delay 450ms 80ms distribution normal loss gemodel 1.6% 30% 100% 0% reorder 7% duplicate 3% corrupt 0.1% rate 384kbit" + + echo "[node${NODE_INDEX}] $cmd" + eval "$cmd" + ;; + blackhole) + echo "[node${NODE_INDEX}] netem blackhole on eth0 (loss 100%)" + tc qdisc add dev eth0 root netem loss 100% + ;; + *) + echo "[node${NODE_INDEX}] unknown profile '$profile'" + touch "$COORD_DIR/FAIL" + exit 1 + ;; + esac +} + +run_outage_cycle() { + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/outage_start" "$COORD_DIR/outage_end" "$COORD_DIR/outage_restored" "$COORD_DIR/outage_done_"* 2>/dev/null || true + signal "outage_start" + fi + + wait_signal "outage_start" 300 + + apply_netem_profile "blackhole" + echo "[node${NODE_INDEX}] outage hold for ${OUTAGE_SEC}s" + sleep "$OUTAGE_SEC" + + tc qdisc del dev eth0 root 2>/dev/null || true + echo "[node${NODE_INDEX}] outage restored (netem removed)" + signal "outage_done_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "outage_done" 300 + signal "outage_restored" + fi + + wait_signal "outage_restored" 300 +} + +run_mesh_phase() { + local phase="$1" + local duration_sec="$2" + local max_reconnect_sec="$3" + local netem_profile="$4" + + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/${phase}_start" "$COORD_DIR/${phase}_complete" "$COORD_DIR/${phase}_done_"* 2>/dev/null || true + signal "${phase}_start" + fi + + wait_signal "${phase}_start" 300 + + apply_netem_profile "$netem_profile" + local peers_csv + peers_csv=$(get_peers_csv) + + if [ -z "$peers_csv" ]; then + echo "[node${NODE_INDEX}] no peers found for phase $phase" + touch "$COORD_DIR/FAIL" + exit 1 + fi + + echo "[node${NODE_INDEX}] phase=$phase peers=$peers_csv" + /app/bin/examples/mesh_check \ + "0.0.0.0:31000" \ + "$MY_IP" \ + "$peers_csv" \ + "$duration_sec" \ + "$max_reconnect_sec" \ + "$MESH_TICK_MS" 2>&1 | tee -a "$LOG_DIR/mesh_${phase}.log" + + signal "${phase}_done_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "${phase}_done" 600 + signal "${phase}_complete" + fi + + wait_signal "${phase}_complete" 600 +} + +run_mesh_phase_nonfatal() { + local phase="$1" + local duration_sec="$2" + local max_reconnect_sec="$3" + local netem_profile="$4" + + set +e + run_mesh_phase "$phase" "$duration_sec" "$max_reconnect_sec" "$netem_profile" + local status=$? + set -e + + if [ "$status" -ne 0 ]; then + echo "[node${NODE_INDEX}] nonfatal mesh phase failed: $phase (exit=$status)" + fi + + return 0 +} + +rolling_restart() { + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/rolling_go" "$COORD_DIR/rolling_all_stopped" "$COORD_DIR/rolling_done" "$COORD_DIR/stopped_"* "$COORD_DIR/restarted_"* 2>/dev/null || true + signal "rolling_go" + fi + + wait_signal "rolling_go" 120 + + local slot=$(( NODE_INDEX * ROLLING_SLOT_SEC )) + sleep "$slot" + + stop_iroh + signal "stopped_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "stopped" 600 + signal "rolling_all_stopped" + fi + + wait_signal "rolling_all_stopped" 600 + + start_iroh "$LOG_DIR/iroh_after_rolling.log" + wait_assigned_ip "$LOG_DIR/iroh_after_rolling.log" 180 + wait_tun_for_ip 120 + echo "$MY_IP" > "$COORD_DIR/node${NODE_INDEX}.ip" + + signal "restarted_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "restarted" 600 + rebuild_peers_list + signal "rolling_done" + fi + + wait_signal "rolling_done" 600 +} + +simultaneous_restart() { + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/sim_go" "$COORD_DIR/sim_all_stopped" "$COORD_DIR/sim_done" "$COORD_DIR/sim_stopped_"* "$COORD_DIR/sim_restarted_"* 2>/dev/null || true + signal "sim_go" + fi + + wait_signal "sim_go" 120 + + local jitter=$(( RANDOM % (SIM_JITTER_MAX_SEC + 1) )) + sleep "$jitter" + + stop_iroh + signal "sim_stopped_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "sim_stopped" 600 + signal "sim_all_stopped" + fi + + wait_signal "sim_all_stopped" 600 + + start_iroh "$LOG_DIR/iroh_after_sim.log" + wait_assigned_ip "$LOG_DIR/iroh_after_sim.log" 180 + wait_tun_for_ip 120 + echo "$MY_IP" > "$COORD_DIR/node${NODE_INDEX}.ip" + + signal "sim_restarted_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "sim_restarted" 600 + rebuild_peers_list + signal "sim_done" + fi + + wait_signal "sim_done" 600 +} + +if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR"/* 2>/dev/null || true +fi +sleep 1 + +start_iroh "$LOG_DIR/iroh.log" +wait_assigned_ip "$LOG_DIR/iroh.log" 180 +wait_tun_for_ip 120 + +echo "$MY_IP" > "$COORD_DIR/node${NODE_INDEX}.ip" +signal "ready_${NODE_INDEX}" + +if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "ready" 300 + rebuild_peers_list + signal "all_ready" +fi + +wait_signal "all_ready" 300 + +run_mesh_phase "baseline" "$BASELINE_SEC" "$RECONNECT_MAX_SEC" "clean" +run_mesh_phase "degraded" "$DEGRADED_SEC" "$RECONNECT_MAX_SEC" "degraded" + +rolling_restart +run_mesh_phase "post_rolling" "$POST_ROLLING_SEC" "$RECONNECT_MAX_SEC" "degraded" + +simultaneous_restart +run_mesh_phase "post_simultaneous" "$POST_SIM_SEC" "$RECONNECT_MAX_SEC" "degraded" + +# Extra chaos step: force hard outage (no recovery possible), then restore and verify recovery +run_outage_cycle +run_mesh_phase_nonfatal "post_outage_recovery" "$POST_OUTAGE_RECOVERY_SEC" "$OUTAGE_RECOVERY_MAX_SEC" "clean" + +run_mesh_phase "recovery" "$RECOVERY_SEC" "$RECONNECT_MAX_SEC" "clean" + +if [ "$NODE_INDEX" = "0" ]; then + signal "TEST_PASS" +fi + +wait_signal "TEST_PASS" 120 + +stop_iroh + +echo "[node${NODE_INDEX}] reliability test complete" +exit 0 diff --git a/docker_test/entrypoint_stress.sh b/docker_test/entrypoint_stress.sh new file mode 100755 index 0000000..68ea234 --- /dev/null +++ b/docker_test/entrypoint_stress.sh @@ -0,0 +1,281 @@ +#!/bin/bash +set -e +set -o pipefail + +LOG_DIR="/app/results" +COORD_DIR="/coord" +mkdir -p "$LOG_DIR" + +collect_logs() { + local exit_code=$? + local ts + ts=$(date +%Y%m%d_%H%M%S) + local out_dir="$LOG_DIR/$ts" + mkdir -p "$out_dir" + + for f in "$LOG_DIR/iroh.log" "$LOG_DIR/iroh_2.log" "$LOG_DIR/game_server.log"; do + if [ -f "$f" ]; then + cp -f "$f" "$out_dir/" + fi + done + + if [ -f "$LOG_DIR/game_client.log" ]; then + cp -f "$LOG_DIR/game_client.log" "$out_dir/" + fi + + rm -f "$COORD_DIR"/* 2>/dev/null || true + echo "Saved logs to $out_dir (exit code: $exit_code)" +} + +trap collect_logs EXIT + +GAME_TEST_DURATION=${GAME_TEST_DURATION:-10} + +NETEM_DELAY_MS=${NETEM_DELAY_MS:-200} +NETEM_JITTER_MS=${NETEM_JITTER_MS:-50} +NETEM_LOSS_PCT=${NETEM_LOSS_PCT:-5} +NETEM_REORDER_PCT=${NETEM_REORDER_PCT:-2} +NETEM_REORDER_GAP=${NETEM_REORDER_GAP:-1} +ENABLE_IPERF_NETEM=${ENABLE_IPERF_NETEM:-1} + +GAME_NETEM_DELAY_MS=${GAME_NETEM_DELAY_MS:-120} +GAME_NETEM_JITTER_MS=${GAME_NETEM_JITTER_MS:-40} +GAME_NETEM_LOSS_PCT=${GAME_NETEM_LOSS_PCT:-2} +GAME_NETEM_REORDER_PCT=${GAME_NETEM_REORDER_PCT:-5} +GAME_NETEM_REORDER_GAP=${GAME_NETEM_REORDER_GAP:-25} +TOPIC="${TOPIC:-test_topic_default}" + +tc qdisc add dev eth0 root netem delay 300ms 100ms distribution normal loss 15% 25% reorder 5% 50% duplicate 1% corrupt 0.1% rate 1mbit +#tc qdisc add dev eth0 root netem delay 200ms 50ms loss 2% + +signal_ready() { + local signal_name="$1" + touch "$COORD_DIR/$signal_name" + echo "[COORD] Signaled: $signal_name" +} + +wait_for_signal() { + local signal_name="$1" + local timeout_sec="${2:-120}" + local start_time + start_time=$(date +%s) + + echo "[COORD] Waiting for signal: $signal_name (timeout: ${timeout_sec}s)" + while [ $(( $(date +%s) - start_time )) -lt $timeout_sec ]; do + if [ -f "$COORD_DIR/$signal_name" ]; then + echo "[COORD] Received signal: $signal_name" + return 0 + fi + sleep 0.5 + done + + echo "[COORD] TIMEOUT waiting for: $signal_name" + return 1 +} + +run_iperf_once() { + local host="$1" + iperf3 -c "$host" -t 60 -l 4000 --connect-timeout 30000 +} + +clear_signal() { + local signal_name="$1" + rm -f "$COORD_DIR/$signal_name" +} + +echo "Starting iroh-lan..." +if [ "${STRESS_VERBOSE:-}" = "1" ]; then + export RUST_LOG="${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info}" + export RUST_BACKTRACE="${RUST_BACKTRACE:-1}" +else + export RUST_LOG="${RUST_LOG:-info}" +fi + +rm -f "$COORD_DIR"/* 2>/dev/null || true + +: > "$LOG_DIR/iroh.log" +/app/bin/iroh-lan "$TOPIC" -t >> "$LOG_DIR/iroh.log" 2>&1 & +IROH_PID=$! + +echo "Waiting for IP assignment (AssignedIp)..." +TIMEOUT=120 +start_time=$(date +%s) + +GOT_IP="" +while [ $(( $(date +%s) - start_time )) -lt $TIMEOUT ]; do + if grep -q "AssignedIp(" "$LOG_DIR/iroh.log"; then + GOT_IP=$(grep "AssignedIp(" "$LOG_DIR/iroh.log" | tail -n1 | sed -n 's/.*AssignedIp(\([0-9.]*\)).*/\1/p') + break + fi + sleep 1 +done + +if [ -z "$GOT_IP" ]; then + echo "Timeout waiting for AssignedIp." + cat "$LOG_DIR/iroh.log" + exit 1 +fi + +echo "Assigned IP: $GOT_IP" +if [ "$GOT_IP" == "172.30.0.2" ]; then + ROLE="server" + PEER_IP="172.30.0.3" + echo "I am the SERVER (since I got .2)" +elif [ "$GOT_IP" == "172.30.0.3" ]; then + ROLE="client" + PEER_IP="172.30.0.2" + echo "I am the CLIENT (since I got .3)" +else + echo "Error: Unexpected IP $GOT_IP" + exit 1 +fi + +echo "Waiting for interface with IP $GOT_IP..." +TUN_WAIT_START=$(date +%s) +TUN_WAIT_TIMEOUT=120 +TUN_DEV="" +TUN_LOGGED=0 +while [ $(( $(date +%s) - TUN_WAIT_START )) -lt $TUN_WAIT_TIMEOUT ]; do + if grep -q "TunActor started for IP: $GOT_IP" "$LOG_DIR/iroh.log"; then + TUN_LOGGED=1 + fi + TUN_DEV=$(ip -o -4 addr show | awk -v ip="$GOT_IP" '$4 ~ ip"/" {print $2; exit}') + if [ -n "$TUN_DEV" ]; then + break + fi + if [ "$TUN_LOGGED" -eq 1 ]; then + TUN_DEV=$(ip -o link show type tun | awk -F': ' 'NR==1{print $2; exit}') + if [ -n "$TUN_DEV" ]; then + break + fi + fi + sleep 0.5 +done + +if [ -z "$TUN_DEV" ]; then + echo "Timeout waiting for interface with IP $GOT_IP." + echo "Last 200 lines of iroh.log:" + tail -n 200 "$LOG_DIR/iroh.log" || true + ip -o -4 addr show || true + exit 1 +fi + +tc qdisc del dev eth0 root 2>/dev/null || true +NETEM_DEV="${NETEM_DEV:-$TUN_DEV}" +echo "Using network device: $NETEM_DEV for netem" + +if [ "$ROLE" == "server" ]; then + echo "Starting Game Check Server..." + /app/bin/examples/game_check server "0.0.0.0:30000" "none" "$GAME_TEST_DURATION" 2>&1 | tee -a "$LOG_DIR/game_server.log" & + GAME_SERVER_PID=$! + + echo "Starting iperf3 server (persistent)..." + iperf3 -s --idle-timeout 60 2>&1 | sed 's/^/[iperf3] /' & + IPERF_PID=$! + for i in {1..40}; do + if ss -ltn | awk '{print $4}' | grep -q ":5201$"; then + signal_ready "iperf_ready" + break + fi + sleep 0.5 + done + + signal_ready "server_ready" + + wait_for_signal "tests_complete" 45000 # 12.5 hour timeout for long game test + + echo "Tests complete, shutting down..." + kill $IPERF_PID 2>/dev/null || true + kill $GAME_SERVER_PID 2>/dev/null || true + kill $IROH_PID 2>/dev/null || true + + echo "SERVER DONE." + exit 0 + +elif [ "$ROLE" == "client" ]; then + + wait_for_signal "server_ready" 120 + + echo "TEST 1/5: Broadcast Hostility Test" + ping -b -i 0.2 -c 100 255.255.255.255 > /dev/null 2>&1 & + PING_PID=$! + + echo "TEST 2/5: Throughput (clean network) 120s" + tc qdisc del dev eth0 root 2>/dev/null || true + run_iperf_once "$PEER_IP" + + echo "TEST 3/5: Throughput (degraded network) 120s" + if [ "$ENABLE_IPERF_NETEM" = "1" ]; then + tc qdisc add dev "$NETEM_DEV" root netem \ + delay ${NETEM_DELAY_MS}ms ${NETEM_JITTER_MS}ms distribution normal \ + loss ${NETEM_LOSS_PCT}% \ + reorder ${NETEM_REORDER_PCT}% ${NETEM_REORDER_GAP} + sleep 1 + fi + + run_iperf_once "$PEER_IP" + + tc qdisc del dev "$NETEM_DEV" root 2>/dev/null || true + tc qdisc add dev eth0 root netem delay 300ms 100ms distribution normal loss 15% 25% reorder 5% 50% duplicate 1% corrupt 0.1% rate 1mbit + + echo "TEST 4/5: Reconnection Event" + echo "Killing iroh-lan..." + kill $IROH_PID 2>/dev/null || true + wait $IROH_PID 2>/dev/null || true + sleep 2 + + echo "Restarting iroh-lan..." + : > "$LOG_DIR/iroh_2.log" + /app/bin/iroh-lan "$TOPIC" -t >> "$LOG_DIR/iroh_2.log" 2>&1 & + IROH_PID_2=$! + + echo "Waiting for new IP assignment..." + NEW_IP="" + TIMEOUT=120 + for i in $(seq 1 $TIMEOUT); do + if grep -q "My IP is" "$LOG_DIR/iroh_2.log"; then + NEW_IP=$(grep "My IP is" "$LOG_DIR/iroh_2.log" | tail -n1 | awk '{print $NF}') + echo "New IP: $NEW_IP" + break + fi + sleep 1 + done + + if [ -z "$NEW_IP" ]; then + echo "Failed to get new IP after restart." + cat "$LOG_DIR/iroh_2.log" + exit 1 + fi + + echo "Waiting for tun device after reconnection..." + for i in $(seq 1 $TIMEOUT); do + if ls /sys/class/net/ | grep -q tun; then + TUN_DEV=$(ls /sys/class/net/ | grep '^tun' | head -n1) + NETEM_DEV="$TUN_DEV" + break + fi + sleep 1 + done + + echo "TEST 5/5: Game simulation (${GAME_TEST_DURATION}m)" + echo "Network: ${GAME_NETEM_DELAY_MS}ms delay, ${GAME_NETEM_LOSS_PCT}% loss" + + echo "Running game client..." + /app/bin/examples/game_check client "0.0.0.0:0" "$PEER_IP:30000" "$GAME_TEST_DURATION" 2>&1 | tee -a "$LOG_DIR/game_client.log" + GAME_EXIT=${PIPESTATUS[0]} + + tc qdisc del dev "$NETEM_DEV" root 2>/dev/null || true + + kill $PING_PID 2>/dev/null || true + kill $IROH_PID_2 2>/dev/null || true + + signal_ready "tests_complete" + + if [ $GAME_EXIT -eq 0 ]; then + echo "ALL STRESS TESTS PASSED" + exit 0 + else + echo "GAME SIMULATION FAILED." + exit 1 + fi +fi diff --git a/docker_test/test_results_con20_read8.log b/docker_test/test_results_con20_read8.log new file mode 100644 index 0000000..0f61d94 --- /dev/null +++ b/docker_test/test_results_con20_read8.log @@ -0,0 +1,2795 @@ +--- Run #1 --- +cargo build + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.66s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.38s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.37s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.41s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.40s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_29320 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.7s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [3/7] WORKDIR /app +#7 CACHED + +#8 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#8 CACHED + +#9 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#9 CACHED + +#10 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#10 CACHED + +#11 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node1-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node2-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node4-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node1-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node0-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node2-1 Starting +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.2 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.4 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node2-1 | [node2] waiting for baseline_start (300s) +node1-1 | [node1] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] netem clean +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] waiting for baseline_start (300s) +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=142 first_rx_delay_s=0.90 max_gap_s=22.21 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=211 first_rx_delay_s=0.91 max_gap_s=11.44 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=340 first_rx_delay_s=1.07 max_gap_s=1.36 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=303 first_rx_delay_s=6.73 max_gap_s=6.29 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=266 first_rx_delay_s=0.48 max_gap_s=10.69 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=2.23 max_gap_s=0.62 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=347 first_rx_delay_s=0.48 max_gap_s=0.34 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=351 first_rx_delay_s=3.26 max_gap_s=3.91 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=279 first_rx_delay_s=8.30 max_gap_s=0.43 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.46 max_gap_s=1.04 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=303 first_rx_delay_s=6.85 max_gap_s=0.32 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=4.08 max_gap_s=0.98 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=283 first_rx_delay_s=8.79 max_gap_s=1.06 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.45 max_gap_s=1.18 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.46 max_gap_s=1.26 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.23 max_gap_s=1.26 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=166 first_rx_delay_s=0.44 max_gap_s=11.18 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.32 max_gap_s=1.18 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=337 first_rx_delay_s=0.45 max_gap_s=1.07 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=93 first_rx_delay_s=0.00 max_gap_s=11.42 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=394 first_rx_delay_s=1.25 max_gap_s=2.55 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=137 first_rx_delay_s=0.03 max_gap_s=11.09 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=384 first_rx_delay_s=0.05 max_gap_s=6.26 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=379 first_rx_delay_s=0.04 max_gap_s=0.89 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=311 first_rx_delay_s=0.60 max_gap_s=9.00 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=381 first_rx_delay_s=0.60 max_gap_s=1.11 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=390 first_rx_delay_s=0.24 max_gap_s=6.37 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=384 first_rx_delay_s=0.64 max_gap_s=0.96 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=383 first_rx_delay_s=0.58 max_gap_s=0.97 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=378 first_rx_delay_s=0.62 max_gap_s=1.05 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=391 first_rx_delay_s=0.23 max_gap_s=2.62 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=384 first_rx_delay_s=0.47 max_gap_s=1.10 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=387 first_rx_delay_s=0.49 max_gap_s=1.00 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=384 first_rx_delay_s=0.59 max_gap_s=0.43 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=0.60 max_gap_s=0.41 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=396 first_rx_delay_s=0.32 max_gap_s=1.25 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] waiting for degraded_complete (600s) +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=374 first_rx_delay_s=0.60 max_gap_s=0.95 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=308 first_rx_delay_s=1.42 max_gap_s=11.28 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=301 first_rx_delay_s=10.69 max_gap_s=0.47 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=381 first_rx_delay_s=0.76 max_gap_s=1.13 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node2-1 | [node2] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=748 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=320 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=354 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=386 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=268 log=/app/results/iroh_after_rolling.log +node0-1 | [node0] AssignedIp=172.30.0.3 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=415 first_rx_delay_s=1.07 max_gap_s=3.44 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=367 first_rx_delay_s=9.33 max_gap_s=0.98 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=420 first_rx_delay_s=1.13 max_gap_s=2.37 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=417 first_rx_delay_s=0.52 max_gap_s=1.20 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=347 first_rx_delay_s=1.22 max_gap_s=10.22 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=357 first_rx_delay_s=1.09 max_gap_s=0.68 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=421 first_rx_delay_s=1.16 max_gap_s=0.62 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=331 first_rx_delay_s=0.59 max_gap_s=5.04 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=425 first_rx_delay_s=0.82 max_gap_s=1.30 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=369 first_rx_delay_s=9.23 max_gap_s=0.96 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=243 first_rx_delay_s=20.12 max_gap_s=0.40 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=414 first_rx_delay_s=1.16 max_gap_s=1.06 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=264 first_rx_delay_s=0.70 max_gap_s=11.42 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=395 first_rx_delay_s=0.79 max_gap_s=7.22 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=369 first_rx_delay_s=0.21 max_gap_s=4.00 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=240 first_rx_delay_s=0.41 max_gap_s=11.17 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=179 first_rx_delay_s=9.29 max_gap_s=10.22 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=426 first_rx_delay_s=0.15 max_gap_s=1.25 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=437 first_rx_delay_s=0.48 max_gap_s=6.50 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=432 first_rx_delay_s=0.34 max_gap_s=1.26 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1084 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=604 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=632 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=536 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=586 log=/app/results/iroh_after_sim.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=180 first_rx_delay_s=0.94 max_gap_s=11.29 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=298 first_rx_delay_s=7.31 max_gap_s=11.46 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=432 first_rx_delay_s=3.19 max_gap_s=1.16 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=392 first_rx_delay_s=6.35 max_gap_s=3.43 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=414 first_rx_delay_s=0.95 max_gap_s=3.44 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=183 first_rx_delay_s=8.27 max_gap_s=11.46 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=428 first_rx_delay_s=0.98 max_gap_s=0.54 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=421 first_rx_delay_s=0.64 max_gap_s=2.51 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=333 first_rx_delay_s=0.56 max_gap_s=11.20 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=2.81 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=376 first_rx_delay_s=13.96 max_gap_s=1.03 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=428 first_rx_delay_s=0.63 max_gap_s=1.31 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=437 first_rx_delay_s=0.17 max_gap_s=1.24 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=437 first_rx_delay_s=0.23 max_gap_s=7.37 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=433 first_rx_delay_s=0.54 max_gap_s=2.33 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=430 first_rx_delay_s=0.53 max_gap_s=1.29 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.48 max_gap_s=1.23 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=285 first_rx_delay_s=11.12 max_gap_s=11.73 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=426 first_rx_delay_s=0.57 max_gap_s=1.33 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=382 first_rx_delay_s=7.62 max_gap_s=2.53 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=352 first_rx_delay_s=0.82 max_gap_s=11.05 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=443 first_rx_delay_s=0.65 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=441 first_rx_delay_s=0.98 max_gap_s=2.34 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.95 max_gap_s=0.92 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.10 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=445 first_rx_delay_s=0.61 max_gap_s=0.35 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.23 max_gap_s=1.15 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.54 max_gap_s=1.01 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.49 max_gap_s=1.11 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.56 max_gap_s=1.20 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.05 max_gap_s=1.11 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.46 max_gap_s=0.92 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=360 first_rx_delay_s=0.18 max_gap_s=11.76 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.30 max_gap_s=0.32 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=448 first_rx_delay_s=0.45 max_gap_s=1.19 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=355 first_rx_delay_s=0.44 max_gap_s=13.61 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=343 first_rx_delay_s=0.48 max_gap_s=9.66 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=448 first_rx_delay_s=0.15 max_gap_s=6.23 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.28 max_gap_s=1.02 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=448 first_rx_delay_s=0.43 max_gap_s=1.23 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.05 max_gap_s=1.15 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.08 max_gap_s=0.96 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.14 max_gap_s=0.98 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.10 max_gap_s=1.21 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.00 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.40 max_gap_s=0.44 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.01 max_gap_s=0.52 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=138 first_rx_delay_s=0.50 max_gap_s=11.27 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=347 first_rx_delay_s=0.87 max_gap_s=1.29 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=347 first_rx_delay_s=0.36 max_gap_s=0.98 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.06 max_gap_s=0.34 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.48 max_gap_s=0.99 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=203 first_rx_delay_s=0.42 max_gap_s=11.74 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.00 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=275 first_rx_delay_s=0.30 max_gap_s=5.32 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.42 max_gap_s=1.10 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=348 first_rx_delay_s=0.02 max_gap_s=8.68 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=349 first_rx_delay_s=0.28 max_gap_s=1.08 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.00 max_gap_s=1.22 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.28 max_gap_s=0.31 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260320_001959 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node4-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node0-1 Stopped +node2-1 | [node2] Saved logs to /app/results/20260320_001959 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260320_001959 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260320_001959 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260320_001959 (exit=0) + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_001959/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_001959/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_001959/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_001959/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_001959/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #2 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.24s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_7697 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#7 CACHED + +#8 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#8 CACHED + +#9 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#9 CACHED + +#10 [3/7] WORKDIR /app +#10 CACHED + +#11 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node0-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node0-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node3-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node0-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node4-1 Starting +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node1-1 | [node1] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node1-1 | [node1] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] waiting for baseline_start (300s) +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=340 first_rx_delay_s=0.97 max_gap_s=6.98 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=203 first_rx_delay_s=0.89 max_gap_s=10.99 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=99 first_rx_delay_s=0.96 max_gap_s=15.53 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=342 first_rx_delay_s=1.05 max_gap_s=2.22 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.42 max_gap_s=1.23 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=216 first_rx_delay_s=7.88 max_gap_s=5.34 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=328 first_rx_delay_s=4.81 max_gap_s=1.26 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.28 max_gap_s=0.34 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.52 max_gap_s=6.42 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=225 first_rx_delay_s=5.95 max_gap_s=13.56 +node3-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.52 max_gap_s=0.87 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=178 first_rx_delay_s=0.53 max_gap_s=0.65 +node1-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node1-1 | [node1] signal: baseline_done_1 +node3-1 | [node3] waiting for baseline_complete (600s) +node1-1 | [node1] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=116 first_rx_delay_s=0.11 max_gap_s=11.25 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=264 first_rx_delay_s=10.80 max_gap_s=5.82 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.42 max_gap_s=1.23 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=326 first_rx_delay_s=4.37 max_gap_s=6.28 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=193 first_rx_delay_s=0.40 max_gap_s=11.20 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=143 first_rx_delay_s=0.04 max_gap_s=10.88 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.48 max_gap_s=1.28 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=183 first_rx_delay_s=0.40 max_gap_s=0.35 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node1-1 | [node1] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node1-1 | [node1] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node2-1 | [node2] waiting for degraded_start (300s) +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=384 first_rx_delay_s=0.24 max_gap_s=1.11 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=369 first_rx_delay_s=4.84 max_gap_s=2.37 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=417 first_rx_delay_s=3.53 max_gap_s=1.16 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=371 first_rx_delay_s=2.76 max_gap_s=4.94 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=333 first_rx_delay_s=0.60 max_gap_s=0.72 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=384 first_rx_delay_s=0.71 max_gap_s=1.00 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=385 first_rx_delay_s=0.51 max_gap_s=1.06 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=381 first_rx_delay_s=0.17 max_gap_s=0.94 +node3-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=376 first_rx_delay_s=0.58 max_gap_s=1.20 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=388 first_rx_delay_s=1.89 max_gap_s=1.14 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=376 first_rx_delay_s=0.68 max_gap_s=1.21 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=464 first_rx_delay_s=9.94 max_gap_s=4.48 +node1-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node1-1 | [node1] signal: degraded_done_1 +node3-1 | [node3] waiting for degraded_complete (600s) +node1-1 | [node1] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=390 first_rx_delay_s=4.98 max_gap_s=0.43 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=380 first_rx_delay_s=0.52 max_gap_s=2.16 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=249 first_rx_delay_s=3.85 max_gap_s=11.23 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=0.71 max_gap_s=1.17 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=470 first_rx_delay_s=9.33 max_gap_s=5.00 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=365 first_rx_delay_s=4.37 max_gap_s=6.88 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=418 first_rx_delay_s=2.53 max_gap_s=1.07 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=388 first_rx_delay_s=0.44 max_gap_s=1.23 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node3-1 | [node3] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=760 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=266 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=298 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=362 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=382 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] AssignedIp=172.30.0.2 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.3 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node1-1 | [node1] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=0.75 max_gap_s=1.18 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=376 first_rx_delay_s=0.60 max_gap_s=2.59 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=253 first_rx_delay_s=0.58 max_gap_s=11.69 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=346 first_rx_delay_s=1.11 max_gap_s=11.15 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=435 first_rx_delay_s=0.57 max_gap_s=4.93 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=428 first_rx_delay_s=1.16 max_gap_s=6.53 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=425 first_rx_delay_s=0.57 max_gap_s=0.72 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=344 first_rx_delay_s=0.68 max_gap_s=11.15 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=432 first_rx_delay_s=0.88 max_gap_s=5.90 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=160 first_rx_delay_s=0.56 max_gap_s=11.69 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=430 first_rx_delay_s=0.46 max_gap_s=5.99 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=347 first_rx_delay_s=2.31 max_gap_s=11.02 +node2-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=433 first_rx_delay_s=0.90 max_gap_s=1.25 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=432 first_rx_delay_s=2.27 max_gap_s=2.37 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.46 max_gap_s=1.33 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=430 first_rx_delay_s=0.45 max_gap_s=0.88 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node2-1 | [node2] signal: post_rolling_done_2 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node2-1 | [node2] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=438 first_rx_delay_s=0.19 max_gap_s=2.17 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=433 first_rx_delay_s=0.26 max_gap_s=1.02 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=429 first_rx_delay_s=0.31 max_gap_s=1.65 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=434 first_rx_delay_s=0.17 max_gap_s=5.91 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1125 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=644 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=652 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=561 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=570 log=/app/results/iroh_after_sim.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.5 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=405 first_rx_delay_s=6.76 max_gap_s=2.11 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=0.62 max_gap_s=1.81 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=374 first_rx_delay_s=8.31 max_gap_s=0.65 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=425 first_rx_delay_s=1.19 max_gap_s=1.12 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=322 first_rx_delay_s=1.02 max_gap_s=10.41 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=345 first_rx_delay_s=0.61 max_gap_s=11.56 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=432 first_rx_delay_s=0.53 max_gap_s=5.84 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=339 first_rx_delay_s=9.98 max_gap_s=3.45 +node1-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=1.08 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=430 first_rx_delay_s=1.14 max_gap_s=1.14 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=257 first_rx_delay_s=0.48 max_gap_s=11.63 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=430 first_rx_delay_s=0.90 max_gap_s=3.23 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=439 first_rx_delay_s=0.21 max_gap_s=1.32 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=177 first_rx_delay_s=0.11 max_gap_s=13.89 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=433 first_rx_delay_s=0.54 max_gap_s=0.70 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=431 first_rx_delay_s=0.14 max_gap_s=1.23 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=428 first_rx_delay_s=0.21 max_gap_s=3.76 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=437 first_rx_delay_s=0.47 max_gap_s=1.09 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=439 first_rx_delay_s=0.11 max_gap_s=7.09 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=0.16 max_gap_s=2.39 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node4-1 | [node4] signal: post_simultaneous_done_4 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node2-1 | [node2] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node2-1 | [node2] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node4-1 | [node4] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node1-1 | [node1] outage restored (netem removed) +node2-1 | [node2] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node2-1 | [node2] signal: outage_done_2 +node1-1 | [node1] waiting for outage_restored (300s) +node2-1 | [node2] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node4-1 | [node4] outage restored (netem removed) +node3-1 | [node3] waiting for outage_restored (300s) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node2-1 | [node2] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.40 max_gap_s=7.17 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.51 max_gap_s=1.06 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=354 first_rx_delay_s=0.65 max_gap_s=11.47 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=404 first_rx_delay_s=0.63 max_gap_s=1.18 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.61 max_gap_s=0.44 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=320 first_rx_delay_s=0.46 max_gap_s=0.75 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.41 max_gap_s=1.13 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=443 first_rx_delay_s=0.62 max_gap_s=1.07 +node1-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=366 first_rx_delay_s=0.49 max_gap_s=10.16 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.61 max_gap_s=0.44 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=443 first_rx_delay_s=0.78 max_gap_s=1.29 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.51 max_gap_s=6.28 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node2-1 | [node2] signal: post_outage_recovery_done_2 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=387 first_rx_delay_s=0.14 max_gap_s=4.19 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=450 first_rx_delay_s=0.10 max_gap_s=1.21 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=450 first_rx_delay_s=0.56 max_gap_s=0.35 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=447 first_rx_delay_s=0.25 max_gap_s=1.13 +node3-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=450 first_rx_delay_s=0.10 max_gap_s=6.21 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=449 first_rx_delay_s=0.07 max_gap_s=1.22 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=413 first_rx_delay_s=0.14 max_gap_s=0.40 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.43 max_gap_s=0.80 +node4-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node4-1 | [node4] signal: post_outage_recovery_done_4 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node2-1 | [node2] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node2-1 | [node2] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.36 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=0.41 max_gap_s=0.93 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=187 first_rx_delay_s=7.60 max_gap_s=11.14 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=339 first_rx_delay_s=0.07 max_gap_s=2.58 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=352 first_rx_delay_s=6.35 max_gap_s=2.95 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.39 max_gap_s=1.05 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.05 max_gap_s=1.15 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.07 max_gap_s=1.33 +node1-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=339 first_rx_delay_s=6.79 max_gap_s=0.47 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.05 max_gap_s=1.09 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.07 max_gap_s=0.88 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.34 max_gap_s=1.08 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.34 max_gap_s=0.34 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=225 first_rx_delay_s=6.32 max_gap_s=10.40 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=341 first_rx_delay_s=0.19 max_gap_s=1.07 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.03 max_gap_s=1.06 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=132 first_rx_delay_s=6.32 max_gap_s=11.07 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.03 max_gap_s=1.20 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.46 max_gap_s=0.36 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=349 first_rx_delay_s=0.19 max_gap_s=1.20 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node4-1 | [node4] signal: recovery_done_4 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | [node3] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node1-1 | [node1] waiting for TEST_PASS (120s) +node2-1 | [node2] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node1-1 | [node1] reliability test complete +node2-1 | [node2] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260320_002703 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_002703 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260320_002703 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node1-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopped + Container docker_test-node2-1 Stopped + node2-1 exited with code 0 +node4-1 | [node4] Saved logs to /app/results/20260320_002704 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260320_002704 (exit=0) + Container docker_test-node1-1 Stopped + node1-1 exited with code 0 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_002703/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_002703/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_002703/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_002704/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_002704/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #3 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.21s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_23539 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#7 CACHED + +#8 [3/7] WORKDIR /app +#8 CACHED + +#9 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#9 CACHED + +#10 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#10 CACHED + +#11 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node1-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node0-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node3-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node1-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node0-1 Starting +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=11 log=/app/results/iroh.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node1-1 | [node1] waiting for baseline_start (300s) +node3-1 | [node3] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] netem clean +node1-1 | [node1] netem clean +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=255 first_rx_delay_s=0.63 max_gap_s=11.53 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=131 first_rx_delay_s=10.11 max_gap_s=0.36 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=344 first_rx_delay_s=0.70 max_gap_s=1.10 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=343 first_rx_delay_s=0.62 max_gap_s=1.13 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.42 max_gap_s=1.13 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=341 first_rx_delay_s=2.21 max_gap_s=1.09 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.13 max_gap_s=2.95 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.56 max_gap_s=1.23 +node2-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.42 max_gap_s=1.08 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=258 first_rx_delay_s=0.50 max_gap_s=10.21 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.17 max_gap_s=0.95 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.56 max_gap_s=1.22 +node3-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.42 max_gap_s=2.12 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.56 max_gap_s=0.89 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.13 max_gap_s=1.15 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.42 max_gap_s=2.29 +node1-1 | MESH_CHECK: PASS +node2-1 | [node2] waiting for baseline_complete (600s) +node3-1 | [node3] signal: baseline_done_3 +node1-1 | [node1] signal: baseline_done_1 +node3-1 | [node3] waiting for baseline_complete (600s) +node1-1 | [node1] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=347 first_rx_delay_s=0.44 max_gap_s=1.07 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.36 max_gap_s=0.38 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.36 max_gap_s=1.23 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=210 first_rx_delay_s=0.10 max_gap_s=2.24 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node3-1 | [node3] waiting for degraded_start (300s) +node1-1 | [node1] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=383 first_rx_delay_s=0.06 max_gap_s=1.21 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=376 first_rx_delay_s=0.76 max_gap_s=0.53 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.01 max_gap_s=1.12 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=334 first_rx_delay_s=4.96 max_gap_s=3.08 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=381 first_rx_delay_s=0.64 max_gap_s=1.22 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=380 first_rx_delay_s=0.57 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=382 first_rx_delay_s=0.22 max_gap_s=0.97 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=386 first_rx_delay_s=0.57 max_gap_s=1.25 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=383 first_rx_delay_s=0.67 max_gap_s=1.15 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=368 first_rx_delay_s=0.54 max_gap_s=3.29 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=381 first_rx_delay_s=0.22 max_gap_s=1.17 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=375 first_rx_delay_s=0.57 max_gap_s=1.41 +node3-1 | MESH_CHECK: PASS +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=383 first_rx_delay_s=0.34 max_gap_s=1.16 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=384 first_rx_delay_s=0.57 max_gap_s=0.42 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=384 first_rx_delay_s=0.57 max_gap_s=0.99 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=385 first_rx_delay_s=0.64 max_gap_s=3.15 +node1-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=389 first_rx_delay_s=0.42 max_gap_s=0.94 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=385 first_rx_delay_s=7.67 max_gap_s=6.02 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=380 first_rx_delay_s=0.48 max_gap_s=0.57 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=384 first_rx_delay_s=0.51 max_gap_s=1.08 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=1029 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=524 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=496 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=409 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=474 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] AssignedIp=172.30.0.2 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.4 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node3-1 | [node3] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=383 first_rx_delay_s=1.10 max_gap_s=1.40 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=435 first_rx_delay_s=1.00 max_gap_s=1.00 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=345 first_rx_delay_s=1.01 max_gap_s=2.61 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=418 first_rx_delay_s=1.07 max_gap_s=1.24 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=376 first_rx_delay_s=0.42 max_gap_s=0.53 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=342 first_rx_delay_s=0.60 max_gap_s=11.35 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=422 first_rx_delay_s=2.29 max_gap_s=2.24 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=437 first_rx_delay_s=0.58 max_gap_s=2.74 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=350 first_rx_delay_s=0.74 max_gap_s=10.86 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=430 first_rx_delay_s=0.30 max_gap_s=1.96 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=336 first_rx_delay_s=0.55 max_gap_s=10.99 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=257 first_rx_delay_s=0.56 max_gap_s=11.37 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node4-1 | [node4] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=261 first_rx_delay_s=0.31 max_gap_s=10.96 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=429 first_rx_delay_s=0.48 max_gap_s=2.33 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=437 first_rx_delay_s=0.66 max_gap_s=2.67 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=434 first_rx_delay_s=0.73 max_gap_s=1.07 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=346 first_rx_delay_s=0.57 max_gap_s=11.48 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=437 first_rx_delay_s=0.65 max_gap_s=1.12 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=437 first_rx_delay_s=0.46 max_gap_s=1.25 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=356 first_rx_delay_s=2.72 max_gap_s=10.90 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node0-1 | [node0] signal: sim_stopped_0 +node3-1 | [node3] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node1-1 | [node1] waiting for sim_go (120s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1454 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=683 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=806 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=786 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=794 log=/app/results/iroh_after_sim.log +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.2 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] netem degraded on tun0 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=424 first_rx_delay_s=0.87 max_gap_s=0.41 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=428 first_rx_delay_s=0.95 max_gap_s=0.47 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=425 first_rx_delay_s=0.87 max_gap_s=1.26 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=428 first_rx_delay_s=4.37 max_gap_s=1.02 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=440 first_rx_delay_s=0.24 max_gap_s=1.00 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=340 first_rx_delay_s=0.74 max_gap_s=11.21 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=349 first_rx_delay_s=14.90 max_gap_s=1.25 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=360 first_rx_delay_s=0.69 max_gap_s=1.04 +node2-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=391 first_rx_delay_s=0.73 max_gap_s=6.52 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=425 first_rx_delay_s=4.62 max_gap_s=0.41 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=421 first_rx_delay_s=0.72 max_gap_s=2.70 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=429 first_rx_delay_s=0.47 max_gap_s=3.89 +node4-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node4-1 | [node4] signal: post_simultaneous_done_4 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=430 first_rx_delay_s=0.67 max_gap_s=1.22 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=195 first_rx_delay_s=0.56 max_gap_s=11.24 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=432 first_rx_delay_s=0.39 max_gap_s=1.20 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=432 first_rx_delay_s=0.61 max_gap_s=1.15 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=329 first_rx_delay_s=0.35 max_gap_s=10.23 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=439 first_rx_delay_s=0.46 max_gap_s=0.44 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=360 first_rx_delay_s=11.12 max_gap_s=0.44 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=435 first_rx_delay_s=0.25 max_gap_s=1.16 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node4-1 | [node4] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] waiting for outage_start (300s) +node2-1 | [node2] outage hold for 25s +node4-1 | [node4] outage hold for 25s +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node2-1 | [node2] outage restored (netem removed) +node4-1 | [node4] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node4-1 | [node4] signal: outage_done_4 +node3-1 | [node3] outage restored (netem removed) +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node2-1 | [node2] netem clean +node3-1 | [node3] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=442 first_rx_delay_s=0.72 max_gap_s=1.09 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.74 max_gap_s=1.20 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=444 first_rx_delay_s=0.65 max_gap_s=1.12 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=444 first_rx_delay_s=0.65 max_gap_s=1.06 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=444 first_rx_delay_s=0.48 max_gap_s=1.11 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=445 first_rx_delay_s=0.50 max_gap_s=6.11 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.32 max_gap_s=2.59 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=449 first_rx_delay_s=0.14 max_gap_s=1.25 +node2-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=445 first_rx_delay_s=0.24 max_gap_s=0.98 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=382 first_rx_delay_s=0.40 max_gap_s=0.34 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=449 first_rx_delay_s=0.14 max_gap_s=1.26 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=284 first_rx_delay_s=0.41 max_gap_s=10.98 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=449 first_rx_delay_s=0.14 max_gap_s=1.16 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.53 max_gap_s=0.96 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=447 first_rx_delay_s=0.40 max_gap_s=1.03 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=445 first_rx_delay_s=0.50 max_gap_s=2.21 +node3-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node3-1 | [node3] signal: post_outage_recovery_done_3 +node4-1 | [node4] signal: post_outage_recovery_done_4 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=360 first_rx_delay_s=0.38 max_gap_s=11.25 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=450 first_rx_delay_s=0.02 max_gap_s=1.22 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.29 max_gap_s=1.10 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=359 first_rx_delay_s=0.29 max_gap_s=0.99 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node4-1 | [node4] waiting for recovery_start (300s) +node3-1 | [node3] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.08 max_gap_s=1.20 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.00 max_gap_s=1.01 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.06 max_gap_s=1.06 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.18 max_gap_s=1.01 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.25 max_gap_s=1.03 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.30 max_gap_s=1.12 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=163 first_rx_delay_s=2.19 max_gap_s=11.07 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=329 first_rx_delay_s=7.94 max_gap_s=5.10 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.25 max_gap_s=1.13 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.60 max_gap_s=2.25 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=237 first_rx_delay_s=2.36 max_gap_s=17.10 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.30 max_gap_s=1.04 +node2-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.79 max_gap_s=1.16 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=1.29 max_gap_s=0.96 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=344 first_rx_delay_s=1.52 max_gap_s=1.23 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.25 max_gap_s=0.42 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node3-1 | [node3] signal: recovery_done_3 +node2-1 | [node2] signal: recovery_done_2 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | [node2] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=317 first_rx_delay_s=0.47 max_gap_s=5.55 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.32 max_gap_s=1.03 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=348 first_rx_delay_s=2.07 max_gap_s=5.36 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.13 max_gap_s=1.99 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260320_003435 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node1-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node0-1 Stopped +node3-1 | [node3] Saved logs to /app/results/20260320_003435 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_003435 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260320_003435 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260320_003435 (exit=0) + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_003435/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_003435/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_003435/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_003435/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_003435/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #4 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_9581 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#7 CACHED + +#8 [3/7] WORKDIR /app +#8 CACHED + +#9 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#9 CACHED + +#10 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node1-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node1-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node0-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node4-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node0-1 Starting +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node1-1 | [node1] AssignedIp=172.30.0.2 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.3 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.4 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node4-1 | [node4] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=132 first_rx_delay_s=0.77 max_gap_s=11.43 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=341 first_rx_delay_s=0.83 max_gap_s=1.45 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=343 first_rx_delay_s=0.91 max_gap_s=0.69 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=254 first_rx_delay_s=0.86 max_gap_s=15.45 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=249 first_rx_delay_s=0.04 max_gap_s=5.11 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=186 first_rx_delay_s=0.40 max_gap_s=10.36 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.49 max_gap_s=0.34 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=337 first_rx_delay_s=0.45 max_gap_s=7.17 +node2-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=252 first_rx_delay_s=0.36 max_gap_s=0.34 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=342 first_rx_delay_s=0.43 max_gap_s=1.45 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.49 max_gap_s=1.12 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.04 max_gap_s=5.66 +node4-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=344 first_rx_delay_s=0.37 max_gap_s=1.16 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.44 max_gap_s=1.16 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.40 max_gap_s=4.53 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.01 max_gap_s=1.32 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.41 max_gap_s=1.39 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=1.02 max_gap_s=1.10 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=227 first_rx_delay_s=5.75 max_gap_s=11.44 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=65 first_rx_delay_s=10.77 max_gap_s=11.14 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] waiting for degraded_start (300s) +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=384 first_rx_delay_s=0.06 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=386 first_rx_delay_s=0.07 max_gap_s=0.73 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=395 first_rx_delay_s=0.94 max_gap_s=0.70 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=386 first_rx_delay_s=0.06 max_gap_s=1.23 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=394 first_rx_delay_s=0.09 max_gap_s=1.05 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=214 first_rx_delay_s=0.01 max_gap_s=10.76 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=388 first_rx_delay_s=0.44 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=387 first_rx_delay_s=7.29 max_gap_s=1.05 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=392 first_rx_delay_s=0.99 max_gap_s=0.57 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=390 first_rx_delay_s=0.85 max_gap_s=2.99 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=382 first_rx_delay_s=0.72 max_gap_s=2.37 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=384 first_rx_delay_s=0.00 max_gap_s=6.16 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node4-1 | [node4] signal: degraded_done_4 +node2-1 | [node2] waiting for degraded_complete (600s) +node4-1 | [node4] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.48 max_gap_s=0.38 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=386 first_rx_delay_s=0.17 max_gap_s=1.33 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=301 first_rx_delay_s=10.84 max_gap_s=5.82 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=106 first_rx_delay_s=0.33 max_gap_s=11.02 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=295 first_rx_delay_s=0.71 max_gap_s=14.20 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=383 first_rx_delay_s=8.59 max_gap_s=1.49 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=379 first_rx_delay_s=0.59 max_gap_s=2.45 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=391 first_rx_delay_s=1.36 max_gap_s=5.40 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=739 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=303 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=358 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=382 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=282 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=340 first_rx_delay_s=0.81 max_gap_s=10.49 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=422 first_rx_delay_s=1.07 max_gap_s=0.41 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=439 first_rx_delay_s=0.63 max_gap_s=0.42 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=107 first_rx_delay_s=1.12 max_gap_s=11.26 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.58 max_gap_s=1.09 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +node2-1 | MESH_CHECK: FAIL peer=172.30.0.5 tx=450 rx=0 (expected both > 0) +node2-1 | MESH_CHECK: FAIL peer=172.30.0.5 never received any packet +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=338 first_rx_delay_s=2.48 max_gap_s=11.46 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.64 max_gap_s=1.12 +node2-1 | MESH_CHECK: FAIL +node2-1 | [node2] Saved logs to /app/results/20260320_003828 (exit=1) +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=432 first_rx_delay_s=0.63 max_gap_s=2.67 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=424 first_rx_delay_s=0.94 max_gap_s=0.60 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=437 first_rx_delay_s=0.35 max_gap_s=1.01 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=250 first_rx_delay_s=0.90 max_gap_s=11.34 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) + node2-1 exited with code 1 + Compose Stopping Aborting on container exit... + Container docker_test-node3-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node2-1 Stopped +node3-1 | [node3] Saved logs to /app/results/20260320_003828 (exit=0) +node0-1 | [node0] Saved logs to /app/results/20260320_003828 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260320_003828 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260320_003828 (exit=0) + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node0-1 Stopped + node0-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_003828/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [FAIL] post_simultaneous: missing log + [INFO] post_outage_recovery: missing log + [FAIL] recovery: missing log +node1: docker_test/results_reliability/node1/20260320_003828/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [FAIL] post_simultaneous: missing log + [INFO] post_outage_recovery: missing log + [FAIL] recovery: missing log +node2: docker_test/results_reliability/node2/20260320_003828/ + [PASS] baseline + [PASS] degraded + [FAIL] post_rolling +MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.58 max_gap_s=1.09 +MESH_CHECK: peer=172.30.0.5 tx=450 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +MESH_CHECK: FAIL peer=172.30.0.5 tx=450 rx=0 (expected both > 0) +MESH_CHECK: FAIL peer=172.30.0.5 never received any packet +MESH_CHECK: peer=172.30.0.2 tx=450 rx=338 first_rx_delay_s=2.48 max_gap_s=11.46 +MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.64 max_gap_s=1.12 +MESH_CHECK: FAIL + [FAIL] post_simultaneous: missing log + [INFO] post_outage_recovery: missing log + [FAIL] recovery: missing log +node3: docker_test/results_reliability/node3/20260320_003828/ + [PASS] baseline + [PASS] degraded + [FAIL] post_rolling +MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms + [FAIL] post_simultaneous: missing log + [INFO] post_outage_recovery: missing log + [FAIL] recovery: missing log +node4: docker_test/results_reliability/node4/20260320_003828/ + [PASS] baseline + [PASS] degraded + [FAIL] post_rolling +MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms + [FAIL] post_simultaneous: missing log + [INFO] post_outage_recovery: missing log + [FAIL] recovery: missing log +======================================================== +RELIABILITY RESULT: FAIL +make: *** [Makefile:29: reliability-test] Error 1 diff --git a/docker_test/test_results_conn10_read6.log b/docker_test/test_results_conn10_read6.log new file mode 100644 index 0000000..cac93da --- /dev/null +++ b/docker_test/test_results_conn10_read6.log @@ -0,0 +1,3798 @@ +--- Run #1 --- +cargo build + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.07s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.40s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.45s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.44s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_26083 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.7s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#7 CACHED + +#8 [3/7] WORKDIR /app +#8 CACHED + +#9 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#9 CACHED + +#10 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node2-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node2-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node4-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node1-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node0-1 Starting +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node2-1 | [node2] started iroh pid=9 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.5 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node3-1 | [node3] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=342 first_rx_delay_s=0.91 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=341 first_rx_delay_s=0.86 max_gap_s=0.34 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=342 first_rx_delay_s=0.81 max_gap_s=0.98 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=204 first_rx_delay_s=0.92 max_gap_s=9.49 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.12 max_gap_s=1.06 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=243 first_rx_delay_s=0.59 max_gap_s=7.83 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=134 first_rx_delay_s=0.49 max_gap_s=9.53 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=347 first_rx_delay_s=0.52 max_gap_s=2.37 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.14 max_gap_s=0.32 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=16 first_rx_delay_s=0.42 max_gap_s=0.24 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=278 first_rx_delay_s=9.90 max_gap_s=5.56 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=60 first_rx_delay_s=0.37 max_gap_s=9.17 +node1-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=286 first_rx_delay_s=0.37 max_gap_s=9.01 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=277 first_rx_delay_s=0.52 max_gap_s=12.47 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=9 first_rx_delay_s=0.47 max_gap_s=0.20 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.11 max_gap_s=1.25 +node3-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=289 first_rx_delay_s=0.02 max_gap_s=8.44 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=95 first_rx_delay_s=0.32 max_gap_s=9.61 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=348 first_rx_delay_s=0.42 max_gap_s=2.47 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=225 first_rx_delay_s=0.37 max_gap_s=9.33 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.02 max_gap_s=0.92 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=381 first_rx_delay_s=0.03 max_gap_s=1.33 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=383 first_rx_delay_s=0.17 max_gap_s=1.16 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=374 first_rx_delay_s=0.26 max_gap_s=1.40 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=380 first_rx_delay_s=0.23 max_gap_s=1.14 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=204 first_rx_delay_s=0.85 max_gap_s=9.30 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=382 first_rx_delay_s=0.62 max_gap_s=1.07 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=353 first_rx_delay_s=5.81 max_gap_s=4.76 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=382 first_rx_delay_s=0.12 max_gap_s=1.14 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=131 first_rx_delay_s=8.32 max_gap_s=9.28 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=424 first_rx_delay_s=0.82 max_gap_s=5.15 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=654 first_rx_delay_s=3.34 max_gap_s=0.55 +node1-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=391 first_rx_delay_s=0.12 max_gap_s=1.31 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=329 first_rx_delay_s=8.32 max_gap_s=1.08 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=0.49 max_gap_s=5.62 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=651 first_rx_delay_s=3.91 max_gap_s=1.37 +node3-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=392 first_rx_delay_s=0.09 max_gap_s=1.28 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=385 first_rx_delay_s=0.44 max_gap_s=4.25 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=0.40 max_gap_s=2.55 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=219 first_rx_delay_s=8.21 max_gap_s=7.73 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=788 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=284 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=324 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=354 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=414 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node2-1 | [node2] waiting for post_rolling_start (300s) +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] netem degraded on tun0 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node3-1 | [node3] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=427 first_rx_delay_s=0.47 max_gap_s=1.18 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=299 first_rx_delay_s=0.68 max_gap_s=9.16 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=359 first_rx_delay_s=1.10 max_gap_s=9.12 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=424 first_rx_delay_s=1.00 max_gap_s=3.26 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=430 first_rx_delay_s=1.10 max_gap_s=1.04 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=414 first_rx_delay_s=0.77 max_gap_s=2.45 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=428 first_rx_delay_s=0.99 max_gap_s=1.34 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=431 first_rx_delay_s=0.70 max_gap_s=1.12 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=425 first_rx_delay_s=0.84 max_gap_s=1.24 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=305 first_rx_delay_s=0.61 max_gap_s=9.20 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=427 first_rx_delay_s=0.95 max_gap_s=1.03 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=434 first_rx_delay_s=0.53 max_gap_s=2.36 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=433 first_rx_delay_s=0.25 max_gap_s=1.14 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=297 first_rx_delay_s=0.02 max_gap_s=9.97 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=404 first_rx_delay_s=0.74 max_gap_s=5.93 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=432 first_rx_delay_s=0.30 max_gap_s=1.32 +node3-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=431 first_rx_delay_s=0.28 max_gap_s=1.17 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=427 first_rx_delay_s=0.22 max_gap_s=2.81 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=400 first_rx_delay_s=12.82 max_gap_s=5.88 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=437 first_rx_delay_s=0.27 max_gap_s=1.20 +node4-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node3-1 | [node3] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node0-1 | [node0] signal: sim_stopped_0 +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1105 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=659 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=518 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=550 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=603 log=/app/results/iroh_after_sim.log +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.6 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node3-1 | [node3] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=420 first_rx_delay_s=0.94 max_gap_s=3.63 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=0.75 max_gap_s=0.54 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=1.05 max_gap_s=1.12 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=423 first_rx_delay_s=0.70 max_gap_s=2.47 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=387 first_rx_delay_s=7.10 max_gap_s=0.37 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=429 first_rx_delay_s=0.69 max_gap_s=1.05 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=367 first_rx_delay_s=0.24 max_gap_s=9.21 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=438 first_rx_delay_s=0.93 max_gap_s=1.28 +node3-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=325 first_rx_delay_s=1.21 max_gap_s=9.46 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=428 first_rx_delay_s=0.75 max_gap_s=5.94 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=425 first_rx_delay_s=14.27 max_gap_s=0.90 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=433 first_rx_delay_s=0.27 max_gap_s=0.89 +node2-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=428 first_rx_delay_s=0.71 max_gap_s=1.34 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=422 first_rx_delay_s=0.84 max_gap_s=2.27 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=434 first_rx_delay_s=13.69 max_gap_s=1.01 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=440 first_rx_delay_s=0.27 max_gap_s=4.55 +node4-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node2-1 | [node2] signal: post_simultaneous_done_2 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=427 first_rx_delay_s=0.46 max_gap_s=1.12 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=180 first_rx_delay_s=0.39 max_gap_s=9.16 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=434 first_rx_delay_s=0.08 max_gap_s=1.14 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=431 first_rx_delay_s=0.41 max_gap_s=2.15 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node3-1 | [node3] waiting for outage_start (300s) +node4-1 | [node4] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node3-1 | [node3] outage hold for 25s +node4-1 | [node4] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node2-1 | [node2] outage restored (netem removed) +node3-1 | [node3] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node3-1 | [node3] signal: outage_done_3 +node4-1 | [node4] outage restored (netem removed) +node2-1 | [node2] waiting for outage_restored (300s) +node4-1 | [node4] signal: outage_done_4 +node3-1 | [node3] waiting for outage_restored (300s) +node4-1 | [node4] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] netem clean +node2-1 | [node2] netem clean +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=403 first_rx_delay_s=0.67 max_gap_s=5.34 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=435 first_rx_delay_s=0.67 max_gap_s=5.50 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=284 first_rx_delay_s=0.61 max_gap_s=9.57 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=441 first_rx_delay_s=0.88 max_gap_s=1.05 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=283 first_rx_delay_s=0.19 max_gap_s=9.29 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=445 first_rx_delay_s=0.33 max_gap_s=2.57 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=446 first_rx_delay_s=0.33 max_gap_s=1.00 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.49 max_gap_s=1.10 +node3-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=445 first_rx_delay_s=0.33 max_gap_s=5.26 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=449 first_rx_delay_s=0.19 max_gap_s=2.60 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=114 first_rx_delay_s=0.61 max_gap_s=12.08 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=446 first_rx_delay_s=0.39 max_gap_s=1.19 +node2-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=336 first_rx_delay_s=0.19 max_gap_s=9.10 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=445 first_rx_delay_s=0.60 max_gap_s=1.03 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=446 first_rx_delay_s=0.33 max_gap_s=1.18 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=417 first_rx_delay_s=0.39 max_gap_s=3.33 +node4-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node3-1 | [node3] signal: post_outage_recovery_done_3 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node4-1 | [node4] signal: post_outage_recovery_done_4 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=450 first_rx_delay_s=0.01 max_gap_s=0.41 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=448 first_rx_delay_s=0.20 max_gap_s=0.94 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=106 first_rx_delay_s=0.18 max_gap_s=8.38 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=448 first_rx_delay_s=0.21 max_gap_s=1.07 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node3-1 | [node3] waiting for recovery_start (300s) +node4-1 | [node4] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node2-1 | [node2] netem clean +node4-1 | [node4] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=272 first_rx_delay_s=7.29 max_gap_s=7.96 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.01 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=263 first_rx_delay_s=0.03 max_gap_s=1.06 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.06 max_gap_s=1.08 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=342 first_rx_delay_s=0.37 max_gap_s=2.17 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=347 first_rx_delay_s=0.28 max_gap_s=1.31 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.10 max_gap_s=0.41 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=264 first_rx_delay_s=0.22 max_gap_s=8.93 +node3-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=367 first_rx_delay_s=5.35 max_gap_s=2.30 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=281 first_rx_delay_s=0.40 max_gap_s=2.58 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.12 max_gap_s=1.14 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.09 max_gap_s=1.09 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=536 first_rx_delay_s=20.79 max_gap_s=0.84 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=329 first_rx_delay_s=0.12 max_gap_s=1.06 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=219 first_rx_delay_s=0.37 max_gap_s=8.99 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.37 max_gap_s=5.72 +node2-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node2-1 | [node2] signal: recovery_done_2 +node4-1 | [node4] signal: recovery_done_4 +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | [node2] waiting for recovery_complete (600s) +node4-1 | [node4] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=348 first_rx_delay_s=0.19 max_gap_s=1.05 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.01 max_gap_s=0.93 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=462 first_rx_delay_s=20.95 max_gap_s=1.10 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=348 first_rx_delay_s=0.18 max_gap_s=1.07 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260319_200448 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node0-1 Stopped +node1-1 | [node1] Saved logs to /app/results/20260319_200448 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260319_200448 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260319_200448 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260319_200448 (exit=0) + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260319_200448/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260319_200448/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260319_200448/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260319_200448/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260319_200448/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #2 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.33s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_27967 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.7s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#7 CACHED + +#8 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#8 CACHED + +#9 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#9 CACHED + +#10 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#10 CACHED + +#11 [3/7] WORKDIR /app +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node1-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node3-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node4-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node1-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node0-1 Starting +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=9 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node3-1 | [node3] AssignedIp=172.30.0.3 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.4 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node1-1 | [node1] AssignedIp=172.30.0.6 +node2-1 | [node2] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node1-1 | [node1] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node2-1 | [node2] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node2-1 | [node2] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=342 first_rx_delay_s=1.00 max_gap_s=1.13 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=341 first_rx_delay_s=0.97 max_gap_s=0.36 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=342 first_rx_delay_s=0.99 max_gap_s=0.93 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=332 first_rx_delay_s=0.88 max_gap_s=0.42 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.60 max_gap_s=2.93 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.59 max_gap_s=0.71 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=276 first_rx_delay_s=0.57 max_gap_s=9.52 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.06 max_gap_s=1.09 +node1-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=272 first_rx_delay_s=0.48 max_gap_s=9.24 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.57 max_gap_s=0.38 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=278 first_rx_delay_s=0.59 max_gap_s=9.74 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=1.16 max_gap_s=1.00 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=348 first_rx_delay_s=0.41 max_gap_s=1.17 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=342 first_rx_delay_s=1.16 max_gap_s=2.54 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.44 max_gap_s=1.07 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.14 max_gap_s=1.04 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=349 first_rx_delay_s=0.11 max_gap_s=1.08 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=330 first_rx_delay_s=0.41 max_gap_s=5.40 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=281 first_rx_delay_s=0.53 max_gap_s=9.03 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=139 first_rx_delay_s=0.51 max_gap_s=9.51 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node2-1 | [node2] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=384 first_rx_delay_s=0.01 max_gap_s=1.26 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=384 first_rx_delay_s=0.10 max_gap_s=0.82 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=379 first_rx_delay_s=0.21 max_gap_s=0.84 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=373 first_rx_delay_s=0.21 max_gap_s=1.16 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=384 first_rx_delay_s=0.17 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=318 first_rx_delay_s=0.64 max_gap_s=9.66 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.53 max_gap_s=2.90 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=317 first_rx_delay_s=0.78 max_gap_s=9.04 +node2-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=379 first_rx_delay_s=0.69 max_gap_s=2.92 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=189 first_rx_delay_s=0.64 max_gap_s=10.20 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=389 first_rx_delay_s=0.28 max_gap_s=1.26 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=394 first_rx_delay_s=0.61 max_gap_s=1.09 +node1-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node1-1 | [node1] signal: degraded_done_1 +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | [node1] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=378 first_rx_delay_s=0.64 max_gap_s=0.43 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=336 first_rx_delay_s=0.58 max_gap_s=7.64 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=392 first_rx_delay_s=0.08 max_gap_s=1.10 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=383 first_rx_delay_s=1.37 max_gap_s=2.43 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=381 first_rx_delay_s=0.61 max_gap_s=2.80 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=153 first_rx_delay_s=2.29 max_gap_s=9.29 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=382 first_rx_delay_s=0.61 max_gap_s=10.78 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=385 first_rx_delay_s=0.11 max_gap_s=1.12 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node1-1 | [node1] waiting for rolling_go (120s) +node2-1 | [node2] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=718 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=265 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=301 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=343 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=384 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.5 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=430 first_rx_delay_s=0.89 max_gap_s=2.41 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=179 first_rx_delay_s=43.20 max_gap_s=0.34 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=360 first_rx_delay_s=1.06 max_gap_s=9.39 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=339 first_rx_delay_s=4.80 max_gap_s=8.91 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=394 first_rx_delay_s=1.09 max_gap_s=3.19 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=431 first_rx_delay_s=0.97 max_gap_s=1.04 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=213 first_rx_delay_s=42.73 max_gap_s=0.38 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=418 first_rx_delay_s=0.96 max_gap_s=1.09 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=432 first_rx_delay_s=0.19 max_gap_s=1.09 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=435 first_rx_delay_s=0.17 max_gap_s=2.28 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=436 first_rx_delay_s=0.70 max_gap_s=0.93 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=423 first_rx_delay_s=0.61 max_gap_s=2.03 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=381 first_rx_delay_s=0.53 max_gap_s=8.25 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=361 first_rx_delay_s=0.14 max_gap_s=9.35 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=304 first_rx_delay_s=0.21 max_gap_s=8.95 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=434 first_rx_delay_s=0.64 max_gap_s=1.16 +node2-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=361 first_rx_delay_s=0.67 max_gap_s=9.12 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=367 first_rx_delay_s=0.32 max_gap_s=9.16 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=416 first_rx_delay_s=4.18 max_gap_s=2.53 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=431 first_rx_delay_s=5.33 max_gap_s=1.01 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node3-1 | [node3] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node0-1 | [node0] signal: sim_stopped_0 +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1101 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=644 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=505 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=549 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=611 log=/app/results/iroh_after_sim.log +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=415 first_rx_delay_s=5.73 max_gap_s=0.92 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=424 first_rx_delay_s=0.91 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=342 first_rx_delay_s=13.16 max_gap_s=0.55 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=426 first_rx_delay_s=0.87 max_gap_s=1.34 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=110 first_rx_delay_s=0.67 max_gap_s=0.73 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=0.08 max_gap_s=2.71 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=286 first_rx_delay_s=9.80 max_gap_s=9.25 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=281 first_rx_delay_s=0.55 max_gap_s=9.13 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=437 first_rx_delay_s=0.26 max_gap_s=0.48 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=427 first_rx_delay_s=0.72 max_gap_s=1.27 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=437 first_rx_delay_s=0.51 max_gap_s=1.24 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=437 first_rx_delay_s=0.63 max_gap_s=2.64 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node3-1 | [node3] signal: post_simultaneous_done_3 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=433 first_rx_delay_s=0.22 max_gap_s=1.04 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=358 first_rx_delay_s=0.63 max_gap_s=29.87 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=415 first_rx_delay_s=0.47 max_gap_s=14.56 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=432 first_rx_delay_s=0.52 max_gap_s=1.42 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=86 first_rx_delay_s=0.44 max_gap_s=0.39 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=433 first_rx_delay_s=0.43 max_gap_s=0.90 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=405 first_rx_delay_s=4.38 max_gap_s=1.05 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=430 first_rx_delay_s=0.45 max_gap_s=23.64 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node3-1 | [node3] outage restored (netem removed) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node3-1 | [node3] signal: outage_done_3 +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | MESH_CHECK: FAIL peer=172.30.0.4 never received packet within 30s +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=375 first_rx_delay_s=0.81 max_gap_s=8.89 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.63 max_gap_s=1.26 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=442 first_rx_delay_s=0.90 max_gap_s=0.35 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=300 first_rx_delay_s=0.56 max_gap_s=1.03 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=449 first_rx_delay_s=0.08 max_gap_s=1.09 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.56 max_gap_s=1.07 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=300 first_rx_delay_s=0.37 max_gap_s=1.08 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=445 first_rx_delay_s=0.50 max_gap_s=2.40 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.27 max_gap_s=1.11 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=300 first_rx_delay_s=0.23 max_gap_s=0.85 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=377 first_rx_delay_s=0.43 max_gap_s=9.07 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.05 max_gap_s=1.15 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=63 first_rx_delay_s=26.61 max_gap_s=3.29 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=442 first_rx_delay_s=0.45 max_gap_s=3.09 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=449 first_rx_delay_s=0.10 max_gap_s=2.61 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=378 first_rx_delay_s=0.31 max_gap_s=9.77 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=342 first_rx_delay_s=0.78 max_gap_s=1.11 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.17 max_gap_s=0.98 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.04 max_gap_s=0.96 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.09 max_gap_s=1.07 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.58 max_gap_s=0.92 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.51 max_gap_s=1.11 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.40 max_gap_s=1.20 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.45 max_gap_s=0.96 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=337 first_rx_delay_s=0.49 max_gap_s=1.11 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.44 max_gap_s=0.37 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.42 max_gap_s=0.98 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.03 max_gap_s=0.89 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.38 max_gap_s=1.00 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.32 max_gap_s=0.71 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.43 max_gap_s=1.40 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.04 max_gap_s=1.14 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node4-1 | [node4] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=347 first_rx_delay_s=0.34 max_gap_s=1.00 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=342 first_rx_delay_s=0.32 max_gap_s=1.00 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.35 max_gap_s=0.37 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.01 max_gap_s=1.15 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260319_201147 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node0-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopped +node3-1 | [node3] Saved logs to /app/results/20260319_201147 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260319_201147 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260319_201147 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260319_201147 (exit=0) + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260319_201147/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260319_201147/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260319_201147/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260319_201147/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260319_201147/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [INFO] post_outage_recovery +MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +MESH_CHECK: FAIL peer=172.30.0.4 never received packet within 30s + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #3 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_29569 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#7 CACHED + +#8 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#8 CACHED + +#9 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#9 CACHED + +#10 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#10 CACHED + +#11 [3/7] WORKDIR /app +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node2-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node1-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node3-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node3-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node0-1 Starting +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.4 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] waiting for baseline_start (300s) +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=342 first_rx_delay_s=0.88 max_gap_s=0.38 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=291 first_rx_delay_s=0.85 max_gap_s=7.44 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=333 first_rx_delay_s=0.74 max_gap_s=11.13 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=342 first_rx_delay_s=0.74 max_gap_s=0.65 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=181 first_rx_delay_s=0.46 max_gap_s=13.01 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=285 first_rx_delay_s=0.70 max_gap_s=16.43 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=280 first_rx_delay_s=0.30 max_gap_s=9.47 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=350 first_rx_delay_s=0.05 max_gap_s=1.09 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=207 first_rx_delay_s=0.49 max_gap_s=2.24 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=347 first_rx_delay_s=0.35 max_gap_s=2.47 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.45 max_gap_s=1.04 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.18 max_gap_s=1.16 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=260 first_rx_delay_s=9.34 max_gap_s=1.12 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=234 first_rx_delay_s=0.28 max_gap_s=9.28 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=310 first_rx_delay_s=0.11 max_gap_s=14.53 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.24 max_gap_s=0.65 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.11 max_gap_s=1.08 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=279 first_rx_delay_s=0.32 max_gap_s=17.25 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=98 first_rx_delay_s=0.25 max_gap_s=9.54 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=343 first_rx_delay_s=0.40 max_gap_s=3.96 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] waiting for degraded_start (300s) +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=0.06 max_gap_s=0.65 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=376 first_rx_delay_s=0.25 max_gap_s=5.08 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=381 first_rx_delay_s=0.01 max_gap_s=0.85 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=387 first_rx_delay_s=0.24 max_gap_s=0.68 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=250 first_rx_delay_s=2.91 max_gap_s=8.20 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=254 first_rx_delay_s=0.59 max_gap_s=8.95 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=386 first_rx_delay_s=0.09 max_gap_s=1.37 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.46 max_gap_s=1.12 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=322 first_rx_delay_s=0.66 max_gap_s=9.47 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=495 first_rx_delay_s=7.90 max_gap_s=5.98 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=382 first_rx_delay_s=0.60 max_gap_s=4.56 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=381 first_rx_delay_s=0.04 max_gap_s=1.31 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=391 first_rx_delay_s=0.52 max_gap_s=0.35 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=386 first_rx_delay_s=0.00 max_gap_s=1.14 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=384 first_rx_delay_s=0.57 max_gap_s=1.11 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=380 first_rx_delay_s=0.51 max_gap_s=2.80 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=376 first_rx_delay_s=0.29 max_gap_s=1.18 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=467 first_rx_delay_s=5.70 max_gap_s=0.62 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=378 first_rx_delay_s=0.48 max_gap_s=1.03 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=391 first_rx_delay_s=0.51 max_gap_s=0.44 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node3-1 | [node3] waiting for rolling_go (120s) +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=743 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=272 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=339 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=382 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=317 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] AssignedIp=172.30.0.3 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.4 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node4-1 | [node4] AssignedIp=172.30.0.2 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.5 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.6 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=359 first_rx_delay_s=1.01 max_gap_s=7.68 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=368 first_rx_delay_s=0.70 max_gap_s=9.03 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=360 first_rx_delay_s=1.15 max_gap_s=16.89 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=428 first_rx_delay_s=0.68 max_gap_s=0.53 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=430 first_rx_delay_s=0.66 max_gap_s=1.27 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=436 first_rx_delay_s=0.64 max_gap_s=2.60 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=432 first_rx_delay_s=1.05 max_gap_s=0.46 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=422 first_rx_delay_s=1.12 max_gap_s=1.13 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=431 first_rx_delay_s=0.49 max_gap_s=1.23 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=384 first_rx_delay_s=0.94 max_gap_s=6.40 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.54 max_gap_s=0.60 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=433 first_rx_delay_s=1.04 max_gap_s=1.09 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=403 first_rx_delay_s=0.20 max_gap_s=3.52 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=431 first_rx_delay_s=0.62 max_gap_s=1.11 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=220 first_rx_delay_s=0.21 max_gap_s=13.86 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=434 first_rx_delay_s=0.24 max_gap_s=1.11 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=306 first_rx_delay_s=0.12 max_gap_s=9.38 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=436 first_rx_delay_s=0.20 max_gap_s=1.21 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=422 first_rx_delay_s=0.23 max_gap_s=1.21 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=435 first_rx_delay_s=0.49 max_gap_s=1.11 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1062 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=625 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=500 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=555 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=582 log=/app/results/iroh_after_sim.log +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.6 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] netem degraded on tun0 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=421 first_rx_delay_s=0.93 max_gap_s=1.09 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=427 first_rx_delay_s=2.73 max_gap_s=0.69 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=408 first_rx_delay_s=0.84 max_gap_s=2.58 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=406 first_rx_delay_s=4.15 max_gap_s=1.22 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=424 first_rx_delay_s=0.74 max_gap_s=1.11 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=330 first_rx_delay_s=9.07 max_gap_s=9.04 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=433 first_rx_delay_s=0.87 max_gap_s=1.11 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=316 first_rx_delay_s=7.63 max_gap_s=3.94 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=325 first_rx_delay_s=10.94 max_gap_s=0.99 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=443 first_rx_delay_s=0.10 max_gap_s=2.56 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=432 first_rx_delay_s=0.62 max_gap_s=0.92 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=426 first_rx_delay_s=0.52 max_gap_s=1.55 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=435 first_rx_delay_s=2.32 max_gap_s=1.31 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=423 first_rx_delay_s=0.76 max_gap_s=1.17 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=432 first_rx_delay_s=0.70 max_gap_s=1.37 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=0.31 max_gap_s=1.25 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.68 max_gap_s=1.25 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=432 first_rx_delay_s=0.64 max_gap_s=1.21 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=426 first_rx_delay_s=0.06 max_gap_s=1.13 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=438 first_rx_delay_s=0.32 max_gap_s=1.30 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node3-1 | [node3] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node3-1 | [node3] outage restored (netem removed) +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=362 first_rx_delay_s=0.75 max_gap_s=5.92 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.74 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=441 first_rx_delay_s=0.89 max_gap_s=0.82 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=263 first_rx_delay_s=0.52 max_gap_s=0.94 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=438 first_rx_delay_s=0.69 max_gap_s=2.71 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.68 max_gap_s=1.18 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=328 first_rx_delay_s=0.19 max_gap_s=1.16 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=443 first_rx_delay_s=0.66 max_gap_s=1.07 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.04 max_gap_s=1.47 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.40 max_gap_s=1.06 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=449 first_rx_delay_s=0.18 max_gap_s=1.44 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.39 max_gap_s=0.37 +node3-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=272 first_rx_delay_s=0.04 max_gap_s=9.03 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=442 first_rx_delay_s=0.37 max_gap_s=0.88 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.39 max_gap_s=1.28 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=358 first_rx_delay_s=0.08 max_gap_s=1.91 +node4-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node4-1 | [node4] signal: post_outage_recovery_done_4 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.37 max_gap_s=0.92 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=450 first_rx_delay_s=0.05 max_gap_s=1.27 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=448 first_rx_delay_s=0.40 max_gap_s=1.31 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.13 max_gap_s=0.35 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node4-1 | [node4] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node4-1 | [node4] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=464 first_rx_delay_s=19.73 max_gap_s=0.92 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.03 max_gap_s=1.56 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=345 first_rx_delay_s=0.56 max_gap_s=0.66 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=368 first_rx_delay_s=0.10 max_gap_s=2.27 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=345 first_rx_delay_s=0.07 max_gap_s=0.61 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=344 first_rx_delay_s=0.11 max_gap_s=1.10 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=336 first_rx_delay_s=0.16 max_gap_s=4.19 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=469 first_rx_delay_s=15.14 max_gap_s=0.99 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=350 first_rx_delay_s=0.02 max_gap_s=1.24 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.21 max_gap_s=1.04 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.46 max_gap_s=1.06 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=0.06 max_gap_s=1.06 +node3-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.25 max_gap_s=1.02 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.38 max_gap_s=0.97 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=28 first_rx_delay_s=7.01 max_gap_s=9.02 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=283 first_rx_delay_s=0.17 max_gap_s=8.04 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node3-1 | [node3] signal: recovery_done_3 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.12 max_gap_s=0.98 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.43 max_gap_s=1.41 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=350 first_rx_delay_s=0.15 max_gap_s=1.21 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.35 max_gap_s=1.01 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260319_201846 (exit=0) +node1-1 | [node1] waiting for TEST_PASS (120s) +node1-1 | [node1] reliability test complete +node1-1 | [node1] Saved logs to /app/results/20260319_201847 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node1-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node0-1 Stopped + Container docker_test-node1-1 Stopped + node1-1 exited with code 0 +node2-1 | [node2] Saved logs to /app/results/20260319_201847 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260319_201847 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260319_201847 (exit=0) + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260319_201846/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260319_201847/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260319_201847/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260319_201847/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260319_201847/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #4 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_28867 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [3/7] WORKDIR /app +#7 CACHED + +#8 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#8 CACHED + +#9 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#9 CACHED + +#10 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#10 CACHED + +#11 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node4-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node1-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node2-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node4-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node0-1 Starting +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node3-1 | [node3] AssignedIp=172.30.0.4 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=0.75 max_gap_s=1.26 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=151 first_rx_delay_s=12.83 max_gap_s=9.73 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=292 first_rx_delay_s=0.89 max_gap_s=7.60 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=343 first_rx_delay_s=0.77 max_gap_s=1.04 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=1.02 max_gap_s=1.22 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=323 first_rx_delay_s=2.34 max_gap_s=2.40 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=275 first_rx_delay_s=1.25 max_gap_s=16.19 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=2.34 max_gap_s=0.95 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.36 max_gap_s=0.92 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=76 first_rx_delay_s=0.34 max_gap_s=0.27 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=281 first_rx_delay_s=8.89 max_gap_s=1.12 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=274 first_rx_delay_s=0.04 max_gap_s=9.60 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.38 max_gap_s=0.38 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.01 max_gap_s=1.15 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=165 first_rx_delay_s=0.33 max_gap_s=9.07 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=73 first_rx_delay_s=0.42 max_gap_s=1.16 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=299 first_rx_delay_s=7.19 max_gap_s=3.09 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=347 first_rx_delay_s=0.35 max_gap_s=0.75 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=348 first_rx_delay_s=0.40 max_gap_s=3.10 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.30 max_gap_s=2.97 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=379 first_rx_delay_s=0.04 max_gap_s=1.13 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=170 first_rx_delay_s=7.69 max_gap_s=9.43 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=383 first_rx_delay_s=0.02 max_gap_s=1.16 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=323 first_rx_delay_s=0.14 max_gap_s=9.61 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=383 first_rx_delay_s=0.19 max_gap_s=1.30 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=387 first_rx_delay_s=0.43 max_gap_s=0.99 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=384 first_rx_delay_s=0.67 max_gap_s=2.69 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=229 first_rx_delay_s=0.73 max_gap_s=14.76 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=339 first_rx_delay_s=7.43 max_gap_s=2.53 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=600 first_rx_delay_s=18.83 max_gap_s=1.77 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=385 first_rx_delay_s=0.55 max_gap_s=4.54 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=385 first_rx_delay_s=0.70 max_gap_s=1.15 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=237 first_rx_delay_s=0.79 max_gap_s=9.15 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=384 first_rx_delay_s=0.25 max_gap_s=1.28 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=233 first_rx_delay_s=14.83 max_gap_s=3.99 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=378 first_rx_delay_s=0.67 max_gap_s=1.12 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=321 first_rx_delay_s=0.23 max_gap_s=10.29 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=392 first_rx_delay_s=0.62 max_gap_s=0.80 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=352 first_rx_delay_s=0.51 max_gap_s=8.87 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=381 first_rx_delay_s=0.55 max_gap_s=1.08 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=777 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=284 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=314 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=368 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=404 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] AssignedIp=172.30.0.2 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.3 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.5 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.6 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node2-1 | [node2] waiting for post_rolling_start (300s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=429 first_rx_delay_s=1.04 max_gap_s=5.81 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=402 first_rx_delay_s=0.80 max_gap_s=2.58 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=363 first_rx_delay_s=1.18 max_gap_s=8.98 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=411 first_rx_delay_s=4.89 max_gap_s=2.18 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=224 first_rx_delay_s=0.98 max_gap_s=9.12 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=410 first_rx_delay_s=0.91 max_gap_s=2.64 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=361 first_rx_delay_s=1.11 max_gap_s=8.97 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=113 first_rx_delay_s=0.44 max_gap_s=9.23 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=288 first_rx_delay_s=0.65 max_gap_s=9.61 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=389 first_rx_delay_s=0.34 max_gap_s=4.02 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=435 first_rx_delay_s=0.06 max_gap_s=1.13 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=369 first_rx_delay_s=0.64 max_gap_s=9.27 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=315 first_rx_delay_s=5.36 max_gap_s=9.14 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=104 first_rx_delay_s=0.34 max_gap_s=9.61 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=345 first_rx_delay_s=9.49 max_gap_s=9.23 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=425 first_rx_delay_s=0.37 max_gap_s=0.97 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=374 first_rx_delay_s=0.66 max_gap_s=8.31 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=434 first_rx_delay_s=0.62 max_gap_s=1.06 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=432 first_rx_delay_s=0.30 max_gap_s=2.12 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=134 first_rx_delay_s=0.02 max_gap_s=9.35 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node2-1 | [node2] waiting for sim_go (120s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1101 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=655 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=516 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=569 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=602 log=/app/results/iroh_after_sim.log +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=231 first_rx_delay_s=7.81 max_gap_s=9.25 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=431 first_rx_delay_s=0.91 max_gap_s=0.45 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=367 first_rx_delay_s=0.63 max_gap_s=12.12 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=240 first_rx_delay_s=0.91 max_gap_s=13.07 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.97 max_gap_s=1.01 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=360 first_rx_delay_s=0.96 max_gap_s=9.46 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=416 first_rx_delay_s=1.06 max_gap_s=2.45 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=346 first_rx_delay_s=0.58 max_gap_s=9.28 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=399 first_rx_delay_s=0.67 max_gap_s=9.37 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=303 first_rx_delay_s=1.35 max_gap_s=8.89 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=391 first_rx_delay_s=0.19 max_gap_s=10.88 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=439 first_rx_delay_s=0.10 max_gap_s=2.72 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=431 first_rx_delay_s=5.29 max_gap_s=2.52 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=440 first_rx_delay_s=0.19 max_gap_s=1.17 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=438 first_rx_delay_s=0.23 max_gap_s=0.99 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=363 first_rx_delay_s=0.49 max_gap_s=7.96 +node3-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=362 first_rx_delay_s=0.13 max_gap_s=9.05 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=370 first_rx_delay_s=0.51 max_gap_s=7.81 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=374 first_rx_delay_s=0.58 max_gap_s=7.96 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=429 first_rx_delay_s=0.18 max_gap_s=4.29 +node2-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node2-1 | [node2] signal: post_simultaneous_done_2 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node1-1 | [node1] waiting for outage_start (300s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node3-1 | [node3] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] outage hold for 25s +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | [node3] netem clean +node2-1 | [node2] netem clean +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.70 max_gap_s=1.24 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=441 first_rx_delay_s=0.75 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=442 first_rx_delay_s=0.82 max_gap_s=1.17 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=442 first_rx_delay_s=0.59 max_gap_s=1.15 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.38 max_gap_s=1.14 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.34 max_gap_s=1.03 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.09 max_gap_s=1.31 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.52 max_gap_s=1.25 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.35 max_gap_s=1.08 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=378 first_rx_delay_s=0.56 max_gap_s=8.26 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.09 max_gap_s=1.26 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=438 first_rx_delay_s=0.39 max_gap_s=2.96 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=429 first_rx_delay_s=0.58 max_gap_s=2.92 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=283 first_rx_delay_s=0.33 max_gap_s=13.42 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.35 max_gap_s=1.21 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.10 max_gap_s=0.62 +node2-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=448 first_rx_delay_s=0.07 max_gap_s=1.17 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=305 first_rx_delay_s=0.28 max_gap_s=9.56 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=386 first_rx_delay_s=0.21 max_gap_s=8.40 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.24 max_gap_s=1.16 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node3-1 | [node3] waiting for recovery_start (300s) +node2-1 | [node2] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.23 max_gap_s=1.11 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.08 max_gap_s=1.14 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.00 max_gap_s=1.12 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=336 first_rx_delay_s=0.11 max_gap_s=1.05 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=332 first_rx_delay_s=0.45 max_gap_s=1.10 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.10 max_gap_s=0.92 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=336 first_rx_delay_s=1.23 max_gap_s=1.14 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=343 first_rx_delay_s=0.50 max_gap_s=1.00 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=344 first_rx_delay_s=0.54 max_gap_s=0.36 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.41 max_gap_s=1.21 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.15 max_gap_s=1.03 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=196 first_rx_delay_s=8.83 max_gap_s=9.04 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=342 first_rx_delay_s=0.17 max_gap_s=0.66 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.36 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=278 first_rx_delay_s=0.45 max_gap_s=9.18 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=292 first_rx_delay_s=3.68 max_gap_s=4.69 +node2-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.07 max_gap_s=1.21 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=347 first_rx_delay_s=0.25 max_gap_s=1.08 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=287 first_rx_delay_s=10.69 max_gap_s=1.16 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.77 max_gap_s=1.22 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260319_202549 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node0-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopped +node4-1 | [node4] Saved logs to /app/results/20260319_202550 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260319_202550 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260319_202550 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260319_202550 (exit=0) + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260319_202549/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260319_202550/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260319_202550/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260319_202550/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260319_202550/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #5 --- +cargo build +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s +cargo build --example tcp_client +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +cargo build --example tcp_server +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example game_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +cargo build --example mesh_check +warning: function `transport_config` is never used + --> src/network.rs:58:4 + | +58 | fn transport_config() -> QuicTransportConfig { + | ^^^^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default + +warning: `iroh-lan` (lib) generated 1 warning + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_20387 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [3/7] WORKDIR /app +#7 CACHED + +#8 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#8 CACHED + +#9 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#9 CACHED + +#10 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node4-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node2-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node0-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node2-1 Starting + Container docker_test-node0-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node1-1 Starting +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=12 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.5 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=341 first_rx_delay_s=1.07 max_gap_s=1.12 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=112 first_rx_delay_s=9.31 max_gap_s=8.97 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=226 first_rx_delay_s=0.43 max_gap_s=7.54 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=341 first_rx_delay_s=0.88 max_gap_s=2.09 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=207 first_rx_delay_s=0.43 max_gap_s=10.72 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=252 first_rx_delay_s=8.44 max_gap_s=2.91 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=341 first_rx_delay_s=1.06 max_gap_s=1.03 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=341 first_rx_delay_s=0.89 max_gap_s=0.95 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=266 first_rx_delay_s=1.02 max_gap_s=9.95 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=306 first_rx_delay_s=0.30 max_gap_s=9.30 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=96 first_rx_delay_s=0.44 max_gap_s=9.54 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=179 first_rx_delay_s=1.04 max_gap_s=9.32 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=150 first_rx_delay_s=0.06 max_gap_s=13.19 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=275 first_rx_delay_s=0.04 max_gap_s=13.96 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=348 first_rx_delay_s=0.18 max_gap_s=1.11 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.68 max_gap_s=1.40 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=349 first_rx_delay_s=0.05 max_gap_s=1.04 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=349 first_rx_delay_s=0.06 max_gap_s=1.05 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.40 max_gap_s=1.24 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=327 first_rx_delay_s=0.16 max_gap_s=4.43 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node4-1 | [node4] waiting for degraded_start (300s) +node0-1 | [node0] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node0-1 | [node0] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=382 first_rx_delay_s=0.13 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=327 first_rx_delay_s=0.11 max_gap_s=8.88 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=385 first_rx_delay_s=0.73 max_gap_s=1.08 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=362 first_rx_delay_s=4.76 max_gap_s=0.75 +node4-1 | MESH_CHECK: PASS +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=383 first_rx_delay_s=0.06 max_gap_s=2.52 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=380 first_rx_delay_s=0.10 max_gap_s=1.07 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=403 first_rx_delay_s=0.18 max_gap_s=6.02 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=392 first_rx_delay_s=0.61 max_gap_s=0.44 +node0-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node0-1 | [node0] signal: degraded_done_0 +node4-1 | [node4] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=231 first_rx_delay_s=9.89 max_gap_s=9.64 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=386 first_rx_delay_s=0.08 max_gap_s=1.24 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=382 first_rx_delay_s=0.63 max_gap_s=0.45 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=399 first_rx_delay_s=0.56 max_gap_s=5.39 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=392 first_rx_delay_s=0.21 max_gap_s=0.63 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=385 first_rx_delay_s=0.27 max_gap_s=2.29 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=376 first_rx_delay_s=0.38 max_gap_s=1.13 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=383 first_rx_delay_s=0.79 max_gap_s=1.18 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=390 first_rx_delay_s=0.24 max_gap_s=1.11 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=392 first_rx_delay_s=0.10 max_gap_s=0.44 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=388 first_rx_delay_s=0.48 max_gap_s=0.54 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=388 first_rx_delay_s=0.25 max_gap_s=3.32 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=758 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=286 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=366 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=336 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=416 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] AssignedIp=172.30.0.2 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=429 first_rx_delay_s=0.65 max_gap_s=1.11 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=366 first_rx_delay_s=0.71 max_gap_s=9.59 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=428 first_rx_delay_s=0.88 max_gap_s=0.62 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=345 first_rx_delay_s=0.81 max_gap_s=9.07 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=398 first_rx_delay_s=6.56 max_gap_s=3.56 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=440 first_rx_delay_s=0.34 max_gap_s=2.95 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=430 first_rx_delay_s=0.62 max_gap_s=1.21 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=413 first_rx_delay_s=4.36 max_gap_s=0.43 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=433 first_rx_delay_s=0.51 max_gap_s=2.17 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=380 first_rx_delay_s=7.46 max_gap_s=1.12 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=431 first_rx_delay_s=0.54 max_gap_s=4.95 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=424 first_rx_delay_s=0.82 max_gap_s=0.93 +node2-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node4-1 | [node4] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=437 first_rx_delay_s=0.60 max_gap_s=1.49 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=379 first_rx_delay_s=0.47 max_gap_s=7.26 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=421 first_rx_delay_s=0.95 max_gap_s=3.33 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=319 first_rx_delay_s=7.42 max_gap_s=8.65 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=411 first_rx_delay_s=0.39 max_gap_s=1.18 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=357 first_rx_delay_s=0.46 max_gap_s=12.36 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=433 first_rx_delay_s=0.28 max_gap_s=2.91 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.47 max_gap_s=1.02 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1050 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=510 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=592 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=578 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=634 log=/app/results/iroh_after_sim.log +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.4 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=425 first_rx_delay_s=0.98 max_gap_s=1.19 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=437 first_rx_delay_s=0.56 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=427 first_rx_delay_s=1.12 max_gap_s=1.22 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=436 first_rx_delay_s=0.67 max_gap_s=1.20 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=429 first_rx_delay_s=0.45 max_gap_s=1.19 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=431 first_rx_delay_s=0.59 max_gap_s=0.41 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=1.08 max_gap_s=0.94 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=364 first_rx_delay_s=0.85 max_gap_s=8.31 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=426 first_rx_delay_s=0.79 max_gap_s=0.47 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=423 first_rx_delay_s=0.94 max_gap_s=5.42 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=0.52 max_gap_s=1.15 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=442 first_rx_delay_s=0.58 max_gap_s=0.93 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=240 first_rx_delay_s=0.96 max_gap_s=9.01 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=432 first_rx_delay_s=0.19 max_gap_s=0.48 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=0.72 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=442 first_rx_delay_s=0.21 max_gap_s=1.12 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=279 first_rx_delay_s=0.18 max_gap_s=1.02 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=440 first_rx_delay_s=0.45 max_gap_s=1.11 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=426 first_rx_delay_s=0.60 max_gap_s=1.03 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=432 first_rx_delay_s=0.20 max_gap_s=1.13 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=446 first_rx_delay_s=0.40 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=442 first_rx_delay_s=0.97 max_gap_s=1.20 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.44 max_gap_s=0.37 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.87 max_gap_s=0.89 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.38 max_gap_s=2.17 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=413 first_rx_delay_s=0.84 max_gap_s=0.93 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.28 max_gap_s=0.37 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=367 first_rx_delay_s=0.95 max_gap_s=5.47 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=443 first_rx_delay_s=0.88 max_gap_s=1.18 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.33 max_gap_s=1.27 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=447 first_rx_delay_s=0.33 max_gap_s=1.07 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.79 max_gap_s=1.15 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=449 first_rx_delay_s=0.02 max_gap_s=0.98 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=398 first_rx_delay_s=0.07 max_gap_s=1.14 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=448 first_rx_delay_s=0.19 max_gap_s=1.02 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=445 first_rx_delay_s=0.56 max_gap_s=2.06 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=382 first_rx_delay_s=0.02 max_gap_s=17.58 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=449 first_rx_delay_s=0.11 max_gap_s=1.34 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=448 first_rx_delay_s=0.45 max_gap_s=1.18 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=448 first_rx_delay_s=0.18 max_gap_s=1.30 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node2-1 | [node2] waiting for recovery_start (300s) +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | [node2] netem clean +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.09 max_gap_s=1.09 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.46 max_gap_s=1.24 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.43 max_gap_s=0.97 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=345 first_rx_delay_s=0.12 max_gap_s=1.29 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +node3-1 | MESH_CHECK: FAIL peer=172.30.0.6 tx=350 rx=0 (expected both > 0) +node3-1 | MESH_CHECK: FAIL peer=172.30.0.6 never received any packet +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=212 first_rx_delay_s=7.04 max_gap_s=9.33 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.42 max_gap_s=0.78 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.45 max_gap_s=0.32 +node3-1 | MESH_CHECK: FAIL +node3-1 | [node3] Saved logs to /app/results/20260319_203302 (exit=1) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=348 first_rx_delay_s=0.36 max_gap_s=0.95 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=348 first_rx_delay_s=0.29 max_gap_s=0.36 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=196 first_rx_delay_s=0.05 max_gap_s=8.52 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.16 max_gap_s=1.04 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) + node3-1 exited with code 1 + Compose Stopping Aborting on container exit... + Container docker_test-node4-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node3-1 Stopped +node1-1 | [node1] Saved logs to /app/results/20260319_203302 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260319_203302 (exit=0) +node0-1 | [node0] Saved logs to /app/results/20260319_203302 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260319_203302 (exit=0) + Container docker_test-node0-1 Stopped + node0-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260319_203302/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260319_203302/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260319_203302/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [FAIL] recovery +MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3: docker_test/results_reliability/node3/20260319_203302/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [FAIL] recovery +MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +MESH_CHECK: peer=172.30.0.6 tx=350 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +MESH_CHECK: FAIL peer=172.30.0.6 tx=350 rx=0 (expected both > 0) +MESH_CHECK: FAIL peer=172.30.0.6 never received any packet +MESH_CHECK: peer=172.30.0.2 tx=350 rx=212 first_rx_delay_s=7.04 max_gap_s=9.33 +MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.42 max_gap_s=0.78 +MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.45 max_gap_s=0.32 +MESH_CHECK: FAIL +node4: docker_test/results_reliability/node4/20260319_203302/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [FAIL] recovery +MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +======================================================== +RELIABILITY RESULT: FAIL +make: *** [Makefile:29: reliability-test] Error 1 diff --git a/docker_test/test_results_conn20_read8_weird_transport_conf.log b/docker_test/test_results_conn20_read8_weird_transport_conf.log new file mode 100644 index 0000000..8ff6f02 --- /dev/null +++ b/docker_test/test_results_conn20_read8_weird_transport_conf.log @@ -0,0 +1,3606 @@ +--- Run #1 --- +cargo build + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.07s +cargo build --example tcp_client + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.51s +cargo build --example tcp_server + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.58s +cargo build --example game_check + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.83s +cargo build --example mesh_check + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.77s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_19885 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#7 CACHED + +#8 [3/7] WORKDIR /app +#8 CACHED + +#9 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#9 CACHED + +#10 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node1-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node1-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node0-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node3-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node0-1 Starting + Container docker_test-node0-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] AssignedIp=172.30.0.3 +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node3-1 | [node3] waiting for all_ready (300s) +node2-1 | [node2] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node3-1 | [node3] waiting for baseline_start (300s) +node4-1 | [node4] waiting for baseline_start (300s) +node1-1 | [node1] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node4-1 | [node4] netem clean +node1-1 | [node1] netem clean +node3-1 | [node3] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=240 first_rx_delay_s=0.99 max_gap_s=12.25 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=0.97 max_gap_s=1.39 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=340 first_rx_delay_s=0.87 max_gap_s=0.94 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=341 first_rx_delay_s=1.24 max_gap_s=0.74 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=345 first_rx_delay_s=7.20 max_gap_s=6.90 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=264 first_rx_delay_s=0.49 max_gap_s=11.04 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=8.46 max_gap_s=1.28 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=335 first_rx_delay_s=0.02 max_gap_s=1.36 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=50 first_rx_delay_s=2.83 max_gap_s=0.71 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=242 first_rx_delay_s=0.02 max_gap_s=13.09 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.49 max_gap_s=1.30 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.39 max_gap_s=0.34 +node2-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=344 first_rx_delay_s=0.51 max_gap_s=1.18 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=342 first_rx_delay_s=0.02 max_gap_s=1.03 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=224 first_rx_delay_s=0.39 max_gap_s=12.96 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=318 first_rx_delay_s=5.37 max_gap_s=0.41 +node1-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.39 max_gap_s=1.00 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=44 first_rx_delay_s=0.32 max_gap_s=0.27 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.02 max_gap_s=1.42 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.49 max_gap_s=2.41 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node2-1 | [node2] signal: baseline_done_2 +node1-1 | [node1] signal: baseline_done_1 +node4-1 | [node4] waiting for baseline_complete (600s) +node2-1 | [node2] waiting for baseline_complete (600s) +node1-1 | [node1] waiting for baseline_complete (600s) +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node1-1 | [node1] waiting for degraded_start (300s) +node2-1 | [node2] waiting for degraded_start (300s) +node3-1 | [node3] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=379 first_rx_delay_s=0.02 max_gap_s=2.49 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=388 first_rx_delay_s=0.08 max_gap_s=2.15 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=378 first_rx_delay_s=0.10 max_gap_s=2.43 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=376 first_rx_delay_s=0.09 max_gap_s=9.39 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=287 first_rx_delay_s=0.65 max_gap_s=12.52 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=388 first_rx_delay_s=0.45 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=384 first_rx_delay_s=0.63 max_gap_s=3.13 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=302 first_rx_delay_s=11.32 max_gap_s=1.28 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=275 first_rx_delay_s=0.14 max_gap_s=12.93 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=582 first_rx_delay_s=2.43 max_gap_s=1.44 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=368 first_rx_delay_s=0.63 max_gap_s=1.20 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=383 first_rx_delay_s=0.71 max_gap_s=1.29 +node2-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=381 first_rx_delay_s=0.27 max_gap_s=1.24 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=49 first_rx_delay_s=13.27 max_gap_s=13.34 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=304 first_rx_delay_s=11.31 max_gap_s=0.53 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=295 first_rx_delay_s=11.74 max_gap_s=1.33 +node1-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node2-1 | [node2] signal: degraded_done_2 +node1-1 | [node1] signal: degraded_done_1 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=578 first_rx_delay_s=2.28 max_gap_s=4.55 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=355 first_rx_delay_s=0.68 max_gap_s=3.41 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=392 first_rx_delay_s=0.09 max_gap_s=1.55 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=86 first_rx_delay_s=0.40 max_gap_s=26.74 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] waiting for degraded_complete (600s) +node2-1 | [node2] waiting for degraded_complete (600s) +node1-1 | [node1] waiting for degraded_complete (600s) +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=756 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=302 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=326 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=376 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=406 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.3 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.6 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=437 first_rx_delay_s=0.73 max_gap_s=2.54 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=399 first_rx_delay_s=0.73 max_gap_s=4.77 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=423 first_rx_delay_s=0.97 max_gap_s=0.42 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=434 first_rx_delay_s=0.70 max_gap_s=1.30 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=383 first_rx_delay_s=12.72 max_gap_s=0.38 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=378 first_rx_delay_s=6.36 max_gap_s=1.17 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=290 first_rx_delay_s=13.81 max_gap_s=9.65 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.81 max_gap_s=1.41 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=376 first_rx_delay_s=0.67 max_gap_s=1.34 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=435 first_rx_delay_s=0.89 max_gap_s=2.43 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=435 first_rx_delay_s=0.64 max_gap_s=1.42 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=435 first_rx_delay_s=0.46 max_gap_s=0.59 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=437 first_rx_delay_s=0.56 max_gap_s=1.92 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=433 first_rx_delay_s=0.55 max_gap_s=0.43 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=253 first_rx_delay_s=7.19 max_gap_s=12.43 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=365 first_rx_delay_s=23.11 max_gap_s=1.18 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=379 first_rx_delay_s=8.93 max_gap_s=1.30 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=259 first_rx_delay_s=0.30 max_gap_s=12.98 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=426 first_rx_delay_s=0.22 max_gap_s=1.07 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=75 first_rx_delay_s=0.15 max_gap_s=13.24 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1079 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=544 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=616 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=636 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=548 log=/app/results/iroh_after_sim.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.5 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=423 first_rx_delay_s=1.06 max_gap_s=1.18 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=0.99 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=422 first_rx_delay_s=0.64 max_gap_s=1.62 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=427 first_rx_delay_s=0.96 max_gap_s=0.99 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.98 max_gap_s=2.29 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=433 first_rx_delay_s=0.88 max_gap_s=1.21 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=423 first_rx_delay_s=0.91 max_gap_s=1.37 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=440 first_rx_delay_s=0.51 max_gap_s=0.46 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=418 first_rx_delay_s=0.75 max_gap_s=1.27 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=439 first_rx_delay_s=0.30 max_gap_s=1.29 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=422 first_rx_delay_s=0.66 max_gap_s=1.18 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=441 first_rx_delay_s=0.14 max_gap_s=1.11 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=338 first_rx_delay_s=0.27 max_gap_s=4.17 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=223 first_rx_delay_s=0.18 max_gap_s=13.43 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=427 first_rx_delay_s=0.50 max_gap_s=0.61 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=428 first_rx_delay_s=0.76 max_gap_s=2.74 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=436 first_rx_delay_s=0.06 max_gap_s=1.44 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=327 first_rx_delay_s=13.73 max_gap_s=1.27 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=434 first_rx_delay_s=0.11 max_gap_s=0.45 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=434 first_rx_delay_s=0.48 max_gap_s=0.38 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=445 first_rx_delay_s=0.57 max_gap_s=1.47 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=442 first_rx_delay_s=0.88 max_gap_s=0.36 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=284 first_rx_delay_s=0.78 max_gap_s=0.38 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=367 first_rx_delay_s=0.85 max_gap_s=9.73 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=443 first_rx_delay_s=0.72 max_gap_s=2.69 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=442 first_rx_delay_s=0.81 max_gap_s=1.20 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.34 max_gap_s=1.20 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=341 first_rx_delay_s=0.80 max_gap_s=0.53 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=349 first_rx_delay_s=0.02 max_gap_s=12.13 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=308 first_rx_delay_s=0.18 max_gap_s=13.10 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=278 first_rx_delay_s=0.49 max_gap_s=15.29 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.47 max_gap_s=1.01 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.41 max_gap_s=0.79 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=445 first_rx_delay_s=0.47 max_gap_s=1.07 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=228 first_rx_delay_s=0.00 max_gap_s=14.29 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=341 first_rx_delay_s=0.16 max_gap_s=0.42 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_outage_recovery_done_3 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=449 first_rx_delay_s=0.05 max_gap_s=2.46 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=450 first_rx_delay_s=0.10 max_gap_s=1.45 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=446 first_rx_delay_s=0.39 max_gap_s=1.36 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=345 first_rx_delay_s=0.33 max_gap_s=18.77 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=351 first_rx_delay_s=0.48 max_gap_s=1.29 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.47 max_gap_s=1.18 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=357 first_rx_delay_s=0.00 max_gap_s=0.99 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=402 first_rx_delay_s=15.05 max_gap_s=1.47 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=122 first_rx_delay_s=1.75 max_gap_s=13.23 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=328 first_rx_delay_s=0.02 max_gap_s=1.15 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.27 max_gap_s=1.37 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.11 max_gap_s=1.17 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=376 first_rx_delay_s=7.07 max_gap_s=1.37 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=198 first_rx_delay_s=26.76 max_gap_s=1.30 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.05 max_gap_s=1.36 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=337 first_rx_delay_s=1.06 max_gap_s=0.31 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=463 first_rx_delay_s=0.94 max_gap_s=9.01 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=352 first_rx_delay_s=1.45 max_gap_s=2.50 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.49 max_gap_s=1.28 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.36 max_gap_s=0.52 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=218 first_rx_delay_s=26.61 max_gap_s=0.51 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.09 max_gap_s=1.07 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.16 max_gap_s=1.13 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.47 max_gap_s=1.13 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260320_010659 (exit=0) +node1-1 | [node1] waiting for TEST_PASS (120s) +node1-1 | [node1] reliability test complete +node1-1 | [node1] Saved logs to /app/results/20260320_010659 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node1-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopped +node3-1 | [node3] Saved logs to /app/results/20260320_010659 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260320_010659 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_010659 (exit=0) + Container docker_test-node1-1 Stopped + node1-1 exited with code 0 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_010659/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_010659/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_010659/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_010659/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_010659/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #2 --- +cargo build + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.03s +cargo build --example tcp_client + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.35s +cargo build --example tcp_server + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.37s +cargo build --example game_check + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.42s +cargo build --example mesh_check + Compiling iroh-lan v1.0.0 (/home/i3/Documents/code/iroh-lan) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_26917 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#7 CACHED + +#8 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#8 CACHED + +#9 [3/7] WORKDIR /app +#9 CACHED + +#10 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node0-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node3-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node2-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node3-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node0-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node4-1 Starting +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node1-1 | [node1] started iroh pid=11 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node2-1 | [node2] AssignedIp=172.30.0.6 +node4-1 | [node4] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.3 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | [node4] waiting for baseline_start (300s) +node2-1 | [node2] waiting for baseline_start (300s) +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] netem clean +node2-1 | [node2] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=150 first_rx_delay_s=0.74 max_gap_s=13.12 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=123 first_rx_delay_s=0.85 max_gap_s=13.23 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=119 first_rx_delay_s=11.75 max_gap_s=13.19 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=263 first_rx_delay_s=5.36 max_gap_s=1.10 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=350 first_rx_delay_s=0.03 max_gap_s=2.51 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=237 first_rx_delay_s=0.48 max_gap_s=13.01 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=204 first_rx_delay_s=0.49 max_gap_s=15.68 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.49 max_gap_s=0.32 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=293 first_rx_delay_s=7.84 max_gap_s=1.14 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.37 max_gap_s=3.15 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=266 first_rx_delay_s=10.90 max_gap_s=2.19 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=347 first_rx_delay_s=0.48 max_gap_s=0.39 +node4-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=250 first_rx_delay_s=8.35 max_gap_s=9.28 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=350 first_rx_delay_s=0.02 max_gap_s=0.35 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=297 first_rx_delay_s=7.41 max_gap_s=1.12 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.37 max_gap_s=1.09 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node4-1 | [node4] signal: baseline_done_4 +node2-1 | [node2] waiting for baseline_complete (600s) +node4-1 | [node4] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=314 first_rx_delay_s=0.31 max_gap_s=3.53 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.06 max_gap_s=2.67 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=340 first_rx_delay_s=0.30 max_gap_s=1.03 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.42 max_gap_s=8.52 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] waiting for degraded_start (300s) +node4-1 | [node4] waiting for degraded_start (300s) +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] netem degraded on tun0 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=381 first_rx_delay_s=0.19 max_gap_s=0.81 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=386 first_rx_delay_s=0.03 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=368 first_rx_delay_s=4.60 max_gap_s=0.38 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=97 first_rx_delay_s=4.53 max_gap_s=13.38 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=391 first_rx_delay_s=0.32 max_gap_s=3.02 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=386 first_rx_delay_s=0.56 max_gap_s=0.47 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=383 first_rx_delay_s=0.68 max_gap_s=1.22 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=404 first_rx_delay_s=2.69 max_gap_s=1.26 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=379 first_rx_delay_s=0.56 max_gap_s=0.45 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=378 first_rx_delay_s=0.69 max_gap_s=1.02 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=392 first_rx_delay_s=0.31 max_gap_s=2.44 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=164 first_rx_delay_s=0.75 max_gap_s=13.20 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] waiting for degraded_complete (600s) +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=0.61 max_gap_s=1.13 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=387 first_rx_delay_s=0.67 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=388 first_rx_delay_s=0.31 max_gap_s=1.36 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=384 first_rx_delay_s=0.53 max_gap_s=1.14 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=366 first_rx_delay_s=0.64 max_gap_s=3.03 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=387 first_rx_delay_s=0.70 max_gap_s=1.31 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=382 first_rx_delay_s=0.43 max_gap_s=1.15 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=391 first_rx_delay_s=0.19 max_gap_s=0.39 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node1-1 | [node1] waiting for rolling_go (120s) +node2-1 | [node2] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=871 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=413 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=378 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=473 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=336 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.6 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.3 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=420 first_rx_delay_s=0.97 max_gap_s=0.53 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=414 first_rx_delay_s=1.03 max_gap_s=1.07 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=428 first_rx_delay_s=1.11 max_gap_s=1.32 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.64 max_gap_s=1.19 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=431 first_rx_delay_s=0.56 max_gap_s=1.13 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=425 first_rx_delay_s=1.05 max_gap_s=1.24 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=431 first_rx_delay_s=0.98 max_gap_s=1.09 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=357 first_rx_delay_s=0.96 max_gap_s=39.22 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=305 first_rx_delay_s=2.86 max_gap_s=1.01 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=432 first_rx_delay_s=0.19 max_gap_s=1.23 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=46 first_rx_delay_s=8.34 max_gap_s=13.16 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=301 first_rx_delay_s=0.32 max_gap_s=35.98 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=329 first_rx_delay_s=0.63 max_gap_s=19.01 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=305 first_rx_delay_s=0.48 max_gap_s=12.72 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=430 first_rx_delay_s=0.15 max_gap_s=1.30 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=326 first_rx_delay_s=0.12 max_gap_s=9.33 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=433 first_rx_delay_s=0.25 max_gap_s=1.26 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=373 first_rx_delay_s=0.47 max_gap_s=1.26 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=441 first_rx_delay_s=0.11 max_gap_s=1.24 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=429 first_rx_delay_s=0.62 max_gap_s=2.84 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1205 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=744 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=586 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=690 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=634 log=/app/results/iroh_after_sim.log +node1-1 | [node1] AssignedIp=172.30.0.2 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.5 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.6 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=1.03 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=428 first_rx_delay_s=0.76 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=426 first_rx_delay_s=1.27 max_gap_s=2.48 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=323 first_rx_delay_s=1.02 max_gap_s=13.61 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=382 first_rx_delay_s=31.51 max_gap_s=0.72 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=200 first_rx_delay_s=7.27 max_gap_s=13.20 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=108 first_rx_delay_s=12.28 max_gap_s=13.73 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=430 first_rx_delay_s=0.63 max_gap_s=1.13 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=435 first_rx_delay_s=0.12 max_gap_s=0.86 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=269 first_rx_delay_s=0.34 max_gap_s=22.78 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=398 first_rx_delay_s=0.55 max_gap_s=3.40 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.71 max_gap_s=2.99 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=363 first_rx_delay_s=9.77 max_gap_s=3.05 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=59 first_rx_delay_s=9.74 max_gap_s=13.22 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=286 first_rx_delay_s=6.86 max_gap_s=13.36 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=437 first_rx_delay_s=0.13 max_gap_s=2.65 +node3-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=429 first_rx_delay_s=0.21 max_gap_s=3.09 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=44 first_rx_delay_s=8.34 max_gap_s=13.20 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=336 first_rx_delay_s=0.13 max_gap_s=13.17 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=97 first_rx_delay_s=10.29 max_gap_s=13.78 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node3-1 | [node3] signal: post_simultaneous_done_3 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node3-1 | [node3] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node3-1 | [node3] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node2-1 | [node2] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node3-1 | [node3] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] netem clean +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=442 first_rx_delay_s=0.81 max_gap_s=1.08 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=440 first_rx_delay_s=1.07 max_gap_s=1.11 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=444 first_rx_delay_s=0.80 max_gap_s=0.35 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=340 first_rx_delay_s=0.82 max_gap_s=11.34 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=445 first_rx_delay_s=0.45 max_gap_s=2.44 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=450 first_rx_delay_s=0.07 max_gap_s=0.38 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.69 max_gap_s=0.93 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=447 first_rx_delay_s=0.43 max_gap_s=1.18 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.32 max_gap_s=0.98 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=450 first_rx_delay_s=0.01 max_gap_s=1.25 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.37 max_gap_s=1.15 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.14 max_gap_s=1.17 +node2-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=323 first_rx_delay_s=0.01 max_gap_s=13.12 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=256 first_rx_delay_s=0.63 max_gap_s=19.18 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=317 first_rx_delay_s=0.21 max_gap_s=13.22 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=447 first_rx_delay_s=0.37 max_gap_s=1.50 +node3-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node3-1 | [node3] signal: post_outage_recovery_done_3 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.27 max_gap_s=2.27 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=449 first_rx_delay_s=0.95 max_gap_s=1.22 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=447 first_rx_delay_s=0.32 max_gap_s=0.34 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.09 max_gap_s=0.95 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node0-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node2-1 | [node2] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node2-1 | [node2] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=344 first_rx_delay_s=0.04 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.21 max_gap_s=1.14 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.01 max_gap_s=0.52 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=345 first_rx_delay_s=0.06 max_gap_s=0.93 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.43 max_gap_s=1.17 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=350 first_rx_delay_s=0.11 max_gap_s=1.05 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.46 max_gap_s=1.05 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=84 first_rx_delay_s=12.87 max_gap_s=13.17 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=300 first_rx_delay_s=0.27 max_gap_s=12.50 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=297 first_rx_delay_s=0.94 max_gap_s=6.81 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.37 max_gap_s=0.76 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=369 first_rx_delay_s=6.42 max_gap_s=0.80 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=351 first_rx_delay_s=0.05 max_gap_s=0.33 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.34 max_gap_s=0.39 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=1.00 max_gap_s=0.75 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.40 max_gap_s=0.36 +node2-1 | MESH_CHECK: PASS +node3-1 | [node3] waiting for recovery_complete (600s) +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=351 first_rx_delay_s=0.46 max_gap_s=0.96 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.29 max_gap_s=1.16 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=351 first_rx_delay_s=0.00 max_gap_s=0.33 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=83 first_rx_delay_s=0.40 max_gap_s=13.30 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260320_011422 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node4-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node0-1 Stopped +node1-1 | [node1] Saved logs to /app/results/20260320_011422 (exit=0) +node4-1 | [node4] Saved logs to /app/results/20260320_011422 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_011422 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260320_011422 (exit=0) + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_011422/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_011422/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_011422/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_011422/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_011422/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #3 --- +cargo build + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.29s +cargo build --example tcp_client + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s +cargo build --example tcp_server + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example game_check + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example mesh_check + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_20431 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#7 CACHED + +#8 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#8 CACHED + +#9 [3/7] WORKDIR /app +#9 CACHED + +#10 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node3-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node2-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node3-1 Recreated + Container docker_test-node0-1 Recreated + Container docker_test-node1-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node0-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node2-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=11 log=/app/results/iroh.log +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.2 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.5 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node2-1 | [node2] AssignedIp=172.30.0.6 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node2-1 | [node2] waiting for baseline_start (300s) +node1-1 | [node1] netem clean +node2-1 | [node2] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=0.90 max_gap_s=1.00 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=342 first_rx_delay_s=0.78 max_gap_s=1.10 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=236 first_rx_delay_s=0.80 max_gap_s=12.88 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=342 first_rx_delay_s=0.98 max_gap_s=0.68 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=246 first_rx_delay_s=0.38 max_gap_s=24.68 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=2.49 max_gap_s=1.04 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=91 first_rx_delay_s=0.36 max_gap_s=13.12 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=348 first_rx_delay_s=0.12 max_gap_s=0.93 +node1-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.45 max_gap_s=0.34 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=71 first_rx_delay_s=0.65 max_gap_s=25.74 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=350 first_rx_delay_s=0.12 max_gap_s=8.55 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=253 first_rx_delay_s=0.56 max_gap_s=20.77 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.31 max_gap_s=0.32 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=224 first_rx_delay_s=0.35 max_gap_s=13.31 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=351 first_rx_delay_s=0.08 max_gap_s=0.76 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=312 first_rx_delay_s=0.44 max_gap_s=1.00 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.43 max_gap_s=2.61 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.51 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=351 first_rx_delay_s=0.08 max_gap_s=1.14 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.33 max_gap_s=0.97 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node2-1 | [node2] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node2-1 | [node2] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=174 first_rx_delay_s=0.02 max_gap_s=0.96 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=380 first_rx_delay_s=0.09 max_gap_s=1.13 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=389 first_rx_delay_s=0.81 max_gap_s=0.85 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=384 first_rx_delay_s=0.03 max_gap_s=1.08 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=233 first_rx_delay_s=0.74 max_gap_s=12.92 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=375 first_rx_delay_s=0.64 max_gap_s=3.06 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=101 first_rx_delay_s=8.82 max_gap_s=12.86 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=388 first_rx_delay_s=0.17 max_gap_s=1.15 +node1-1 | MESH_CHECK: PASS +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=167 first_rx_delay_s=0.17 max_gap_s=1.02 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=383 first_rx_delay_s=0.09 max_gap_s=0.87 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=230 first_rx_delay_s=20.85 max_gap_s=10.53 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=383 first_rx_delay_s=0.71 max_gap_s=1.07 +node2-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node2-1 | [node2] signal: degraded_done_2 +node1-1 | [node1] waiting for degraded_complete (600s) +node2-1 | [node2] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=1.44 max_gap_s=1.14 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=321 first_rx_delay_s=9.18 max_gap_s=0.54 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=385 first_rx_delay_s=0.65 max_gap_s=1.17 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=386 first_rx_delay_s=0.13 max_gap_s=1.13 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=367 first_rx_delay_s=0.68 max_gap_s=0.93 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=362 first_rx_delay_s=0.43 max_gap_s=2.61 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=388 first_rx_delay_s=0.57 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=391 first_rx_delay_s=0.21 max_gap_s=1.14 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=822 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=340 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=408 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=432 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=296 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] AssignedIp=172.30.0.2 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.3 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.4 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.5 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node3-1 | [node3] waiting for post_rolling_start (300s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | [node2] waiting for post_rolling_start (300s) +node0-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=360 first_rx_delay_s=16.76 max_gap_s=1.04 +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=80 first_rx_delay_s=0.94 max_gap_s=0.38 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=437 first_rx_delay_s=0.40 max_gap_s=2.22 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=421 first_rx_delay_s=1.00 max_gap_s=3.42 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=430 first_rx_delay_s=0.95 max_gap_s=2.23 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=72 first_rx_delay_s=6.78 max_gap_s=13.14 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=428 first_rx_delay_s=0.65 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=380 first_rx_delay_s=0.38 max_gap_s=6.39 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=322 first_rx_delay_s=0.31 max_gap_s=13.20 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=438 first_rx_delay_s=0.54 max_gap_s=1.29 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=431 first_rx_delay_s=0.86 max_gap_s=0.45 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=430 first_rx_delay_s=0.87 max_gap_s=1.20 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=324 first_rx_delay_s=38.16 max_gap_s=0.31 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=443 first_rx_delay_s=0.33 max_gap_s=1.12 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=387 first_rx_delay_s=6.83 max_gap_s=0.58 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=425 first_rx_delay_s=0.49 max_gap_s=1.17 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=433 first_rx_delay_s=0.47 max_gap_s=0.76 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=442 first_rx_delay_s=0.16 max_gap_s=1.29 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=234 first_rx_delay_s=0.09 max_gap_s=21.68 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=383 first_rx_delay_s=6.79 max_gap_s=2.67 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node2-1 | [node2] waiting for sim_go (120s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1145 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=667 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=712 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=552 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=591 log=/app/results/iroh_after_sim.log +node1-1 | [node1] AssignedIp=172.30.0.4 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=233 first_rx_delay_s=1.03 max_gap_s=20.47 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=429 first_rx_delay_s=1.14 max_gap_s=0.41 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=419 first_rx_delay_s=0.98 max_gap_s=0.97 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=324 first_rx_delay_s=0.51 max_gap_s=13.02 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=423 first_rx_delay_s=0.86 max_gap_s=2.77 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=233 first_rx_delay_s=0.60 max_gap_s=12.91 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=433 first_rx_delay_s=0.96 max_gap_s=0.52 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=137 first_rx_delay_s=9.54 max_gap_s=13.38 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=418 first_rx_delay_s=0.52 max_gap_s=2.82 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=250 first_rx_delay_s=1.00 max_gap_s=13.23 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=435 first_rx_delay_s=0.54 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=325 first_rx_delay_s=9.41 max_gap_s=6.33 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=431 first_rx_delay_s=0.53 max_gap_s=1.14 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=435 first_rx_delay_s=0.19 max_gap_s=1.12 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=226 first_rx_delay_s=0.27 max_gap_s=13.30 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=221 first_rx_delay_s=0.80 max_gap_s=12.76 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=60 first_rx_delay_s=0.49 max_gap_s=13.43 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=426 first_rx_delay_s=0.25 max_gap_s=0.35 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.54 max_gap_s=2.60 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=431 first_rx_delay_s=0.18 max_gap_s=0.98 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] waiting for outage_start (300s) +node4-1 | [node4] outage hold for 25s +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node3-1 | [node3] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=441 first_rx_delay_s=0.79 max_gap_s=0.33 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=441 first_rx_delay_s=0.77 max_gap_s=1.16 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=268 first_rx_delay_s=1.45 max_gap_s=13.39 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=438 first_rx_delay_s=0.14 max_gap_s=1.23 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=441 first_rx_delay_s=0.75 max_gap_s=1.08 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=447 first_rx_delay_s=0.29 max_gap_s=8.71 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=333 first_rx_delay_s=0.82 max_gap_s=17.80 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=441 first_rx_delay_s=0.75 max_gap_s=2.15 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.03 max_gap_s=2.61 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=267 first_rx_delay_s=0.38 max_gap_s=13.03 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=259 first_rx_delay_s=0.36 max_gap_s=1.19 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=449 first_rx_delay_s=0.11 max_gap_s=2.08 +node4-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=264 first_rx_delay_s=0.45 max_gap_s=1.09 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=447 first_rx_delay_s=0.38 max_gap_s=1.00 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.08 max_gap_s=0.97 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=341 first_rx_delay_s=0.13 max_gap_s=12.23 +node3-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node3-1 | [node3] signal: post_outage_recovery_done_3 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=349 first_rx_delay_s=0.42 max_gap_s=11.89 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.05 max_gap_s=1.03 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=449 first_rx_delay_s=0.08 max_gap_s=1.21 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=447 first_rx_delay_s=0.33 max_gap_s=1.07 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node4-1 | [node4] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node4-1 | [node4] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=115 first_rx_delay_s=5.66 max_gap_s=12.93 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.00 max_gap_s=0.58 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=346 first_rx_delay_s=0.39 max_gap_s=0.36 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.10 max_gap_s=0.73 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.51 max_gap_s=0.32 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.06 max_gap_s=1.05 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.07 max_gap_s=0.73 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.02 max_gap_s=1.19 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=347 first_rx_delay_s=0.51 max_gap_s=1.39 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=43 first_rx_delay_s=6.34 max_gap_s=12.91 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.14 max_gap_s=0.32 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=349 first_rx_delay_s=0.14 max_gap_s=1.18 +node3-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=310 first_rx_delay_s=6.25 max_gap_s=2.16 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.14 max_gap_s=2.46 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=349 first_rx_delay_s=0.14 max_gap_s=1.09 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=329 first_rx_delay_s=5.79 max_gap_s=2.48 +node4-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node4-1 | [node4] signal: recovery_done_4 +node3-1 | [node3] waiting for recovery_complete (600s) +node4-1 | [node4] waiting for recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=349 first_rx_delay_s=0.11 max_gap_s=1.09 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=347 first_rx_delay_s=0.44 max_gap_s=1.20 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=98 first_rx_delay_s=0.45 max_gap_s=13.13 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.11 max_gap_s=1.12 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node1-1 | [node1] waiting for TEST_PASS (120s) +node0-1 | [node0] Saved logs to /app/results/20260320_012132 (exit=0) +node1-1 | [node1] reliability test complete +node1-1 | [node1] Saved logs to /app/results/20260320_012132 (exit=0) + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... + Container docker_test-node3-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node0-1 Stopped + Container docker_test-node1-1 Stopped + node1-1 exited with code 0 +node4-1 | [node4] Saved logs to /app/results/20260320_012132 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_012132 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260320_012132 (exit=0) + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_012132/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_012132/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_012132/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_012132/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_012132/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #4 --- +cargo build + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.37s +cargo build --example tcp_client + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +cargo build --example tcp_server + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s +cargo build --example game_check + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +cargo build --example mesh_check + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_2934 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#7 CACHED + +#8 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#8 CACHED + +#9 [3/7] WORKDIR /app +#9 CACHED + +#10 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#10 CACHED + +#11 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node3-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node3-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node0-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node0-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node1-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node3-1 Starting +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=10 log=/app/results/iroh.log +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node4-1 | [node4] AssignedIp=172.30.0.3 +node1-1 | [node1] AssignedIp=172.30.0.5 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for baseline_start (300s) +node4-1 | [node4] waiting for baseline_start (300s) +node4-1 | [node4] netem clean +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=99 first_rx_delay_s=13.40 max_gap_s=3.94 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=239 first_rx_delay_s=11.78 max_gap_s=9.20 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.42 max_gap_s=1.02 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.42 max_gap_s=0.37 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=201 first_rx_delay_s=6.91 max_gap_s=10.46 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.39 max_gap_s=1.18 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=238 first_rx_delay_s=0.37 max_gap_s=19.56 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=146 first_rx_delay_s=0.45 max_gap_s=8.58 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=330 first_rx_delay_s=0.53 max_gap_s=9.60 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=345 first_rx_delay_s=0.36 max_gap_s=1.29 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.41 max_gap_s=0.95 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=74 first_rx_delay_s=0.45 max_gap_s=13.85 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=345 first_rx_delay_s=0.41 max_gap_s=2.27 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=347 first_rx_delay_s=0.35 max_gap_s=0.79 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.35 max_gap_s=0.93 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=159 first_rx_delay_s=13.86 max_gap_s=0.47 +node1-1 | MESH_CHECK: PASS +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.35 max_gap_s=2.84 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=279 first_rx_delay_s=9.38 max_gap_s=0.83 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=259 first_rx_delay_s=0.40 max_gap_s=18.42 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=178 first_rx_delay_s=0.35 max_gap_s=12.99 +node4-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for degraded_start (300s) +node4-1 | [node4] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node4-1 | [node4] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=383 first_rx_delay_s=0.48 max_gap_s=0.86 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=388 first_rx_delay_s=0.76 max_gap_s=1.14 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=290 first_rx_delay_s=0.69 max_gap_s=3.34 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=402 first_rx_delay_s=0.27 max_gap_s=4.72 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: degraded_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=415 first_rx_delay_s=0.24 max_gap_s=1.30 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=396 first_rx_delay_s=0.68 max_gap_s=1.17 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=292 first_rx_delay_s=12.25 max_gap_s=1.06 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=169 first_rx_delay_s=0.53 max_gap_s=5.26 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=383 first_rx_delay_s=0.67 max_gap_s=1.01 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=280 first_rx_delay_s=7.84 max_gap_s=1.06 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=374 first_rx_delay_s=0.62 max_gap_s=1.18 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=390 first_rx_delay_s=0.32 max_gap_s=0.87 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.64 max_gap_s=1.10 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=154 first_rx_delay_s=13.22 max_gap_s=0.49 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=284 first_rx_delay_s=0.04 max_gap_s=11.46 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=405 first_rx_delay_s=0.29 max_gap_s=0.43 +node4-1 | MESH_CHECK: PASS +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=387 first_rx_delay_s=0.74 max_gap_s=1.09 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=166 first_rx_delay_s=0.50 max_gap_s=14.21 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=425 first_rx_delay_s=3.84 max_gap_s=2.44 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=388 first_rx_delay_s=0.49 max_gap_s=1.17 +node1-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node1-1 | [node1] signal: degraded_done_1 +node4-1 | [node4] waiting for degraded_complete (600s) +node1-1 | [node1] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node2-1 | [node2] waiting for rolling_go (120s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node1-1 | [node1] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=796 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=307 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=358 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=376 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=424 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.5 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for post_rolling_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=426 first_rx_delay_s=1.07 max_gap_s=1.34 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=435 first_rx_delay_s=0.63 max_gap_s=0.41 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=311 first_rx_delay_s=0.81 max_gap_s=12.51 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=432 first_rx_delay_s=0.61 max_gap_s=1.09 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=425 first_rx_delay_s=0.58 max_gap_s=1.98 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=431 first_rx_delay_s=0.43 max_gap_s=1.10 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=433 first_rx_delay_s=0.74 max_gap_s=1.34 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=214 first_rx_delay_s=0.59 max_gap_s=14.32 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=425 first_rx_delay_s=0.51 max_gap_s=0.79 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=355 first_rx_delay_s=0.51 max_gap_s=2.16 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=355 first_rx_delay_s=0.74 max_gap_s=19.19 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=324 first_rx_delay_s=0.76 max_gap_s=13.66 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=319 first_rx_delay_s=0.57 max_gap_s=13.16 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=329 first_rx_delay_s=0.45 max_gap_s=13.22 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=382 first_rx_delay_s=31.01 max_gap_s=1.12 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=429 first_rx_delay_s=0.48 max_gap_s=0.70 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=434 first_rx_delay_s=0.25 max_gap_s=1.39 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=162 first_rx_delay_s=7.79 max_gap_s=19.31 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=330 first_rx_delay_s=0.40 max_gap_s=11.84 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=434 first_rx_delay_s=0.39 max_gap_s=1.15 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node2-1 | [node2] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_stopped_0 +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1149 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=579 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=633 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=622 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=676 log=/app/results/iroh_after_sim.log +node1-1 | [node1] AssignedIp=172.30.0.3 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.4 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.6 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | [node3] netem degraded on tun0 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=435 first_rx_delay_s=0.49 max_gap_s=0.91 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=424 first_rx_delay_s=0.67 max_gap_s=9.95 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=428 first_rx_delay_s=0.98 max_gap_s=1.12 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=426 first_rx_delay_s=0.54 max_gap_s=2.52 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=44 first_rx_delay_s=0.78 max_gap_s=14.01 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=307 first_rx_delay_s=10.76 max_gap_s=1.11 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=433 first_rx_delay_s=1.10 max_gap_s=0.99 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=422 first_rx_delay_s=0.54 max_gap_s=0.62 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=244 first_rx_delay_s=0.65 max_gap_s=7.80 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=359 first_rx_delay_s=0.95 max_gap_s=9.49 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=425 first_rx_delay_s=0.63 max_gap_s=1.21 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=421 first_rx_delay_s=0.67 max_gap_s=3.39 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=331 first_rx_delay_s=0.37 max_gap_s=13.28 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=325 first_rx_delay_s=0.80 max_gap_s=39.23 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=428 first_rx_delay_s=0.46 max_gap_s=0.50 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=440 first_rx_delay_s=0.49 max_gap_s=2.66 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=329 first_rx_delay_s=0.34 max_gap_s=39.38 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=440 first_rx_delay_s=5.27 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=0.10 max_gap_s=1.24 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=133 first_rx_delay_s=10.30 max_gap_s=13.25 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node3-1 | [node3] netem clean +node0-1 | [node0] netem clean +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=447 first_rx_delay_s=0.30 max_gap_s=1.33 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.53 max_gap_s=1.11 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.84 max_gap_s=1.20 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=445 first_rx_delay_s=0.53 max_gap_s=1.06 +node0-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.85 max_gap_s=1.10 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.57 max_gap_s=1.35 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=445 first_rx_delay_s=0.32 max_gap_s=1.29 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=445 first_rx_delay_s=0.67 max_gap_s=0.41 +node3-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node3-1 | [node3] signal: post_outage_recovery_done_3 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.51 max_gap_s=1.00 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=442 first_rx_delay_s=0.84 max_gap_s=0.81 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=445 first_rx_delay_s=0.52 max_gap_s=1.13 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=446 first_rx_delay_s=0.51 max_gap_s=0.33 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=443 first_rx_delay_s=0.67 max_gap_s=1.17 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=448 first_rx_delay_s=0.03 max_gap_s=0.37 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=448 first_rx_delay_s=0.35 max_gap_s=1.22 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=448 first_rx_delay_s=0.12 max_gap_s=1.00 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.07 max_gap_s=1.16 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=449 first_rx_delay_s=0.19 max_gap_s=1.20 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=450 first_rx_delay_s=0.11 max_gap_s=1.18 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=450 first_rx_delay_s=0.06 max_gap_s=7.44 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node4-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for recovery_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=341 first_rx_delay_s=0.90 max_gap_s=0.41 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=345 first_rx_delay_s=0.47 max_gap_s=1.15 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=346 first_rx_delay_s=0.04 max_gap_s=0.43 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.00 max_gap_s=1.23 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=47 first_rx_delay_s=0.05 max_gap_s=12.07 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.33 max_gap_s=0.98 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=341 first_rx_delay_s=0.89 max_gap_s=1.03 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=212 first_rx_delay_s=0.00 max_gap_s=13.14 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=348 first_rx_delay_s=0.17 max_gap_s=1.15 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=0.73 max_gap_s=1.06 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=239 first_rx_delay_s=0.30 max_gap_s=13.30 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=345 first_rx_delay_s=0.16 max_gap_s=1.07 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=349 first_rx_delay_s=0.17 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=350 first_rx_delay_s=0.03 max_gap_s=1.09 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.44 max_gap_s=1.17 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=341 first_rx_delay_s=0.01 max_gap_s=2.72 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: recovery_done_4 +node4-1 | [node4] waiting for recovery_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=346 first_rx_delay_s=0.11 max_gap_s=1.07 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=349 first_rx_delay_s=0.15 max_gap_s=2.47 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=349 first_rx_delay_s=0.08 max_gap_s=1.29 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.39 max_gap_s=1.01 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: recovery_done_3 +node3-1 | [node3] waiting for recovery_complete (600s) +node0-1 | [node0] signal: recovery_complete +node0-1 | [node0] waiting for recovery_complete (600s) +node0-1 | [node0] signal: TEST_PASS +node0-1 | [node0] waiting for TEST_PASS (120s) +node2-1 | [node2] waiting for TEST_PASS (120s) +node0-1 | [node0] reliability test complete +node2-1 | [node2] reliability test complete +node0-1 | [node0] Saved logs to /app/results/20260320_012836 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_012836 (exit=0) +node1-1 | [node1] waiting for TEST_PASS (120s) +node1-1 | [node1] reliability test complete + node0-1 exited with code 0 + Compose Stopping Aborting on container exit... +node1-1 | [node1] Saved logs to /app/results/20260320_012836 (exit=0) + Container docker_test-node0-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node2-1 Stopping + Container docker_test-node0-1 Stopped + Container docker_test-node2-1 Stopped + node2-1 exited with code 0 +node4-1 | [node4] Saved logs to /app/results/20260320_012836 (exit=0) +node3-1 | [node3] Saved logs to /app/results/20260320_012836 (exit=0) + Container docker_test-node1-1 Stopped + node1-1 exited with code 0 + Container docker_test-node4-1 Stopped + node4-1 exited with code 143 + Container docker_test-node3-1 Stopped + node3-1 exited with code 143 + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_012836/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_012836/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_012836/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_012836/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node4: docker_test/results_reliability/node4/20260320_012836/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +======================================================== +RELIABILITY RESULT: PASS +--- Run #5 --- +cargo build + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s +cargo build --example tcp_client + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.27s +cargo build --example tcp_server + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +cargo build --example game_check + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s +cargo build --example mesh_check + Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s +sudo rm docker_test/results_reliability/node*/*.log -r; \ +TOPIC="reliability_$RANDOM"; \ +echo "Using TOPIC=$TOPIC"; \ +sudo -E TOPIC=$TOPIC RECONNECT_MAX_SEC=60 docker compose -f docker_test/compose-reliability.yaml up --build --abort-on-container-exit --remove-orphans; \ +echo ""; \ +chmod +x ./docker_test/check_reliability_logs.sh; \ +./docker_test/check_reliability_logs.sh +Using TOPIC=reliability_12590 + Image iroh-lan-test Building +#1 [internal] load local bake definitions +#1 reading from stdin 540B done +#1 DONE 0.0s + +#2 [internal] load build definition from Dockerfile +#2 transferring dockerfile: 571B done +#2 DONE 0.0s + +#3 [internal] load metadata for docker.io/library/ubuntu:24.04 +#3 DONE 0.6s + +#4 [internal] load .dockerignore +#4 transferring context: 2B done +#4 DONE 0.0s + +#5 [1/7] FROM docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c +#5 resolve docker.io/library/ubuntu:24.04@sha256:186072bba1b2f436cbb91ef2567abca677337cfc786c86e107d25b7072feef0c 0.0s done +#5 DONE 0.0s + +#6 [internal] load build context +#6 transferring context: 132B done +#6 DONE 0.0s + +#7 [2/7] RUN apt-get update && apt-get install -y iproute2 ethtool procps netcat-openbsd iputils-ping iperf3 gdb && rm -rf /var/lib/apt/lists/* +#7 CACHED + +#8 [3/7] WORKDIR /app +#8 CACHED + +#9 [6/7] COPY check_reliability_logs.sh /app/check_reliability_logs.sh +#9 CACHED + +#10 [5/7] COPY entrypoint_reliability.sh /app/entrypoint_reliability.sh +#10 CACHED + +#11 [4/7] COPY entrypoint_stress.sh /app/entrypoint_stress.sh +#11 CACHED + +#12 [7/7] RUN chmod +x /app/entrypoint_stress.sh /app/entrypoint_reliability.sh /app/check_reliability_logs.sh +#12 CACHED + +#13 exporting to image +#13 exporting layers done +#13 writing image sha256:383f69f4245fcf8e0dcc2c1bc8ee2c13d0b5760dbba93be457af530847dcdc2a done +#13 naming to docker.io/library/iroh-lan-test done +#13 DONE 0.0s + +#14 resolving provenance for metadata file +#14 DONE 0.0s + Image iroh-lan-test Built + Container docker_test-node3-1 Recreate + Container docker_test-node0-1 Recreate + Container docker_test-node1-1 Recreate + Container docker_test-node4-1 Recreate + Container docker_test-node2-1 Recreate + Container docker_test-node0-1 Recreated + Container docker_test-node4-1 Recreated + Container docker_test-node2-1 Recreated + Container docker_test-node1-1 Recreated + Container docker_test-node3-1 Recreated +Attaching to node0-1, node1-1, node2-1, node3-1, node4-1 + Container docker_test-node1-1 Starting + Container docker_test-node3-1 Starting + Container docker_test-node4-1 Starting + Container docker_test-node2-1 Starting + Container docker_test-node0-1 Starting +node0-1 | Mesh phase durations and settings: +node0-1 | baseline: 35s +node0-1 | degraded: 40s (with netem profile) +node0-1 | post_rolling: 45s (with netem profile) +node0-1 | post_simultaneous: 45s (with netem profile) +node0-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node0-1 | recovery: 35s (with clean netem profile) +node0-1 | max_reconnect: 60s +node0-1 | rolling_slot_sec: 10s +node0-1 | sim_jitter_max_sec: 5s +node0-1 | outage_sec: 25s +node0-1 | outage_recovery_max_sec: 30s +node0-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node0-1 | + Container docker_test-node0-1 Started +node2-1 | Mesh phase durations and settings: +node2-1 | baseline: 35s +node2-1 | degraded: 40s (with netem profile) +node2-1 | post_rolling: 45s (with netem profile) +node2-1 | post_simultaneous: 45s (with netem profile) +node2-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node2-1 | recovery: 35s (with clean netem profile) +node2-1 | max_reconnect: 60s +node2-1 | rolling_slot_sec: 10s +node2-1 | sim_jitter_max_sec: 5s +node2-1 | outage_sec: 25s +node2-1 | outage_recovery_max_sec: 30s +node2-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node2-1 | + Container docker_test-node2-1 Started +node4-1 | Mesh phase durations and settings: +node4-1 | baseline: 35s +node4-1 | degraded: 40s (with netem profile) +node4-1 | post_rolling: 45s (with netem profile) +node4-1 | post_simultaneous: 45s (with netem profile) +node4-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node4-1 | recovery: 35s (with clean netem profile) +node4-1 | max_reconnect: 60s +node4-1 | rolling_slot_sec: 10s +node4-1 | sim_jitter_max_sec: 5s +node4-1 | outage_sec: 25s +node4-1 | outage_recovery_max_sec: 30s +node4-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node4-1 | + Container docker_test-node4-1 Started +node1-1 | Mesh phase durations and settings: +node1-1 | baseline: 35s +node1-1 | degraded: 40s (with netem profile) +node1-1 | post_rolling: 45s (with netem profile) +node1-1 | post_simultaneous: 45s (with netem profile) +node1-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node1-1 | recovery: 35s (with clean netem profile) +node1-1 | max_reconnect: 60s +node1-1 | rolling_slot_sec: 10s +node1-1 | sim_jitter_max_sec: 5s +node1-1 | outage_sec: 25s +node1-1 | outage_recovery_max_sec: 30s +node1-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node1-1 | + Container docker_test-node1-1 Started +node3-1 | Mesh phase durations and settings: +node3-1 | baseline: 35s +node3-1 | degraded: 40s (with netem profile) +node3-1 | post_rolling: 45s (with netem profile) +node3-1 | post_simultaneous: 45s (with netem profile) +node3-1 | post_outage_recovery: 45s (nonfatal, with clean netem profile) +node3-1 | recovery: 35s (with clean netem profile) +node3-1 | max_reconnect: 60s +node3-1 | rolling_slot_sec: 10s +node3-1 | sim_jitter_max_sec: 5s +node3-1 | outage_sec: 25s +node3-1 | outage_recovery_max_sec: 30s +node3-1 | netem profile for degraded/rolling/simultaneous phases: delay 180ms ±60ms, loss 4%, reorder 2% with gap 25, duplicate 1% +node3-1 | + Container docker_test-node3-1 Started +node0-1 | [node0] started iroh pid=11 log=/app/results/iroh.log +node2-1 | [node2] started iroh pid=10 log=/app/results/iroh.log +node4-1 | [node4] started iroh pid=10 log=/app/results/iroh.log +node1-1 | [node1] started iroh pid=9 log=/app/results/iroh.log +node3-1 | [node3] started iroh pid=10 log=/app/results/iroh.log +node0-1 | [node0] AssignedIp=172.30.0.3 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: ready_0 +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: ready_4 +node4-1 | [node4] waiting for all_ready (300s) +node3-1 | [node3] AssignedIp=172.30.0.5 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: ready_3 +node3-1 | [node3] waiting for all_ready (300s) +node2-1 | [node2] AssignedIp=172.30.0.2 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: ready_2 +node2-1 | [node2] waiting for all_ready (300s) +node1-1 | [node1] AssignedIp=172.30.0.6 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: ready_1 +node1-1 | [node1] waiting for all_ready (300s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: all_ready +node0-1 | [node0] waiting for all_ready (300s) +node4-1 | [node4] waiting for baseline_start (300s) +node0-1 | [node0] signal: baseline_start +node0-1 | [node0] waiting for baseline_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=baseline peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node1-1 | [node1] waiting for baseline_start (300s) +node0-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] netem clean +node1-1 | [node1] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for baseline_start (300s) +node3-1 | [node3] netem clean +node3-1 | [node3] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for baseline_start (300s) +node2-1 | [node2] netem clean +node2-1 | [node2] phase=baseline peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] netem clean +node4-1 | [node4] phase=baseline peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=128 first_rx_delay_s=13.26 max_gap_s=9.54 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=179 first_rx_delay_s=0.56 max_gap_s=13.33 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=266 first_rx_delay_s=9.28 max_gap_s=3.80 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=213 first_rx_delay_s=0.49 max_gap_s=13.24 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: baseline_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=342 first_rx_delay_s=0.97 max_gap_s=0.79 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=342 first_rx_delay_s=1.00 max_gap_s=1.08 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=21 first_rx_delay_s=0.39 max_gap_s=25.14 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=243 first_rx_delay_s=0.39 max_gap_s=13.61 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: baseline_done_1 +node1-1 | [node1] waiting for baseline_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=179 first_rx_delay_s=11.81 max_gap_s=9.09 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=231 first_rx_delay_s=0.98 max_gap_s=3.05 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=246 first_rx_delay_s=0.45 max_gap_s=24.06 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=259 first_rx_delay_s=0.34 max_gap_s=4.44 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: baseline_done_3 +node3-1 | [node3] waiting for baseline_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=198 first_rx_delay_s=0.53 max_gap_s=19.13 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=237 first_rx_delay_s=0.18 max_gap_s=13.09 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=144 first_rx_delay_s=11.93 max_gap_s=13.39 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=350 first_rx_delay_s=0.84 max_gap_s=1.12 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: baseline_done_2 +node2-1 | [node2] waiting for baseline_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=237 first_rx_delay_s=0.50 max_gap_s=10.48 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=147 first_rx_delay_s=17.25 max_gap_s=13.64 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=142 first_rx_delay_s=0.06 max_gap_s=19.20 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=349 first_rx_delay_s=0.07 max_gap_s=1.03 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: baseline_done_4 +node4-1 | [node4] waiting for baseline_complete (600s) +node0-1 | [node0] signal: baseline_complete +node0-1 | [node0] waiting for baseline_complete (600s) +node1-1 | [node1] waiting for degraded_start (300s) +node0-1 | [node0] signal: degraded_start +node0-1 | [node0] waiting for degraded_start (300s) +node1-1 | [node1] netem degraded on tun0 +node0-1 | [node0] netem degraded on tun0 +node1-1 | [node1] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=40s max_reconnect=60s tick=100ms +node0-1 | [node0] phase=degraded peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node3-1 | [node3] waiting for degraded_start (300s) +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for degraded_start (300s) +node2-1 | [node2] netem degraded on tun0 +node2-1 | [node2] phase=degraded peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for degraded_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=degraded peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=40s max_reconnect=60s tick=100ms +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=383 first_rx_delay_s=0.05 max_gap_s=1.15 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=384 first_rx_delay_s=0.08 max_gap_s=1.29 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=43 first_rx_delay_s=4.86 max_gap_s=13.27 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=283 first_rx_delay_s=0.49 max_gap_s=12.36 +node1-1 | MESH_CHECK: PASS +node0-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=386 first_rx_delay_s=1.13 max_gap_s=0.80 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=391 first_rx_delay_s=0.05 max_gap_s=1.20 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=373 first_rx_delay_s=3.28 max_gap_s=3.93 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=200 first_rx_delay_s=10.23 max_gap_s=12.95 +node0-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: degraded_done_1 +node1-1 | [node1] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_done_0 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=110 first_rx_delay_s=0.05 max_gap_s=0.67 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=467 first_rx_delay_s=0.42 max_gap_s=0.60 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=373 first_rx_delay_s=0.66 max_gap_s=2.92 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=373 first_rx_delay_s=6.65 max_gap_s=1.01 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: degraded_done_3 +node3-1 | [node3] waiting for degraded_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=400 rx=245 first_rx_delay_s=7.84 max_gap_s=0.58 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=202 first_rx_delay_s=0.09 max_gap_s=1.23 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=385 first_rx_delay_s=1.11 max_gap_s=0.89 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=387 first_rx_delay_s=0.48 max_gap_s=1.12 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: degraded_done_2 +node2-1 | [node2] waiting for degraded_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=400 rx=392 first_rx_delay_s=0.23 max_gap_s=0.85 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=400 rx=382 first_rx_delay_s=0.20 max_gap_s=0.98 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=400 rx=257 first_rx_delay_s=8.30 max_gap_s=5.37 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=400 rx=398 first_rx_delay_s=0.09 max_gap_s=0.42 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: degraded_done_4 +node4-1 | [node4] waiting for degraded_complete (600s) +node0-1 | [node0] signal: degraded_complete +node0-1 | [node0] waiting for degraded_complete (600s) +node0-1 | [node0] signal: rolling_go +node0-1 | [node0] waiting for rolling_go (120s) +node3-1 | [node3] waiting for rolling_go (120s) +node0-1 | [node0] signal: stopped_0 +node2-1 | [node2] waiting for rolling_go (120s) +node4-1 | [node4] waiting for rolling_go (120s) +node1-1 | [node1] waiting for rolling_go (120s) +node1-1 | [node1] signal: stopped_1 +node1-1 | [node1] waiting for rolling_all_stopped (600s) +node2-1 | [node2] signal: stopped_2 +node2-1 | [node2] waiting for rolling_all_stopped (600s) +node3-1 | [node3] signal: stopped_3 +node3-1 | [node3] waiting for rolling_all_stopped (600s) +node4-1 | [node4] signal: stopped_4 +node4-1 | [node4] waiting for rolling_all_stopped (600s) +node0-1 | [node0] signal: rolling_all_stopped +node0-1 | [node0] waiting for rolling_all_stopped (600s) +node0-1 | [node0] started iroh pid=821 log=/app/results/iroh_after_rolling.log +node4-1 | [node4] started iroh pid=306 log=/app/results/iroh_after_rolling.log +node2-1 | [node2] started iroh pid=394 log=/app/results/iroh_after_rolling.log +node3-1 | [node3] started iroh pid=346 log=/app/results/iroh_after_rolling.log +node1-1 | [node1] started iroh pid=439 log=/app/results/iroh_after_rolling.log +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: restarted_0 +node2-1 | [node2] AssignedIp=172.30.0.4 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: restarted_2 +node2-1 | [node2] waiting for rolling_done (600s) +node1-1 | [node1] AssignedIp=172.30.0.5 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: restarted_1 +node1-1 | [node1] waiting for rolling_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.3 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: restarted_4 +node4-1 | [node4] waiting for rolling_done (600s) +node3-1 | [node3] AssignedIp=172.30.0.6 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: restarted_3 +node3-1 | [node3] waiting for rolling_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: rolling_done +node0-1 | [node0] waiting for rolling_done (600s) +node0-1 | [node0] signal: post_rolling_start +node0-1 | [node0] waiting for post_rolling_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_rolling peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_rolling_start (300s) +node2-1 | [node2] netem degraded on tun0 +node3-1 | [node3] waiting for post_rolling_start (300s) +node2-1 | [node2] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] netem degraded on tun0 +node3-1 | [node3] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node3-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_rolling_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_rolling peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node1-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_rolling_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_rolling peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=426 first_rx_delay_s=0.89 max_gap_s=1.16 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=431 first_rx_delay_s=0.80 max_gap_s=1.24 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=430 first_rx_delay_s=0.63 max_gap_s=2.60 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=411 first_rx_delay_s=10.77 max_gap_s=2.79 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_rolling_done_0 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=257 first_rx_delay_s=6.79 max_gap_s=13.52 +node2-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=442 first_rx_delay_s=0.59 max_gap_s=1.07 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=351 first_rx_delay_s=0.64 max_gap_s=1.14 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=309 first_rx_delay_s=4.60 max_gap_s=13.47 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_rolling_done_2 +node2-1 | [node2] waiting for post_rolling_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=326 first_rx_delay_s=0.48 max_gap_s=13.29 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=431 first_rx_delay_s=0.64 max_gap_s=1.21 +node3-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=324 first_rx_delay_s=1.06 max_gap_s=6.48 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=427 first_rx_delay_s=0.49 max_gap_s=0.96 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_rolling_done_3 +node3-1 | [node3] waiting for post_rolling_complete (600s) +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=434 first_rx_delay_s=0.54 max_gap_s=1.21 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=229 first_rx_delay_s=10.60 max_gap_s=13.28 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=164 first_rx_delay_s=3.56 max_gap_s=13.88 +node1-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=361 first_rx_delay_s=0.53 max_gap_s=9.83 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_rolling_done_1 +node1-1 | [node1] waiting for post_rolling_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=328 first_rx_delay_s=0.44 max_gap_s=13.12 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=436 first_rx_delay_s=0.07 max_gap_s=1.06 +node4-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=216 first_rx_delay_s=5.81 max_gap_s=13.22 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=335 first_rx_delay_s=18.45 max_gap_s=1.06 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_rolling_done_4 +node4-1 | [node4] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: post_rolling_complete +node0-1 | [node0] waiting for post_rolling_complete (600s) +node0-1 | [node0] signal: sim_go +node0-1 | [node0] waiting for sim_go (120s) +node2-1 | [node2] waiting for sim_go (120s) +node3-1 | [node3] waiting for sim_go (120s) +node1-1 | [node1] waiting for sim_go (120s) +node4-1 | [node4] waiting for sim_go (120s) +node0-1 | [node0] signal: sim_stopped_0 +node4-1 | [node4] signal: sim_stopped_4 +node4-1 | [node4] waiting for sim_all_stopped (600s) +node2-1 | [node2] signal: sim_stopped_2 +node2-1 | [node2] waiting for sim_all_stopped (600s) +node1-1 | [node1] signal: sim_stopped_1 +node1-1 | [node1] waiting for sim_all_stopped (600s) +node3-1 | [node3] signal: sim_stopped_3 +node3-1 | [node3] waiting for sim_all_stopped (600s) +node0-1 | [node0] signal: sim_all_stopped +node0-1 | [node0] waiting for sim_all_stopped (600s) +node0-1 | [node0] started iroh pid=1223 log=/app/results/iroh_after_sim.log +node1-1 | [node1] started iroh pid=694 log=/app/results/iroh_after_sim.log +node4-1 | [node4] started iroh pid=574 log=/app/results/iroh_after_sim.log +node3-1 | [node3] started iroh pid=617 log=/app/results/iroh_after_sim.log +node2-1 | [node2] started iroh pid=645 log=/app/results/iroh_after_sim.log +node3-1 | [node3] AssignedIp=172.30.0.3 +node3-1 | [node3] TUN_DEV=tun0 +node3-1 | [node3] signal: sim_restarted_3 +node3-1 | [node3] waiting for sim_done (600s) +node4-1 | [node4] AssignedIp=172.30.0.4 +node4-1 | [node4] TUN_DEV=tun0 +node4-1 | [node4] signal: sim_restarted_4 +node4-1 | [node4] waiting for sim_done (600s) +node0-1 | [node0] AssignedIp=172.30.0.2 +node0-1 | [node0] TUN_DEV=tun0 +node0-1 | [node0] signal: sim_restarted_0 +node1-1 | [node1] AssignedIp=172.30.0.6 +node1-1 | [node1] TUN_DEV=tun0 +node1-1 | [node1] signal: sim_restarted_1 +node1-1 | [node1] waiting for sim_done (600s) +node2-1 | [node2] AssignedIp=172.30.0.5 +node2-1 | [node2] TUN_DEV=tun0 +node2-1 | [node2] signal: sim_restarted_2 +node2-1 | [node2] waiting for sim_done (600s) +node0-1 | [node0] peers.list=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6, +node0-1 | [node0] signal: sim_done +node0-1 | [node0] waiting for sim_done (600s) +node0-1 | [node0] signal: post_simultaneous_start +node0-1 | [node0] waiting for post_simultaneous_start (300s) +node0-1 | [node0] netem degraded on tun0 +node0-1 | [node0] phase=post_simultaneous peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for post_simultaneous_start (300s) +node1-1 | [node1] netem degraded on tun0 +node1-1 | [node1] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for post_simultaneous_start (300s) +node4-1 | [node4] netem degraded on tun0 +node4-1 | [node4] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for post_simultaneous_start (300s) +node2-1 | [node2] netem degraded on tun0 +node3-1 | [node3] waiting for post_simultaneous_start (300s) +node2-1 | [node2] phase=post_simultaneous peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] netem degraded on tun0 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node3-1 | [node3] phase=post_simultaneous peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=433 first_rx_delay_s=1.07 max_gap_s=2.60 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=428 first_rx_delay_s=1.16 max_gap_s=2.63 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=4 first_rx_delay_s=39.28 max_gap_s=0.14 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=102 first_rx_delay_s=10.38 max_gap_s=3.67 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_simultaneous_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=427 first_rx_delay_s=0.78 max_gap_s=1.32 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=417 first_rx_delay_s=1.03 max_gap_s=1.11 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=332 first_rx_delay_s=0.81 max_gap_s=12.57 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=417 first_rx_delay_s=0.68 max_gap_s=10.87 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_simultaneous_done_1 +node1-1 | [node1] waiting for post_simultaneous_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=332 first_rx_delay_s=0.38 max_gap_s=13.04 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=65 first_rx_delay_s=7.84 max_gap_s=13.35 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=258 first_rx_delay_s=8.25 max_gap_s=13.63 +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=428 first_rx_delay_s=0.69 max_gap_s=1.21 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_simultaneous_done_4 +node4-1 | [node4] waiting for post_simultaneous_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=429 first_rx_delay_s=1.28 max_gap_s=1.17 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=326 first_rx_delay_s=0.08 max_gap_s=13.26 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=422 first_rx_delay_s=0.13 max_gap_s=1.19 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=332 first_rx_delay_s=0.58 max_gap_s=12.35 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_simultaneous_done_2 +node2-1 | [node2] waiting for post_simultaneous_complete (600s) +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=342 first_rx_delay_s=0.07 max_gap_s=37.68 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=224 first_rx_delay_s=0.62 max_gap_s=13.22 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=338 first_rx_delay_s=7.23 max_gap_s=2.08 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=436 first_rx_delay_s=0.12 max_gap_s=0.96 +node3-1 | MESH_CHECK: PASS +node3-1 | [node3] signal: post_simultaneous_done_3 +node3-1 | [node3] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: post_simultaneous_complete +node0-1 | [node0] waiting for post_simultaneous_complete (600s) +node0-1 | [node0] signal: outage_start +node0-1 | [node0] waiting for outage_start (300s) +node0-1 | [node0] netem blackhole on tun0 (loss 100%) +node0-1 | [node0] outage hold for 25s +node1-1 | [node1] waiting for outage_start (300s) +node1-1 | [node1] netem blackhole on tun0 (loss 100%) +node1-1 | [node1] outage hold for 25s +node4-1 | [node4] waiting for outage_start (300s) +node4-1 | [node4] netem blackhole on tun0 (loss 100%) +node4-1 | [node4] outage hold for 25s +node2-1 | [node2] waiting for outage_start (300s) +node2-1 | [node2] netem blackhole on tun0 (loss 100%) +node2-1 | [node2] outage hold for 25s +node3-1 | [node3] waiting for outage_start (300s) +node3-1 | [node3] netem blackhole on tun0 (loss 100%) +node3-1 | [node3] outage hold for 25s +node0-1 | [node0] outage restored (netem removed) +node0-1 | [node0] signal: outage_done_0 +node1-1 | [node1] outage restored (netem removed) +node1-1 | [node1] signal: outage_done_1 +node1-1 | [node1] waiting for outage_restored (300s) +node4-1 | [node4] outage restored (netem removed) +node4-1 | [node4] signal: outage_done_4 +node4-1 | [node4] waiting for outage_restored (300s) +node2-1 | [node2] outage restored (netem removed) +node2-1 | [node2] signal: outage_done_2 +node2-1 | [node2] waiting for outage_restored (300s) +node3-1 | [node3] outage restored (netem removed) +node3-1 | [node3] signal: outage_done_3 +node3-1 | [node3] waiting for outage_restored (300s) +node0-1 | [node0] signal: outage_restored +node0-1 | [node0] waiting for outage_restored (300s) +node0-1 | [node0] signal: post_outage_recovery_start +node0-1 | [node0] waiting for post_outage_recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=post_outage_recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node1-1 | [node1] waiting for post_outage_recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=45s max_reconnect=30s tick=100ms +node4-1 | [node4] waiting for post_outage_recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node2-1 | [node2] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] netem clean +node3-1 | [node3] waiting for post_outage_recovery_start (300s) +node2-1 | [node2] phase=post_outage_recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] netem clean +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node3-1 | [node3] phase=post_outage_recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=45s max_reconnect=30s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=442 first_rx_delay_s=0.81 max_gap_s=1.25 +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=339 first_rx_delay_s=0.48 max_gap_s=18.97 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=443 first_rx_delay_s=0.81 max_gap_s=0.57 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=333 first_rx_delay_s=0.74 max_gap_s=26.92 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: post_outage_recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=441 first_rx_delay_s=0.79 max_gap_s=0.31 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=442 first_rx_delay_s=0.69 max_gap_s=1.13 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=350 first_rx_delay_s=0.41 max_gap_s=2.34 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=443 first_rx_delay_s=0.76 max_gap_s=1.12 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: post_outage_recovery_done_1 +node1-1 | [node1] waiting for post_outage_recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=446 first_rx_delay_s=0.46 max_gap_s=1.11 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=449 first_rx_delay_s=0.12 max_gap_s=1.18 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=83 first_rx_delay_s=1.20 max_gap_s=13.32 +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.09 max_gap_s=14.74 +node4-1 | MESH_CHECK: PASS +node4-1 | [node4] signal: post_outage_recovery_done_4 +node4-1 | [node4] waiting for post_outage_recovery_complete (600s) +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=447 first_rx_delay_s=0.29 max_gap_s=1.27 +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=450 first_rx_delay_s=0.06 max_gap_s=1.28 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=450 rx=238 first_rx_delay_s=0.37 max_gap_s=0.34 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.01 max_gap_s=3.77 +node2-1 | MESH_CHECK: PASS +node2-1 | [node2] signal: post_outage_recovery_done_2 +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=450 rx=450 first_rx_delay_s=0.01 max_gap_s=1.08 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=450 rx=304 first_rx_delay_s=0.65 max_gap_s=2.44 +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=450 rx=450 first_rx_delay_s=0.05 max_gap_s=1.16 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=450 rx=348 first_rx_delay_s=0.39 max_gap_s=8.98 +node3-1 | MESH_CHECK: PASS +node2-1 | [node2] waiting for post_outage_recovery_complete (600s) +node3-1 | [node3] signal: post_outage_recovery_done_3 +node3-1 | [node3] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: post_outage_recovery_complete +node0-1 | [node0] waiting for post_outage_recovery_complete (600s) +node0-1 | [node0] signal: recovery_start +node0-1 | [node0] waiting for recovery_start (300s) +node0-1 | [node0] netem clean +node0-1 | [node0] phase=recovery peers=172.30.0.3,172.30.0.4,172.30.0.5,172.30.0.6 +node0-1 | MESH_CHECK: start self_ip=172.30.0.2 bind=0.0.0.0:31000 peers=[172.30.0.3, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node1-1 | [node1] waiting for recovery_start (300s) +node1-1 | [node1] netem clean +node1-1 | [node1] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.5 +node1-1 | MESH_CHECK: start self_ip=172.30.0.6 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.5] duration=35s max_reconnect=60s tick=100ms +node4-1 | [node4] waiting for recovery_start (300s) +node4-1 | [node4] netem clean +node4-1 | [node4] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.5,172.30.0.6 +node4-1 | MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node2-1 | [node2] waiting for recovery_start (300s) +node3-1 | [node3] waiting for recovery_start (300s) +node2-1 | [node2] netem clean +node3-1 | [node3] netem clean +node2-1 | [node2] phase=recovery peers=172.30.0.2,172.30.0.3,172.30.0.4,172.30.0.6 +node3-1 | [node3] phase=recovery peers=172.30.0.2,172.30.0.4,172.30.0.5,172.30.0.6 +node2-1 | MESH_CHECK: start self_ip=172.30.0.5 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.4, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node3-1 | MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +node0-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=339 first_rx_delay_s=2.69 max_gap_s=2.17 +node0-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.09 max_gap_s=0.78 +node0-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=344 first_rx_delay_s=0.06 max_gap_s=1.15 +node0-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=346 first_rx_delay_s=0.03 max_gap_s=0.93 +node0-1 | MESH_CHECK: PASS +node0-1 | [node0] signal: recovery_done_0 +node1-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=166 first_rx_delay_s=3.09 max_gap_s=8.51 +node1-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=346 first_rx_delay_s=0.07 max_gap_s=1.30 +node1-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=345 first_rx_delay_s=0.07 max_gap_s=1.24 +node1-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=347 first_rx_delay_s=0.01 max_gap_s=1.21 +node1-1 | MESH_CHECK: PASS +node1-1 | [node1] signal: recovery_done_1 +node1-1 | [node1] waiting for recovery_complete (600s) +node4-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=75 first_rx_delay_s=0.50 max_gap_s=0.28 +node4-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +node4-1 | MESH_CHECK: FAIL peer=172.30.0.3 tx=350 rx=0 (expected both > 0) +node4-1 | MESH_CHECK: FAIL peer=172.30.0.3 never received any packet +node4-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=344 first_rx_delay_s=0.05 max_gap_s=1.17 +node4-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=349 first_rx_delay_s=0.07 max_gap_s=0.32 +node4-1 | MESH_CHECK: FAIL +node4-1 | [node4] Saved logs to /app/results/20260320_013548 (exit=1) +node2-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.12 max_gap_s=1.10 +node2-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=349 first_rx_delay_s=0.09 max_gap_s=1.11 +node2-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=233 first_rx_delay_s=0.46 max_gap_s=10.63 +node2-1 | MESH_CHECK: peer=172.30.0.3 tx=350 rx=296 first_rx_delay_s=0.43 max_gap_s=13.36 +node2-1 | MESH_CHECK: PASS +node3-1 | MESH_CHECK: peer=172.30.0.2 tx=350 rx=343 first_rx_delay_s=0.09 max_gap_s=0.82 +node3-1 | MESH_CHECK: peer=172.30.0.4 tx=350 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +node3-1 | MESH_CHECK: FAIL peer=172.30.0.4 tx=350 rx=0 (expected both > 0) +node3-1 | MESH_CHECK: FAIL peer=172.30.0.4 never received any packet +node3-1 | MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.12 max_gap_s=0.31 +node3-1 | MESH_CHECK: peer=172.30.0.5 tx=350 rx=362 first_rx_delay_s=0.32 max_gap_s=2.49 +node3-1 | MESH_CHECK: FAIL +node2-1 | [node2] signal: recovery_done_2 +node2-1 | [node2] waiting for recovery_complete (600s) +node3-1 | [node3] Saved logs to /app/results/20260320_013548 (exit=1) + node4-1 exited with code 1 + Compose Stopping Aborting on container exit... + Container docker_test-node2-1 Stopping + Container docker_test-node1-1 Stopping + Container docker_test-node3-1 Stopping + Container docker_test-node0-1 Stopping + Container docker_test-node4-1 Stopping + Container docker_test-node4-1 Stopped +node0-1 | [node0] Saved logs to /app/results/20260320_013548 (exit=0) +node2-1 | [node2] Saved logs to /app/results/20260320_013548 (exit=0) +node1-1 | [node1] Saved logs to /app/results/20260320_013548 (exit=0) + Container docker_test-node3-1 Stopped + node3-1 exited with code 1 + Container docker_test-node0-1 Stopped + node0-1 exited with code 143 + Container docker_test-node1-1 Stopped + node1-1 exited with code 143 + Container docker_test-node2-1 Stopped + node2-1 exited with code 143 + + +======================================================== + 5-NODE RELIABILITY TEST REPORT +======================================================== +node0: docker_test/results_reliability/node0/20260320_013548/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node1: docker_test/results_reliability/node1/20260320_013548/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node2: docker_test/results_reliability/node2/20260320_013548/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [PASS] recovery +node3: docker_test/results_reliability/node3/20260320_013548/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [FAIL] recovery +MESH_CHECK: start self_ip=172.30.0.3 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.4, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +MESH_CHECK: peer=172.30.0.2 tx=350 rx=343 first_rx_delay_s=0.09 max_gap_s=0.82 +MESH_CHECK: peer=172.30.0.4 tx=350 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +MESH_CHECK: FAIL peer=172.30.0.4 tx=350 rx=0 (expected both > 0) +MESH_CHECK: FAIL peer=172.30.0.4 never received any packet +MESH_CHECK: peer=172.30.0.6 tx=350 rx=348 first_rx_delay_s=0.12 max_gap_s=0.31 +MESH_CHECK: peer=172.30.0.5 tx=350 rx=362 first_rx_delay_s=0.32 max_gap_s=2.49 +MESH_CHECK: FAIL +node4: docker_test/results_reliability/node4/20260320_013548/ + [PASS] baseline + [PASS] degraded + [PASS] post_rolling + [PASS] post_simultaneous + [PASS] post_outage_recovery + [FAIL] recovery +MESH_CHECK: start self_ip=172.30.0.4 bind=0.0.0.0:31000 peers=[172.30.0.2, 172.30.0.3, 172.30.0.5, 172.30.0.6] duration=35s max_reconnect=60s tick=100ms +MESH_CHECK: peer=172.30.0.5 tx=350 rx=75 first_rx_delay_s=0.50 max_gap_s=0.28 +MESH_CHECK: peer=172.30.0.3 tx=350 rx=0 first_rx_delay_s=-1.00 max_gap_s=0.00 +MESH_CHECK: FAIL peer=172.30.0.3 tx=350 rx=0 (expected both > 0) +MESH_CHECK: FAIL peer=172.30.0.3 never received any packet +MESH_CHECK: peer=172.30.0.2 tx=350 rx=344 first_rx_delay_s=0.05 max_gap_s=1.17 +MESH_CHECK: peer=172.30.0.6 tx=350 rx=349 first_rx_delay_s=0.07 max_gap_s=0.32 +MESH_CHECK: FAIL +======================================================== +RELIABILITY RESULT: FAIL +make: *** [Makefile:29: reliability-test] Error 1 diff --git a/examples/game_check.rs b/examples/game_check.rs new file mode 100644 index 0000000..e8abebd --- /dev/null +++ b/examples/game_check.rs @@ -0,0 +1,268 @@ +use rand::RngCore; +use std::env; +use std::sync::Arc; +use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::time::Duration; +use tokio::net::UdpSocket; +use tokio::time::{self, Instant}; + +const TICK_RATE: u64 = 50; // 50ms = 20 ticks per second (typical for games like Minecraft/Minetest) +const PACKET_SIZE: usize = 1200; +const DISCONNECT_TIMEOUT_SEC: u64 = 60; // Fail if no packets for 60s +const RECONNECT_LOG_THRESHOLD_SEC: u64 = 2; +const DONE_TAG: &[u8] = b"GAME_DONE"; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("Usage: game_check [bind_addr] [target_addr] [duration_minutes]"); + return Ok(()); + } + + let mode = &args[1]; + let bind_addr = args.get(2).unwrap_or(&"0.0.0.0:30000".to_string()).clone(); + let duration_minutes: u64 = args.get(4).and_then(|s| s.parse().ok()).unwrap_or(5); + let run_duration = Duration::from_secs(duration_minutes * 60); + + match mode.as_str() { + "server" => run_server(&bind_addr, run_duration).await?, + "client" => { + let target_addr = args.get(3).expect("Client needs target address"); + run_client(&bind_addr, target_addr, run_duration).await? + } + _ => eprintln!("Invalid mode. Use server or client"), + } + + Ok(()) +} + +async fn run_server( + bind_addr: &str, + _duration: Duration, +) -> Result<(), Box> { + let socket = Arc::new(UdpSocket::bind(bind_addr).await?); + println!("[Server] Listening on {}", bind_addr); + println!("[Server] Waiting for client completion (duration handled by client)."); + + let clients = Arc::new(tokio::sync::Mutex::new(std::collections::HashMap::new())); + let recv_count = Arc::new(AtomicU64::new(0)); + let send_count = Arc::new(AtomicU64::new(0)); + + let socket_recv = socket.clone(); + let clients_recv = clients.clone(); + let recv_count_recv = recv_count.clone(); + let active = Arc::new(AtomicBool::new(true)); + let active_recv = active.clone(); + + tokio::spawn(async move { + let mut buf = [0u8; 2048]; + while active_recv.load(Ordering::Relaxed) { + if let Ok(Ok((len, addr))) = + time::timeout(Duration::from_secs(1), socket_recv.recv_from(&mut buf)).await + && len > 0 + { + let mut guard = clients_recv.lock().await; + if !guard.contains_key(&addr) { + println!("[Server] New Player Connected: {}", addr); + } + let entry = guard.entry(addr).or_insert((Instant::now(), false)); + entry.0 = Instant::now(); + recv_count_recv.fetch_add(1, Ordering::Relaxed); + if len >= DONE_TAG.len() && &buf[..DONE_TAG.len()] == DONE_TAG { + entry.1 = true; + println!("[Server] Player {} finished test.", addr); + } + } + } + }); + + let clients_log = clients.clone(); + let recv_count_log = recv_count.clone(); + let send_count_log = send_count.clone(); + let active_log = active.clone(); + tokio::spawn(async move { + let mut log_interval = time::interval(Duration::from_secs(5)); + let mut last_recv = 0u64; + let mut last_send = 0u64; + while active_log.load(Ordering::Relaxed) { + log_interval.tick().await; + let guard = clients_log.lock().await; + let recv_now = recv_count_log.load(Ordering::Relaxed); + let send_now = send_count_log.load(Ordering::Relaxed); + let recv_delta = recv_now.saturating_sub(last_recv); + let send_delta = send_now.saturating_sub(last_send); + last_recv = recv_now; + last_send = send_now; + println!( + "[Server] Active clients: {} | recv/s: {} | send/s: {}", + guard.len(), + recv_delta / 5, + send_delta / 5 + ); + } + }); + + let mut interval = time::interval(Duration::from_millis(TICK_RATE)); + let mut packet_data = vec![0u8; PACKET_SIZE]; + for (i, byte) in packet_data.iter_mut().enumerate() { + *byte = (i % 255) as u8; + } + + while active.load(Ordering::Relaxed) { + interval.tick().await; + + let mut guard = clients.lock().await; + // Remove dead clients (no packet in 20s) + let now = Instant::now(); + guard.retain(|addr, (last_seen, _done)| { + if now.duration_since(*last_seen) > Duration::from_secs(20) { + println!("[Server] Player {} timed out", addr); + false + } else { + true + } + }); + + let any_done = guard.values().any(|(_, done)| *done); + if any_done { + println!("[Server] Client finished. Shutting down."); + active.store(false, Ordering::Relaxed); + break; + } + + // Broadcast World State to all connected clients + for (addr, _) in guard.iter() { + let _ = socket.send_to(&packet_data, addr).await; + send_count.fetch_add(1, Ordering::Relaxed); + } + } + + Ok(()) +} + +async fn run_client( + bind_addr: &str, + target_addr: &str, + duration: Duration, +) -> Result<(), Box> { + let socket = Arc::new(UdpSocket::bind(bind_addr).await?); + println!("[Client] Bound to {}", bind_addr); + println!("[Client] Connecting to Game Server at {}", target_addr); + + let last_packet = Arc::new(tokio::sync::Mutex::new(Instant::now())); + let last_gap_ms = Arc::new(AtomicU64::new(0)); + let packet_count = Arc::new(AtomicU64::new(0)); + + // Receiver Loop + let socket_recv = socket.clone(); + let last_packet_recv = last_packet.clone(); + let last_gap_ms_recv = last_gap_ms.clone(); + let packet_count_recv = packet_count.clone(); + + tokio::spawn(async move { + let mut buf = [0u8; 2048]; + let mut last_gap_logged = false; + loop { + if let Ok((len, _)) = socket_recv.recv_from(&mut buf).await + && len > 0 + { + let now = Instant::now(); + let mut lock = last_packet_recv.lock().await; + let gap = now.duration_since(*lock); + *lock = now; + packet_count_recv.fetch_add(1, Ordering::Relaxed); + last_gap_ms_recv.store(gap.as_millis() as u64, Ordering::Relaxed); + + if gap > Duration::from_secs(RECONNECT_LOG_THRESHOLD_SEC) { + println!("[Client] RECONNECTED (gap {:.2}s)", gap.as_secs_f32()); + last_gap_logged = true; + } else if last_gap_logged { + println!("[Client] Connection stable again."); + last_gap_logged = false; + } + } + } + }); + + // Game Client Loop + let start_time = Instant::now(); + let mut interval = time::interval(Duration::from_millis(TICK_RATE)); + let mut input_data = vec![0u8; 200]; + rand::rng().fill_bytes(&mut input_data); + + println!("[Client] Game Loop Started (Duration: {:?})", duration); + println!("[Client] CSV: time_s,packets_total,packets_per_sec,last_gap_s"); + + let packet_count_log = packet_count.clone(); + let last_gap_ms_log = last_gap_ms.clone(); + let start_time_log = start_time; + let active_log = Arc::new(AtomicBool::new(true)); + let active_log_clone = active_log.clone(); + tokio::spawn(async move { + let mut stat_interval = time::interval(Duration::from_secs(1)); + let mut last_packets = 0u64; + loop { + stat_interval.tick().await; + if !active_log_clone.load(Ordering::Relaxed) { + break; + } + let total = packet_count_log.load(Ordering::Relaxed); + let delta = total.saturating_sub(last_packets); + last_packets = total; + let gap_s = last_gap_ms_log.load(Ordering::Relaxed) as f32 / 1000.0; + let time_s = start_time_log.elapsed().as_secs_f32(); + println!( + "[Client] CSV: {:.0},{},{}, {:.2}", + time_s, total, delta, gap_s + ); + } + }); + + while start_time.elapsed() < duration { + interval.tick().await; + + match socket.send_to(&input_data, target_addr).await { + Ok(_) => {} + Err(e) => eprintln!("[Client] Failed to send input: {}", e), + } + + let time_since_last = { + let lock = last_packet.lock().await; + Instant::now().duration_since(*lock) + }; + + if time_since_last > Duration::from_secs(DISCONNECT_TIMEOUT_SEC) { + eprintln!("\n[Client] CRITICAL FAILURE: Connection Lost!"); + eprintln!( + "[Client] No packets received for {:?} (Timeout is {}s)", + time_since_last, DISCONNECT_TIMEOUT_SEC + ); + std::process::exit(1); + } + + if start_time.elapsed().as_secs().is_multiple_of(10) + && start_time.elapsed().subsec_millis() < 55 + { + println!( + "[Client] Stats: Time={:.0}s | Packets Received: {}", + start_time.elapsed().as_secs_f32(), + packet_count.load(Ordering::Relaxed) + ); + } + } + + active_log.store(false, Ordering::Relaxed); + println!("[Client] Session Complete. SUCCESS."); + println!( + "[Client] Total Packets Received: {}", + packet_count.load(Ordering::Relaxed) + ); + + for _ in 0..3 { + let _ = socket.send_to(DONE_TAG, target_addr).await; + time::sleep(Duration::from_millis(100)).await; + } + + Ok(()) +} diff --git a/examples/mesh_check.rs b/examples/mesh_check.rs new file mode 100644 index 0000000..5190c9e --- /dev/null +++ b/examples/mesh_check.rs @@ -0,0 +1,258 @@ +use std::collections::HashMap; +use std::env; +use std::net::Ipv4Addr; +use std::sync::Arc; +use std::time::Duration; + +use tokio::net::UdpSocket; +use tokio::sync::Mutex; +use tokio::time::{self, Instant}; + +const DETAIL_LOG_LIMIT: u64 = 5; +const DETAIL_LOG_EVERY: u64 = 100; + +#[derive(Debug, Clone)] +struct PeerStats { + tx_count: u64, + rx_count: u64, + first_rx_at: Option, + last_rx_at: Option, + max_gap: Duration, +} + +impl PeerStats { + fn new() -> Self { + Self { + tx_count: 0, + rx_count: 0, + first_rx_at: None, + last_rx_at: None, + max_gap: Duration::from_secs(0), + } + } +} + +fn should_log_detail(count: u64) -> bool { + count <= DETAIL_LOG_LIMIT || count.is_multiple_of(DETAIL_LOG_EVERY) +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + let args: Vec = env::args().collect(); + if args.len() < 6 { + eprintln!( + "Usage: mesh_check [tick_ms]" + ); + std::process::exit(2); + } + + let bind_addr = &args[1]; + let self_ip: Ipv4Addr = args[2].parse()?; + let peer_csv = &args[3]; + let duration_sec: u64 = args[4].parse()?; + let max_reconnect_sec: u64 = args[5].parse()?; + let tick_ms: u64 = args.get(6).and_then(|s| s.parse().ok()).unwrap_or(100); + + let mut peers: Vec = peer_csv + .split(',') + .filter(|s| !s.trim().is_empty()) + .filter_map(|s| s.trim().parse::().ok()) + .filter(|ip| *ip != self_ip) + .collect(); + peers.sort_unstable(); + peers.dedup(); + + if peers.is_empty() { + eprintln!( + "MESH_CHECK: FAIL no peers to test against (self_ip={})", + self_ip + ); + std::process::exit(1); + } + + let duration = Duration::from_secs(duration_sec); + let max_reconnect = Duration::from_secs(max_reconnect_sec); + + println!( + "MESH_CHECK: start self_ip={} bind={} peers={:?} duration={}s max_reconnect={}s tick={}ms", + self_ip, bind_addr, peers, duration_sec, max_reconnect_sec, tick_ms + ); + + let socket = Arc::new(UdpSocket::bind(bind_addr).await?); + let stats: Arc>> = Arc::new(Mutex::new( + peers + .iter() + .copied() + .map(|ip| (ip, PeerStats::new())) + .collect(), + )); + + let start = Instant::now(); + let mut send_tick = time::interval(Duration::from_millis(tick_ms)); + send_tick.set_missed_tick_behavior(time::MissedTickBehavior::Skip); + + let mut stat_tick = time::interval(Duration::from_secs(1)); + stat_tick.set_missed_tick_behavior(time::MissedTickBehavior::Skip); + + let mut recv_buf = vec![0u8; 2048]; + + loop { + if start.elapsed() >= duration { + break; + } + + tokio::select! { + _ = send_tick.tick() => { + let payload = format!("mesh:{}:{}", self_ip, start.elapsed().as_millis()); + let payload_len = payload.len(); + let socket = Arc::clone(&socket); + let stats = Arc::clone(&stats); + let peers = peers.clone(); + tokio::spawn(async move { + for ip in &peers { + let addr = format!("{}:31000", ip); + if socket.send_to(payload.as_bytes(), &addr).await.is_ok() { + let mut guard = stats.lock().await; + if let Some(s) = guard.get_mut(ip) { + s.tx_count = s.tx_count.saturating_add(1); + if should_log_detail(s.tx_count) { + /*println!( + "MESH_CHECK: TX peer={} tx={} payload_len={} payload={}", + ip, + s.tx_count, + payload_len, + payload + );*/ + } + } + } else { + eprintln!("MESH_CHECK: WARN failed to send to {}", addr); + } + } + }); + + } + recv = socket.recv_from(&mut recv_buf) => { + if let Ok((len, src)) = recv { + if len == 0 { + continue; + } + let payload_text = String::from_utf8_lossy(&recv_buf[..len]).into_owned(); + if let std::net::IpAddr::V4(src_v4) = src.ip() { + let now = Instant::now(); + let mut guard = stats.lock().await; + if let Some(s) = guard.get_mut(&src_v4) { + if let Some(last) = s.last_rx_at { + let gap = now.duration_since(last); + if gap > s.max_gap { + s.max_gap = gap; + } + } + if s.first_rx_at.is_none() { + s.first_rx_at = Some(now); + } + s.last_rx_at = Some(now); + s.rx_count = s.rx_count.saturating_add(1); + if should_log_detail(s.rx_count) { + /*println!( + "MESH_CHECK: RX peer={} rx={} payload_len={} payload={}", + src_v4, + s.rx_count, + len, + payload_text + );*/ + } + } else { + println!( + "MESH_CHECK: RX-UNKNOWN peer={} payload_len={} payload={}", + src_v4, + len, + payload_text + ); + } + } + } + } + _ = stat_tick.tick() => { + let elapsed = start.elapsed(); + let guard = stats.lock().await; + for (ip, s) in guard.iter() { + if s.first_rx_at.is_none() && elapsed > max_reconnect { + eprintln!( + "MESH_CHECK: FAIL peer={} never received packet within {}s", + ip, + max_reconnect_sec + ); + std::process::exit(1); + } + if let Some(last) = s.last_rx_at + && Instant::now().duration_since(last) > max_reconnect + { + eprintln!( + "MESH_CHECK: FAIL peer={} no packets for > {}s", + ip, + max_reconnect_sec + ); + std::process::exit(1); + } + } + } + } + } + + let guard = stats.lock().await; + let mut failed = false; + for (ip, s) in guard.iter() { + let first_rx_delay = s + .first_rx_at + .map(|t| t.duration_since(start).as_secs_f32()) + .unwrap_or(-1.0); + println!( + "MESH_CHECK: peer={} tx={} rx={} first_rx_delay_s={:.2} max_gap_s={:.2}", + ip, + s.tx_count, + s.rx_count, + first_rx_delay, + s.max_gap.as_secs_f32() + ); + + if s.tx_count == 0 || s.rx_count == 0 { + failed = true; + eprintln!( + "MESH_CHECK: FAIL peer={} tx={} rx={} (expected both > 0)", + ip, s.tx_count, s.rx_count + ); + } + + if let Some(first_rx_at) = s.first_rx_at { + if first_rx_at.duration_since(start) > max_reconnect { + failed = true; + eprintln!( + "MESH_CHECK: FAIL peer={} first_rx exceeded {}s", + ip, max_reconnect_sec + ); + } + } else { + failed = true; + eprintln!("MESH_CHECK: FAIL peer={} never received any packet", ip); + } + + if s.max_gap > max_reconnect { + failed = true; + eprintln!( + "MESH_CHECK: FAIL peer={} max gap {:.2}s exceeded {}s", + ip, + s.max_gap.as_secs_f32(), + max_reconnect_sec + ); + } + } + + if failed { + eprintln!("MESH_CHECK: FAIL"); + std::process::exit(1); + } + + println!("MESH_CHECK: PASS"); + Ok(()) +} diff --git a/examples/participant.rs b/examples/participant.rs index d0d6fa8..cce1e00 100644 --- a/examples/participant.rs +++ b/examples/participant.rs @@ -1,4 +1,4 @@ -use iroh_lan::{RouterIp, network::Network}; +use iroh_lan::{RouterIp, Network}; use tokio::time::sleep; #[tokio::main] @@ -22,14 +22,15 @@ async fn main() -> anyhow::Result<()> { sleep(std::time::Duration::from_millis(500)).await; } - println!("my ip is {:?}", network.get_router_state().await?); + if let RouterIp::AssignedIp(ip) = network.get_router_state().await? { + println!("My IP is {}", ip); + } tokio::spawn(async move { loop { - println!( - "Network started with endpoint ID {:?}", - network.get_router_state().await - ); + if let Ok(RouterIp::AssignedIp(ip)) = network.get_router_state().await { + println!("My IP is still {}", ip); + } sleep(std::time::Duration::from_secs(5)).await; } }); diff --git a/examples/tcp_client.rs b/examples/tcp_client.rs index c928911..a399ad2 100644 --- a/examples/tcp_client.rs +++ b/examples/tcp_client.rs @@ -6,10 +6,11 @@ use tokio::{ #[tokio::main] async fn main() -> anyhow::Result<()> { - // bind local addr 172.22.0.3:0 and connect to remote - let local: std::net::SocketAddr = "172.22.0.4:0".parse()?; - let remote: std::net::SocketAddr = "172.22.0.3:8000".parse()?; + // bind local addr 172.30.0.4:0 and connect to remote + let local: std::net::SocketAddr = "172.30.0.4:0".parse()?; + let remote: std::net::SocketAddr = "172.30.0.3:8000".parse()?; let socket = tokio::net::TcpSocket::new_v4()?; + socket.bind_device(Some("tun1".as_bytes()))?; socket.bind(local)?; let mut tcp_stream = socket.connect(remote).await?; println!( diff --git a/examples/tcp_server.rs b/examples/tcp_server.rs index 0af89a1..592c9e9 100644 --- a/examples/tcp_server.rs +++ b/examples/tcp_server.rs @@ -2,7 +2,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[tokio::main] async fn main() -> anyhow::Result<()> { - let listener = tokio::net::TcpListener::bind("172.22.0.3:8000").await?; + let listener = tokio::net::TcpListener::bind("172.30.0.3:8000").await?; while let Ok((mut stream, addr)) = listener.accept().await { println!("Accepted connection from {addr}"); tokio::spawn(async move { diff --git a/Dockerfile b/legacy_test/Dockerfile similarity index 87% rename from Dockerfile rename to legacy_test/Dockerfile index 11e2ee0..f6cc855 100644 --- a/Dockerfile +++ b/legacy_test/Dockerfile @@ -30,14 +30,12 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry,sharin --mount=type=cache,target=/usr/local/cargo/git,id=cargo-git,sharing=locked \ --mount=type=cache,target=/app/target,id=cargo-target,sharing=locked \ cargo build --example participant \ - && cargo build --example creator \ && mkdir -p /dist \ - && cp /app/target/debug/examples/participant /dist/participant \ - && cp /app/target/debug/examples/creator /dist/creator + && cp /app/target/debug/examples/participant /dist/participant FROM debian:bullseye-slim AS runtime-base RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates libssl1.1 \ + ca-certificates libssl1.1 iperf3 iproute2 iputils-ping \ && rm -rf /var/lib/apt/lists/* WORKDIR /app ENV RUST_BACKTRACE=1 @@ -45,7 +43,4 @@ ENV RUST_BACKTRACE=1 FROM runtime-base AS participant-runtime COPY --from=builder /dist/participant /usr/local/bin/participant CMD ["participant"] - -FROM runtime-base AS creator-runtime -COPY --from=builder /dist/creator /usr/local/bin/creator CMD ["creator"] \ No newline at end of file diff --git a/Dockerfile_creator b/legacy_test/Dockerfile_creator similarity index 100% rename from Dockerfile_creator rename to legacy_test/Dockerfile_creator diff --git a/Dockerfile_participant b/legacy_test/Dockerfile_participant similarity index 100% rename from Dockerfile_participant rename to legacy_test/Dockerfile_participant diff --git a/docker-compose.yml b/legacy_test/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to legacy_test/docker-compose.yml diff --git a/netns_tests/netns_lab.sh b/netns_tests/netns_lab.sh new file mode 100755 index 0000000..fdb11ce --- /dev/null +++ b/netns_tests/netns_lab.sh @@ -0,0 +1,178 @@ +#!/usr/bin/env bash +# Builds/destroys the NAT lab. Everything lives inside namespaces +# prefixed "il-" (iroh-lab). Teardown removes all of it. +set -euo pipefail + +P="il" # namespace prefix, avoids clashing with anything +NODES=(0 1 2 3 4) +# which router each node sits behind: +ROUTER_OF=(0 0 1 1 2) +ROUTERS=(0 1 2) + +UPLINK_SUBNET="10.250.0.0/30" +UPLINK_HOST_IP="10.250.0.1" +UPLINK_ISP_IP="10.250.0.2" +HOST_VETH="il-uplink" +REAL_IFACE="${REAL_IFACE:-}" + +ns_node() { echo "${P}-node$1"; } +ns_rtr() { echo "${P}-rtr$1"; } +NS_ISP="${P}-isp" + +teardown() { + remove_uplink + for ns in $(ip netns list | awk '{print $1}' | grep "^${P}-" || true); do + ip netns del "$ns" 2>/dev/null || true + done + echo "lab removed. verify with: ip netns list" +} + +setup() { + teardown + + # ---- ISP namespace with a bridge (the fake internet) ---- + ip netns add "$NS_ISP" + ip -n "$NS_ISP" link set lo up + ip netns exec "$NS_ISP" sysctl -q -w net.ipv4.ip_forward=1 + ip -n "$NS_ISP" link add br0 type bridge + ip -n "$NS_ISP" addr add 203.0.113.1/24 dev br0 + ip -n "$NS_ISP" link set br0 up + + # ---- routers ---- + for r in "${ROUTERS[@]}"; do + local_rtr=$(ns_rtr "$r") + ip netns add "$local_rtr" + ip -n "$local_rtr" link set lo up + + # WAN link: router <-> isp bridge + ip link add "${P}-w${r}" type veth peer name wan netns "$local_rtr" + ip link set "${P}-w${r}" netns "$NS_ISP" + ip -n "$NS_ISP" link set "${P}-w${r}" master br0 + ip -n "$NS_ISP" link set "${P}-w${r}" up + + ip -n "$local_rtr" addr add "203.0.113.$(( (r + 1) * 10 ))/24" dev wan + ip -n "$local_rtr" link set wan up + ip -n "$local_rtr" route add default via 203.0.113.1 + + # LAN side: a bridge inside the router ns + ip -n "$local_rtr" link add lan type bridge + ip -n "$local_rtr" addr add "192.168.$(( (r + 1) * 10 )).1/24" dev lan + ip -n "$local_rtr" link set lan up + + ip netns exec "$local_rtr" sysctl -q -w net.ipv4.ip_forward=1 + + # NAT: masquerade LAN -> WAN. Lives ONLY in this namespace. + ip netns exec "$local_rtr" nft -f - < "/etc/netns/${node}/resolv.conf" + done + + echo "lab up:" + ip netns list | grep "^${P}-" + if [ "${WITH_UPLINK:-1}" = "1" ]; then + add_uplink + echo "uplink added via $HOST_VETH (host $UPLINK_HOST_IP <-> isp $UPLINK_ISP_IP)" + fi +} + +status() { + for ns in $(ip netns list | awk '{print $1}' | grep "^${P}-" || true); do + echo "== $ns ==" + ip -n "$ns" -o -4 addr show | awk '{print " " $2, $4}' + done +} + +detect_real_iface() { + if [ -z "$REAL_IFACE" ]; then + REAL_IFACE=$(ip route show default | awk '/default/ {print $5; exit}') + fi + echo "using host uplink interface: $REAL_IFACE" +} + +add_uplink() { + detect_real_iface + + # host-side leg of the veth stays on the host, ISP-side moves into the ns + ip link add "$HOST_VETH" type veth peer name uplink netns "$NS_ISP" + ip addr add "${UPLINK_HOST_IP}/30" dev "$HOST_VETH" + ip link set "$HOST_VETH" up + + ip -n "$NS_ISP" addr add "${UPLINK_ISP_IP}/30" dev uplink + ip -n "$NS_ISP" link set uplink up + ip -n "$NS_ISP" route add default via "$UPLINK_HOST_IP" + + # ISP: masquerade all lab traffic leaving via the uplink so the host only sees 10.250.0.0/30 + ip netns exec "$NS_ISP" nft -f - < /tmp/il-resolv/resolv.conf + # actually forward DNS: host must accept/forward UDP/TCP 53 too, covered + # by the generic FORWARD/MASQUERADE rules above since port isn't filtered. + cp /tmp/il-resolv/resolv.conf /etc/netns/${NS_ISP}/resolv.conf 2>/dev/null || { + mkdir -p "/etc/netns/${NS_ISP}" + echo "nameserver ${UPLINK_HOST_IP}" > "/etc/netns/${NS_ISP}/resolv.conf" + } +} + +remove_uplink() { + ip netns exec "$NS_ISP" nft delete table ip nat 2>/dev/null || true + ip link del "$HOST_VETH" 2>/dev/null || true + iptables -t nat -S POSTROUTING 2>/dev/null | grep "il-lab-uplink" | while read -r rule; do + eval "iptables -t nat -D POSTROUTING ${rule#-A POSTROUTING }" 2>/dev/null || true + done || true + iptables -S FORWARD 2>/dev/null | grep "il-lab-uplink" | while read -r rule; do + eval "iptables -D FORWARD ${rule#-A FORWARD }" 2>/dev/null || true + done || true + rm -rf "/etc/netns/${NS_ISP}" +} + +case "${1:-}" in + setup) setup ;; + teardown) teardown ;; + status) status ;; + *) echo "usage: $0 setup|teardown|status"; exit 1 ;; +esac \ No newline at end of file diff --git a/netns_tests/reliability_test/check_logs.sh b/netns_tests/reliability_test/check_logs.sh new file mode 100755 index 0000000..1d1214a --- /dev/null +++ b/netns_tests/reliability_test/check_logs.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -euo pipefail +cd "$(dirname "$0")" + +overall_fail=0 +phases=(baseline degraded post_rolling post_simultaneous post_outage_recovery recovery) +optional_phases=(post_outage_recovery) + +is_optional_phase() { + local phase="$1" + for optional in "${optional_phases[@]}"; do + if [ "$optional" = "$phase" ]; then + return 0 + fi + done + return 1 +} + +for node in 0 1 2 3 4; do + base="./results/node${node}" + latest=$(find "$base" -mindepth 1 -maxdepth 1 -type d -name '20[0-9][0-9][0-1][0-9][0-3][0-9]_[0-2][0-9][0-5][0-9][0-5][0-9]' -printf '%T@ %p\n' 2>/dev/null | sort -nr | head -n1 | cut -d' ' -f2- || true) + + if [ -z "$latest" ]; then + echo "[FAIL] node${node}: no timestamped log directory found" + overall_fail=1 + continue + fi + + echo "node${node}: $latest" + + for phase in "${phases[@]}"; do + log="$latest/mesh_${phase}.log" + if [ ! -f "$log" ]; then + if is_optional_phase "$phase"; then + echo " [INFO] ${phase}: missing log" + else + echo " [FAIL] ${phase}: missing log" + overall_fail=1 + fi + continue + fi + + if grep -q "MESH_CHECK: PASS" "$log"; then + echo " [PASS] ${phase}" + else + if is_optional_phase "$phase"; then + echo " [INFO] ${phase}" + else + echo " [FAIL] ${phase}" + overall_fail=1 + fi + tail -n 20 "$log" || true + fi + done + +done + +echo "========================================================" +if [ "$overall_fail" -eq 0 ]; then + echo "RELIABILITY RESULT: PASS" + exit 0 +else + echo "RELIABILITY RESULT: FAIL" + exit 1 +fi diff --git a/netns_tests/reliability_test/entrypoint.sh b/netns_tests/reliability_test/entrypoint.sh new file mode 100644 index 0000000..fbe0bac --- /dev/null +++ b/netns_tests/reliability_test/entrypoint.sh @@ -0,0 +1,517 @@ +#!/bin/bash +set -e +set -o pipefail + +RESULTS_DIR="${RESULTS_DIR:-/app/results}" +RUN_ID="${RUN_ID:-$(date +%Y%m%d_%H%M%S)}" +LOG_DIR="$RESULTS_DIR/$RUN_ID" +QLOG_DIR="$LOG_DIR/qlog.log" +COORD_DIR="${COORD_DIR:-/coord}" +BIN_DIR="${BIN_DIR:-/app/bin}" + +mkdir -p "$LOG_DIR" "$QLOG_DIR" "$COORD_DIR" + +NODE_INDEX="${NODE_INDEX:-0}" +NODE_COUNT="${NODE_COUNT:-5}" +EXPECTED_PEERS="${EXPECTED_PEERS:-4}" +TOPIC="${TOPIC:-test_topic_default}" +RECONNECT_MAX_SEC="${RECONNECT_MAX_SEC:-60}" +MESH_TICK_MS="${MESH_TICK_MS:-100}" + +BASELINE_SEC="${BASELINE_SEC:-35}" +DEGRADED_SEC="${DEGRADED_SEC:-40}" +POST_ROLLING_SEC="${POST_ROLLING_SEC:-45}" +POST_SIM_SEC="${POST_SIM_SEC:-45}" +RECOVERY_SEC="${RECOVERY_SEC:-35}" +POST_OUTAGE_RECOVERY_SEC="${POST_OUTAGE_RECOVERY_SEC:-45}" + +ROLLING_SLOT_SEC="${ROLLING_SLOT_SEC:-10}" +SIM_JITTER_MAX_SEC="${SIM_JITTER_MAX_SEC:-5}" +OUTAGE_SEC="${OUTAGE_SEC:-25}" +OUTAGE_RECOVERY_MAX_SEC="${OUTAGE_RECOVERY_MAX_SEC:-30}" + + +IROH_PID="" +MY_IP="" +TUN_DEV="" +LOGS_COLLECTED=0 + +# echo the mesh_check durations and max_reconnect to make sure they make sense +echo "Mesh phase durations and settings:" +echo " baseline: ${BASELINE_SEC}s" +echo " degraded: ${DEGRADED_SEC}s (with netem profile)" +echo " post_rolling: ${POST_ROLLING_SEC}s (with netem profile)" +echo " post_simultaneous: ${POST_SIM_SEC}s (with netem profile)" +echo " post_outage_recovery: ${POST_OUTAGE_RECOVERY_SEC}s (nonfatal, with clean netem profile)" +echo " recovery: ${RECOVERY_SEC}s (with clean netem profile)" +echo " max_reconnect: ${RECONNECT_MAX_SEC}s" +echo " rolling_slot_sec: ${ROLLING_SLOT_SEC}s" +echo " sim_jitter_max_sec: ${SIM_JITTER_MAX_SEC}s" +echo " outage_sec: ${OUTAGE_SEC}s" +echo " outage_recovery_max_sec: ${OUTAGE_RECOVERY_MAX_SEC}s" +echo " netem profile for degraded/rolling/simultaneous phases: delay ${NETEM_DELAY_MS}ms ±${NETEM_JITTER_MS}ms, loss ${NETEM_LOSS_PCT}%, reorder ${NETEM_REORDER_PCT}% with gap ${NETEM_REORDER_GAP}, duplicate ${NETEM_DUP_PCT}%" +echo "" + + +#tc qdisc add dev eth0 root netem delay 300ms 100ms distribution normal loss 1.5% 2.5% reorder 0.5% 5% duplicate 0.1% corrupt 0.01% rate 10mbit +#tc qdisc replace dev eth0 root netem delay 1200ms 400ms reorder 35% 50% loss 35% 10% rate 6mbit limit 4000 + +collect_logs() { + local exit_code="${1:-$?}" + + if [ "$LOGS_COLLECTED" -eq 1 ]; then + return + fi + LOGS_COLLECTED=1 + + sync "$LOG_DIR" 2>/dev/null || true + echo "[node${NODE_INDEX}] Saved logs to $LOG_DIR (exit=$exit_code)" +} + +finalize_and_exit() { + local exit_code="$1" + + trap - EXIT TERM INT + + stop_iroh + tc qdisc del dev eth0 root 2>/dev/null || true + collect_logs "$exit_code" + + exit "$exit_code" +} + +handle_term() { + local exit_code=143 + + if [ -f "$COORD_DIR/TEST_PASS" ]; then + exit_code=0 + fi + + echo "[node${NODE_INDEX}] received SIGTERM" + finalize_and_exit "$exit_code" +} + +handle_int() { + echo "[node${NODE_INDEX}] received SIGINT" + finalize_and_exit 130 +} + +handle_exit() { + local exit_code=$? + + trap - EXIT TERM INT + stop_iroh + tc qdisc del dev eth0 root 2>/dev/null || true + collect_logs "$exit_code" + exit "$exit_code" +} + +trap handle_exit EXIT +trap handle_term TERM +trap handle_int INT + +signal() { + local name="$1" + touch "$COORD_DIR/$name" + echo "[node${NODE_INDEX}] signal: $name" +} + +wait_signal() { + local name="$1" + local timeout_sec="${2:-300}" + local start + start=$(date +%s) + + echo "[node${NODE_INDEX}] waiting for $name (${timeout_sec}s)" + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + if [ -f "$COORD_DIR/$name" ]; then + return 0 + fi + if [ -f "$COORD_DIR/FAIL" ]; then + echo "[node${NODE_INDEX}] observed global FAIL" + exit 1 + fi + sleep 0.5 + done + + echo "[node${NODE_INDEX}] timeout waiting for $name" + signal "FAIL" + touch "$COORD_DIR/FAIL" + exit 1 +} + +wait_all_signals() { + local prefix="$1" + local timeout_sec="${2:-300}" + local start + start=$(date +%s) + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + local count + count=$(ls "$COORD_DIR"/${prefix}_* 2>/dev/null | wc -l || true) + if [ "$count" -ge "$NODE_COUNT" ]; then + return 0 + fi + if [ -f "$COORD_DIR/FAIL" ]; then + echo "[node${NODE_INDEX}] observed global FAIL" + exit 1 + fi + sleep 0.5 + done + + echo "[node${NODE_INDEX}] timeout waiting for all ${prefix}_* signals" + touch "$COORD_DIR/FAIL" + exit 1 +} + +start_iroh() { + local logfile="$1" + > "$logfile" + echo "Backtrace will be logged to $logfile" + export RUST_LOG="${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info}" + export RUST_BACKTRACE=full + + connected_timer=${EPOCHREALTIME/./} + "$BIN_DIR/iroh-lan" "$TOPIC" -t --qlog-dir "$QLOG_DIR" \ + ${IROH_RELAY_URL:+--relay-url "$IROH_RELAY_URL"} \ + >> "$logfile" 2>&1 & + IROH_PID=$! + echo "[node${NODE_INDEX}] started iroh pid=$IROH_PID log=$logfile" +} + +stop_iroh() { + if [ -n "$IROH_PID" ]; then + kill "$IROH_PID" 2>/dev/null || true + # Give iroh-lan up to 5s to shut down cleanly, then SIGKILL. + local _i + for _i in 1 2 3 4 5; do + if ! kill -0 "$IROH_PID" 2>/dev/null; then break; fi + sleep 1 + done + if kill -0 "$IROH_PID" 2>/dev/null; then + kill -9 "$IROH_PID" 2>/dev/null || true + wait "$IROH_PID" 2>/dev/null || true + fi + IROH_PID="" + fi +} + +wait_assigned_ip() { + local logfile="$1" + local timeout_sec="${2:-180}" + local start + start=$(date +%s) + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + local ip + ip=$(grep "My IP is " "$logfile" 2>/dev/null | tail -n1 | sed -n 's/My IP is \([0-9.]*\).*/\1/p' || true) + if [ -n "$ip" ]; then + MY_IP="$ip" + echo "[node${NODE_INDEX}] My IP=$MY_IP" + break + fi + sleep 1 + done + + if [ -z "$MY_IP" ]; then + echo "[node${NODE_INDEX}] timeout waiting My IP" + touch "$COORD_DIR/FAIL" + exit 1 + fi + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + local count + count=$(grep "Peer connected:" "$logfile" 2>/dev/null | grep -v "Peer connected: $MY_IP " | sed -n 's/Peer connected: \([0-9.]*\).*/\1/p' | sort -u | wc -l || true) + if [ "$count" -ge "$EXPECTED_PEERS" ]; then + ms=$(( (${EPOCHREALTIME/./} - connected_timer) / 1000 )) + echo "[node${NODE_INDEX}] Peer connected count=$count; time-to-all-connected=$(printf '%d,%03d' $((ms/1000)) $((ms%1000)))s" + return 0 + fi + sleep 1 + done + + echo "[node${NODE_INDEX}] timeout waiting Peer connected (expected $EXPECTED_PEERS)" + touch "$COORD_DIR/FAIL" + exit 1 +} + +wait_tun_for_ip() { + local timeout_sec="${1:-120}" + local start + start=$(date +%s) + + while [ $(( $(date +%s) - start )) -lt "$timeout_sec" ]; do + TUN_DEV=$(ip -o -4 addr show | awk -v ip="$MY_IP" '$4 ~ ip"/" {print $2; exit}') + if [ -n "$TUN_DEV" ]; then + echo "[node${NODE_INDEX}] TUN_DEV=$TUN_DEV" + return 0 + fi + sleep 0.5 + done + + echo "[node${NODE_INDEX}] timeout waiting TUN for $MY_IP" + ip -o -4 addr show || true + touch "$COORD_DIR/FAIL" + exit 1 +} + +rebuild_peers_list() { + local out="$COORD_DIR/peers.list" + ls "$COORD_DIR"/node*.ip 2>/dev/null | sort | while read -r f; do cat "$f"; done | sed '/^$/d' | sort -u > "$out" || true + echo "[node${NODE_INDEX}] peers.list=$(tr '\n' ',' < "$out")" +} + +get_peers_csv() { + if [ ! -f "$COORD_DIR/peers.list" ]; then + echo "" + return + fi + grep -v "^$MY_IP$" "$COORD_DIR/peers.list" | paste -sd, - || true +} + +#NETEM_DELAY_MS=600 +#NETEM_JITTER_MS=200 +#NETEM_LOSS="gemodel 5% 15% 100% 0%" +#NETEM_RATE="128kbit" +#NETEM_REORDER_PCT=8 +#NETEM_REORDER_CORR=50 +#NETEM_DUP_PCT=3 +#NETEM_CORRUPT_PCT=0.5 +#NETEM_SLOT="100ms 500ms" + + + +apply_netem_profile() { + local profile="$1" + + tc qdisc del dev eth0 root 2>/dev/null || true + + case "$profile" in + clean) + echo "[node${NODE_INDEX}] netem clean" + ;; + degraded) + echo "[node${NODE_INDEX}] netem degraded on eth0" + + # Build the tc command piecewise so each feature + # can be independently toggled via empty vars + local cmd="tc qdisc add dev eth0 root netem delay 450ms 80ms distribution normal loss gemodel 1.6% 30% 100% 0% reorder 7% duplicate 3% corrupt 0.1% rate 384kbit" + + echo "[node${NODE_INDEX}] $cmd" + eval "$cmd" + ;; + blackhole) + echo "[node${NODE_INDEX}] netem blackhole on eth0 (loss 100%)" + tc qdisc add dev eth0 root netem loss 100% + ;; + *) + echo "[node${NODE_INDEX}] unknown profile '$profile'" + touch "$COORD_DIR/FAIL" + exit 1 + ;; + esac +} + +run_outage_cycle() { + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/outage_start" "$COORD_DIR/outage_end" "$COORD_DIR/outage_restored" "$COORD_DIR/outage_done_"* 2>/dev/null || true + signal "outage_start" + fi + + wait_signal "outage_start" 300 + + apply_netem_profile "blackhole" + echo "[node${NODE_INDEX}] outage hold for ${OUTAGE_SEC}s" + sleep "$OUTAGE_SEC" + + tc qdisc del dev eth0 root 2>/dev/null || true + echo "[node${NODE_INDEX}] outage restored (netem removed)" + signal "outage_done_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "outage_done" 300 + signal "outage_restored" + fi + + wait_signal "outage_restored" 300 +} + +run_mesh_phase() { + local phase="$1" + local duration_sec="$2" + local max_reconnect_sec="$3" + local netem_profile="$4" + + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/${phase}_start" "$COORD_DIR/${phase}_complete" "$COORD_DIR/${phase}_done_"* 2>/dev/null || true + signal "${phase}_start" + fi + + wait_signal "${phase}_start" 300 + + apply_netem_profile "$netem_profile" + local peers_csv + peers_csv=$(get_peers_csv) + + if [ -z "$peers_csv" ]; then + echo "[node${NODE_INDEX}] no peers found for phase $phase" + touch "$COORD_DIR/FAIL" + exit 1 + fi + + echo "[node${NODE_INDEX}] phase=$phase peers=$peers_csv" + "$BIN_DIR/examples/mesh_check" \ + "0.0.0.0:31000" \ + "$MY_IP" \ + "$peers_csv" \ + "$duration_sec" \ + "$max_reconnect_sec" \ + "$MESH_TICK_MS" 2>&1 | tee -a "$LOG_DIR/mesh_${phase}.log" + + signal "${phase}_done_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "${phase}_done" 600 + signal "${phase}_complete" + fi + + wait_signal "${phase}_complete" 600 +} + +run_mesh_phase_nonfatal() { + local phase="$1" + local duration_sec="$2" + local max_reconnect_sec="$3" + local netem_profile="$4" + + set +e + run_mesh_phase "$phase" "$duration_sec" "$max_reconnect_sec" "$netem_profile" + local status=$? + set -e + + if [ "$status" -ne 0 ]; then + echo "[node${NODE_INDEX}] nonfatal mesh phase failed: $phase (exit=$status)" + fi + + return 0 +} + +rolling_restart() { + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/rolling_go" "$COORD_DIR/rolling_all_stopped" "$COORD_DIR/rolling_done" "$COORD_DIR/stopped_"* "$COORD_DIR/restarted_"* 2>/dev/null || true + signal "rolling_go" + fi + + wait_signal "rolling_go" 120 + + local slot=$(( NODE_INDEX * ROLLING_SLOT_SEC )) + sleep "$slot" + + stop_iroh + signal "stopped_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "stopped" 600 + signal "rolling_all_stopped" + fi + + wait_signal "rolling_all_stopped" 600 + + start_iroh "$LOG_DIR/iroh_after_rolling.log" + wait_assigned_ip "$LOG_DIR/iroh_after_rolling.log" 180 + wait_tun_for_ip 120 + echo "$MY_IP" > "$COORD_DIR/node${NODE_INDEX}.ip" + + signal "restarted_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "restarted" 600 + rebuild_peers_list + signal "rolling_done" + fi + + wait_signal "rolling_done" 600 +} + +simultaneous_restart() { + if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR/sim_go" "$COORD_DIR/sim_all_stopped" "$COORD_DIR/sim_done" "$COORD_DIR/sim_stopped_"* "$COORD_DIR/sim_restarted_"* 2>/dev/null || true + signal "sim_go" + fi + + wait_signal "sim_go" 120 + + local jitter=$(( RANDOM % (SIM_JITTER_MAX_SEC + 1) )) + sleep "$jitter" + + stop_iroh + signal "sim_stopped_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "sim_stopped" 600 + signal "sim_all_stopped" + fi + + wait_signal "sim_all_stopped" 600 + + start_iroh "$LOG_DIR/iroh_after_sim.log" + wait_assigned_ip "$LOG_DIR/iroh_after_sim.log" 180 + wait_tun_for_ip 120 + echo "$MY_IP" > "$COORD_DIR/node${NODE_INDEX}.ip" + + signal "sim_restarted_${NODE_INDEX}" + + if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "sim_restarted" 600 + rebuild_peers_list + signal "sim_done" + fi + + wait_signal "sim_done" 600 +} + +if [ "$NODE_INDEX" = "0" ]; then + rm -f "$COORD_DIR"/* 2>/dev/null || true +fi +sleep 1 + +start_iroh "$LOG_DIR/iroh.log" +wait_assigned_ip "$LOG_DIR/iroh.log" 180 +wait_tun_for_ip 120 + +echo "$MY_IP" > "$COORD_DIR/node${NODE_INDEX}.ip" +signal "ready_${NODE_INDEX}" + +if [ "$NODE_INDEX" = "0" ]; then + wait_all_signals "ready" 300 + rebuild_peers_list + signal "all_ready" +fi + +wait_signal "all_ready" 300 + +run_mesh_phase "baseline" "$BASELINE_SEC" "$RECONNECT_MAX_SEC" "clean" +run_mesh_phase "degraded" "$DEGRADED_SEC" "$RECONNECT_MAX_SEC" "degraded" + +rolling_restart +run_mesh_phase "post_rolling" "$POST_ROLLING_SEC" "$RECONNECT_MAX_SEC" "degraded" + +simultaneous_restart +run_mesh_phase "post_simultaneous" "$POST_SIM_SEC" "$RECONNECT_MAX_SEC" "degraded" + +# Extra chaos step: force hard outage (no recovery possible), then restore and verify recovery +run_outage_cycle +run_mesh_phase_nonfatal "post_outage_recovery" "$POST_OUTAGE_RECOVERY_SEC" "$OUTAGE_RECOVERY_MAX_SEC" "clean" + +run_mesh_phase "recovery" "$RECOVERY_SEC" "$RECONNECT_MAX_SEC" "clean" + +if [ "$NODE_INDEX" = "0" ]; then + signal "TEST_PASS" +fi + +wait_signal "TEST_PASS" 120 + +stop_iroh + +echo "[node${NODE_INDEX}] reliability test complete" +exit 0 diff --git a/netns_tests/reliability_test/run.sh b/netns_tests/reliability_test/run.sh new file mode 100755 index 0000000..017588a --- /dev/null +++ b/netns_tests/reliability_test/run.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/../.." # repo root + +TOPIC="${TOPIC:-reliability_$RANDOM}" +RUN_ID="${RUN_ID:-$(date +%Y%m%d_%H%M%S)}" +COORD_DIR="$(mktemp -d /tmp/iroh-coord.XXXX)" +RESULTS_ROOT="$PWD/netns_tests/reliability_test/results" +BIN_DIR="$PWD/target/debug" +#RELAY_URL="http://203.0.113.1:3340" +RELAY_URL="${RELAY_URL:-}" + +PIDS=() +cleanup() { + for pid in "${PIDS[@]}"; do kill "$pid" 2>/dev/null || true; done + wait 2>/dev/null || true + ./netns_tests/netns_lab.sh teardown + rm -rf "$COORD_DIR" +} +trap cleanup EXIT INT TERM + +sudo killall iroh-lan 2>/dev/null || true +./netns_tests/netns_lab.sh setup + +# relay in the ISP namespace +ip netns exec il-isp "$HOME/.cargo/bin/iroh-relay" \ + --dev > "$COORD_DIR/relay.log" 2>&1 & +PIDS+=($!) +sleep 2 + +for i in 0 1 2 3 4; do + NODE_RESULTS_DIR="$RESULTS_ROOT/node$i" + NODE_LOG_DIR="$NODE_RESULTS_DIR/$RUN_ID" + mkdir -p "$NODE_LOG_DIR" + + ip netns exec "il-node$i" env \ + NODE_INDEX=$i NODE_COUNT=5 TOPIC="$TOPIC" RUN_ID="$RUN_ID" \ + RECONNECT_MAX_SEC="${RECONNECT_MAX_SEC:-60}" \ + MESH_TICK_MS="${MESH_TICK_MS:-100}" \ + RUST_LOG="${RUST_LOG:-iroh_lan=trace,iroh=info,iroh_gossip=info}" \ + COORD_DIR="$COORD_DIR" \ + RESULTS_DIR="$NODE_RESULTS_DIR" \ + BIN_DIR="$BIN_DIR" \ + ${RELAY_URL:+IROH_RELAY_URL="$RELAY_URL"} \ + RUST_BACKTRACE=full \ + bash netns_tests/reliability_test/entrypoint.sh \ + > "$NODE_LOG_DIR/entrypoint.log" 2>&1 & + PIDS+=($!) +done + +fail=0 +for pid in "${PIDS[@]:1}"; do # skip relay pid + wait "$pid" || fail=1 +done +kill "${PIDS[0]}" 2>/dev/null || true +exit $fail \ No newline at end of file diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 0000000..3855da3 --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,12 @@ +use anyhow::Result; + +#[tokio::main] +async fn main() -> Result<()> { + + if !self_runas::is_elevated() { + self_runas::admin()?; + return Ok(()); + } + + return iroh_lan::cli::run_cli().await +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..e2cb69b --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,387 @@ +use anyhow::Result; +use clap::Parser; +use crossterm::{ + event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyModifiers}, + execute, + terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode}, +}; +use iroh::EndpointId; +use ratatui::{ + Frame, Terminal, + backend::CrosstermBackend, + layout::{Constraint, Direction, Layout}, + style::{Color, Modifier, Style}, + text::{Line, Span}, + widgets::{Block, Borders, List, ListItem, Paragraph, Wrap}, +}; +use std::{collections::HashSet, io, net::Ipv4Addr, path::PathBuf, time::Duration}; +use tokio::time::sleep; + +use crate::{build_ip, connection::InnerConnState, state::IpClaim}; +use crate::{Network, state::Config}; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Name of the network + #[arg(value_name = "NAME")] + name: String, + + /// Password for the network + #[arg(short, long, default_value = "")] + password: String, + + /// Disable the TUI and run in headless mode + #[arg(short = 'n', long = "no-display")] + no_display: bool, + + /// Run headless with full tracing output + #[arg(short = 't', long = "trace")] + trace: bool, + + /// Directory for qlog files + #[arg(long = "qlog-dir", value_name = "qlog", requires = "trace")] + qlog_dir: Option, + + /// Iroh relay URL (overwrite default) + #[arg(long = "relay-url", value_name = "relay")] + relay_url: Option, +} + +pub async fn run_cli() -> Result<()> { + let args = Args::parse(); + + if args.name.is_empty() { + anyhow::bail!("Network name is required") + } + + if args.trace { + use tracing_subscriber::{EnvFilter, fmt, prelude::*}; + tracing_subscriber::registry() + .with(fmt::layer().with_thread_ids(true)) + .with(EnvFilter::new( + //"iroh_lan=debug,iroh_auth=debug,iroh_topic_tracker=debug,iroh=info,iroh_gossip=debug", + //"iroh_lan::connection=debug,iroh_lan::direct_connect=debug,iroh_lan::router=debug,iroh_quinn_proto=warn,condriver-unreachable=debug", + "iroh_lan::network=debug,iroh_lan::tun=info,iroh_lan::connection=debug,iroh_lan::direct_connect=debug,iroh_lan::overlay=info,iroh_lan::state=info,iroh_auth=debug,iroh_topic_tracker=debug", + )) + .init(); + } + + let headless = args.no_display || args.trace; + + if headless { + run_headless(args.name, args.password, args.qlog_dir, args.relay_url).await?; + } else { + run_tui(args.name, args.password, args.relay_url).await?; + } + + Ok(()) +} + +async fn run_headless( + name: String, + password: String, + qlog_dir: Option, + relay_url: Option, +) -> Result<()> { + println!("Waiting for first peer connection..."); + if let Some(qlog_dir) = &qlog_dir { + println!("qlog: {:?}", qlog_dir); + } + let network = + Network::new_logs_dir(&name, &password, qlog_dir, relay_url, Config::default()).await?; + println!("Waiting for IP assignment..."); + + let mut known_peers: HashSet<(EndpointId, std::net::Ipv4Addr)> = HashSet::new(); + let mut lost_peers: HashSet<(EndpointId, std::net::Ipv4Addr)> = HashSet::new(); + + loop { + tokio::select! { + _ = tokio::signal::ctrl_c() => break, + _ = sleep(std::time::Duration::from_millis(2000)) => { + if let Ok(peers) = network.get_peers().await { + let direct = network.get_direct_handle().await.ok(); + let mut new_peers = Vec::new(); + for (id, ip) in peers.iter() { + let ip = match ip { + Some(ip) => *ip, + None => continue, + }; + // Track (EndpointId, IP) pairs so a peer that switches IPs + // (e.g. during a rolling restart) is re-announced for its + // new IP instead of being silently swallowed by dedup. + if known_peers.contains(&(*id, ip)) { + continue; + } + if let Some(ref d) = direct + && matches!(d.get_conn_state(*id).await, Ok(InnerConnState::Open)) { + new_peers.push((*id, ip)); + } + } + for (id, ip) in new_peers { + known_peers.insert((id, ip)); + lost_peers.remove(&(id, ip)); + println!("Peer connected: {} ({})", ip, id); + } + let newly_lost_peers: Vec<_> = known_peers + .iter() + .filter(|(id, ip)| !peers.iter().any(|(pid, pip)| pid == id && *pip == Some(*ip))) + .cloned() + .collect(); + for pair @ (id, _) in newly_lost_peers { + lost_peers.insert(pair); + known_peers.remove(&pair); + println!("Peer disconnected: {}", id); + } + } + } + } + } + + Ok(()) +} + +struct AppState { + name: String, + password: String, + node_id: Option, + my_ip: String, + peers: Vec<(EndpointId, Option)>, + status: String, +} + +impl AppState { + fn new(name: String, password: String) -> Self { + Self { + name, + password, + node_id: None, + my_ip: "Unknown".to_string(), + peers: vec![], + status: "Initializing...".to_string(), + } + } +} + +async fn run_tui(name: String, password: String, relay_url: Option) -> Result<()> { + // Setup terminal + enable_raw_mode()?; + let mut stdout = io::stdout(); + execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?; + let backend = CrosstermBackend::new(stdout); + let mut terminal = Terminal::new(backend)?; + + // Use a guard to clean up terminal state on panic or early return + struct CleanUp; + impl Drop for CleanUp { + fn drop(&mut self) { + let _ = disable_raw_mode(); + let _ = execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture); + } + } + let _clean_up = CleanUp; + + // Create App State + let mut app_state = AppState::new(name.clone(), password.clone()); + + // Initial draw to show something immediately + terminal.draw(|f| ui(f, &app_state))?; + + // Initialize Network in background so TUI remains responsive + let (tx_network, mut rx_network) = tokio::sync::mpsc::channel(1); + let name_clone = name.clone(); + let password_clone = password.clone(); + + tokio::spawn(async move { + match Network::new(&name_clone, &password_clone, relay_url, Config::default()).await { + Ok(network) => { + let _ = tx_network.send(Ok(network)).await; + } + Err(e) => { + let _ = tx_network.send(Err(e)).await; + } + } + }); + + let mut network: Option = None; + + // Main loop + let tick_rate = Duration::from_millis(100); + let mut last_tick = std::time::Instant::now(); + + loop { + terminal.draw(|f| ui(f, &app_state))?; + + let timeout = tick_rate + .checked_sub(last_tick.elapsed()) + .unwrap_or_else(|| Duration::from_secs(0)); + + if crossterm::event::poll(timeout)? + && let Event::Key(key) = event::read()? + && (key.code == KeyCode::Char('q') + || (key.code == KeyCode::Char('c') + && key.modifiers.contains(KeyModifiers::CONTROL))) + { + // Explicitly break loop + break; + } + + if last_tick.elapsed() >= tick_rate { + // Check if network is ready + if network.is_none() + && let Ok(res) = rx_network.try_recv() + { + match res { + Ok(net) => { + network = Some(net); + app_state.status = "Network Started".to_string(); + } + Err(e) => { + app_state.status = format!("Init Failed: {}", e); + } + } + } + + // Update state if network exists + if let Some(net) = &network { + update_state(net, &mut app_state).await?; + } + last_tick = std::time::Instant::now(); + } + } + + Ok(()) +} + +async fn update_state(network: &Network, app_state: &mut AppState) -> Result<()> { + // Node ID + if app_state.node_id.is_none() + && let Ok(id) = network.get_node_id().await + { + app_state.node_id = Some(id); + } + if let Ok(state) = network.get_own_state().await { + // Router State (IP and Status) + match state.ip_claim { + IpClaim::Unclaimed => { + app_state.status = "No IP".to_string(); + app_state.my_ip = "None".to_string(); + } + IpClaim::Claimed(ip) => { + app_state.status = "Connected".to_string(); + app_state.my_ip = build_ip(Config::default().net_prefix, ip.ip).to_string(); + } + } + } + + // Peers + match network.get_peers().await { + Ok(peers) => { + app_state.peers = peers; + } + Err(_) => { + // keep old peers or clear? + } + } + + Ok(()) +} + +fn ui(f: &mut Frame, state: &AppState) { + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints( + [ + Constraint::Length(3), // Header + Constraint::Length(6), // Info + Constraint::Min(0), // Peers + Constraint::Length(3), // Footer + ] + .as_ref(), + ) + .split(f.area()); + + // Header + let title = Paragraph::new(format!("Iroh LAN - Network: {}", state.name)) + .style( + Style::default() + .fg(Color::Cyan) + .add_modifier(Modifier::BOLD), + ) + .block(Block::default().borders(Borders::ALL)); + f.render_widget(title, chunks[0]); + + // Info + let node_id_str = state + .node_id + .map(|id| id.to_string()) + .unwrap_or_else(|| "Loading...".to_string()); + + let info_text = vec![ + Line::from(vec![ + Span::raw("Status: "), + Span::styled( + &state.status, + Style::default().fg(if state.status == "Connected" { + Color::Green + } else { + Color::Yellow + }), + ), + ]), + Line::from(vec![ + Span::raw("My IP: "), + Span::styled( + &state.my_ip, + Style::default() + .fg(Color::White) + .add_modifier(Modifier::BOLD), + ), + ]), + Line::from(vec![ + Span::raw("Node ID: "), + Span::styled(node_id_str, Style::default().fg(Color::Gray)), + ]), + Line::from(vec![ + Span::raw("Password: "), + Span::styled(&state.password, Style::default().fg(Color::Red)), // Maybe mask this or make it red + ]), + ]; + + let info = Paragraph::new(info_text) + .block(Block::default().title("Info").borders(Borders::ALL)) + .wrap(Wrap { trim: true }); + f.render_widget(info, chunks[1]); + + // Peers + let peers: Vec = state + .peers + .iter() + .map(|(id, ip)| { + let ip_str = ip + .map(|i| i.to_string()) + .unwrap_or_else(|| "Unknown IP".to_string()); + let content = vec![Line::from(vec![ + Span::styled(format!("{:<20}", ip_str), Style::default().fg(Color::Green)), + Span::raw(" "), + Span::styled(id.to_string(), Style::default().fg(Color::Gray)), + ])]; + ListItem::new(content) + }) + .collect(); + + let peers_list = List::new(peers) + .block( + Block::default() + .borders(Borders::ALL) + .title("Connected Peers"), + ) + .highlight_style(Style::default().add_modifier(Modifier::BOLD)); + f.render_widget(peers_list, chunks[2]); + + // Footer + let footer = Paragraph::new("Press 'q' to quit") + .style(Style::default().fg(Color::Gray)) + .block(Block::default().borders(Borders::ALL)); + f.render_widget(footer, chunks[3]); +} diff --git a/src/connection.rs b/src/connection.rs index ccd04fd..3a33db7 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,43 +1,235 @@ -use std::{ - collections::VecDeque, - sync::atomic::AtomicUsize, - time::{Duration, SystemTime}, -}; +use std::fmt::{self, Display}; +use std::net::Ipv4Addr; +use std::sync::Arc; +use std::sync::atomic::Ordering; +use std::{collections::VecDeque, sync::atomic::AtomicUsize, time::Duration}; use crate::DirectMessage; -use actor_helper::{Action, Actor, Handle, Receiver, act, act_ok}; +use actor_helper::{Action, ActorState, Handle, Receiver, act, act_ok}; use anyhow::Result; +use bytes::Bytes; +use futures_lite::StreamExt; +use iroh::address_lookup::{AddressLookup, DnsAddressLookup}; use iroh::endpoint::{Connection, VarInt}; -use iroh::{ - Endpoint, EndpointId, - endpoint::{RecvStream, SendStream}, -}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tracing::{debug, warn}; +use iroh::{Endpoint, EndpointAddr, EndpointId}; +use n0_watcher::Watchable; +use tokio::sync::Mutex; +use tokio::time::{self, Instant}; +use tracing::{debug, info, trace, warn}; const QUEUE_SIZE: usize = 1024 * 16; -const MAX_RECONNECTS: usize = 5; -const RECONNECT_BACKOFF_BASE: Duration = Duration::from_millis(100); +const BACKPRESSURE_WARN_MS: u128 = 5; +const MAX_SENDER_QUEUE: usize = 50_000; +const WRITE_CHANNEL_CAP: usize = 8_192; +const STATS_LOG_INTERVAL: Duration = Duration::from_secs(5); +const QUEUE_WARN_LEN: usize = 10_000; +const KEEPALIVE_INTERVAL: Duration = Duration::from_millis(2000); +const CONNECTING_TIMEOUT: Duration = Duration::from_secs(15); +const DATAGRAM_PREFIX: u8 = 0x43; +const MAX_CONSECUTIVE_READ_TIMEOUTS: usize = 3; +const MAX_CONSECUTIVE_WRITE_TIMEOUTS: usize = 3; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum InnerConnState { + Connecting, + Open, + Closed, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum ConnLiveness { + Usable, + Suspect, + Dead, +} + +impl Display for ConnLiveness { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Usable => write!(f, "usable"), + Self::Suspect => write!(f, "suspect"), + Self::Dead => write!(f, "dead"), + } + } +} + +#[derive(Debug, Default)] +struct ConnHealthWindow { + last_rx_count: usize, + last_tx_count: usize, + last_udp_rx: u64, + last_udp_tx: u64, + last_lost: u64, + consecutive_read_timeouts: usize, + consecutive_write_timeouts: usize, + no_active_paths: bool, +} + +#[derive(Debug, Clone)] +pub struct ConnPathSnapshot { + pub path_id: String, + pub remote_addr: String, + pub is_selected: bool, + pub is_closed: bool, + pub rtt_ms: Option, + pub lost_packets: Option, + pub black_holes_detected: Option, + pub current_mtu: Option, + pub udp_tx_datagrams: Option, + pub udp_rx_datagrams: Option, +} + +#[derive(Debug, Clone)] +pub struct ConnSnapshot { + pub conn_actor_id: u64, + pub peer: EndpointId, + pub quic_stable_id: Option, + pub side: &'static str, + pub state: InnerConnState, + pub liveness: ConnLiveness, + pub idle_for_ms: u128, + pub rx_count: usize, + pub tx_count: usize, + pub queue_len: usize, + pub write_timeouts: usize, + pub consecutive_write_errors: usize, + pub consecutive_read_timeouts: usize, + pub consecutive_write_timeouts: usize, + pub no_active_paths: bool, + pub dropped_packets: usize, + pub total_lost_packets: Option, + pub total_udp_tx_datagrams: Option, + pub total_udp_rx_datagrams: Option, + pub selected_path: Option, + pub paths: Vec, +} + +impl fmt::Display for ConnPathSnapshot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "path_id={} remote_addr={} selected={} closed={} rtt_ms={} lost_packets={} black_holes={} mtu={} udp_tx_dgrams={} udp_rx_dgrams={}", + self.path_id, + self.remote_addr, + self.is_selected, + self.is_closed, + self.rtt_ms + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.lost_packets + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.black_holes_detected + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.current_mtu + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.udp_tx_datagrams + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.udp_rx_datagrams + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()) + ) + } +} + +impl fmt::Display for ConnSnapshot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let selected_path = self + .selected_path + .as_ref() + .map(|path| path.to_string()) + .unwrap_or_else(|| "none".to_string()); + let all_paths = if self.paths.is_empty() { + "none".to_string() + } else { + self.paths + .iter() + .map(|path| path.to_string()) + .collect::>() + .join(" | ") + }; + + write!( + f, + "conn_actor_id={} peer={} quic_stable_id={} side={} state={:?} liveness={} idle_for_ms={} rx_count={} tx_count={} queue_len={} write_timeouts={} consecutive_write_errors={} consecutive_read_timeouts={} consecutive_write_timeouts={} no_active_paths={} dropped_packets={} total_lost_packets={} total_udp_tx_dgrams={} total_udp_rx_dgrams={} selected_path=[{}] paths=[{}]", + self.conn_actor_id, + self.peer, + self.quic_stable_id + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.side, + self.state, + self.liveness, + self.idle_for_ms, + self.rx_count, + self.tx_count, + self.queue_len, + self.write_timeouts, + self.consecutive_write_errors, + self.consecutive_read_timeouts, + self.consecutive_write_timeouts, + self.no_active_paths, + self.dropped_packets, + self.total_lost_packets + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.total_udp_tx_datagrams + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + self.total_udp_rx_datagrams + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + selected_path, + all_paths + ) + } +} + +fn side_label(is_open_side: bool) -> &'static str { + if is_open_side { "open" } else { "accept" } +} + +fn snapshot_paths(conn: &Connection) -> Vec { + conn.paths() + .into_iter() + .map(|path| { + let stats = path.stats(); + ConnPathSnapshot { + path_id: format!("{:?}", path.id()), + remote_addr: format!("{:?}", path.remote_addr()), + is_selected: path.is_selected(), + is_closed: false, + rtt_ms: Some(path.rtt().as_millis()), + lost_packets: Some(stats.lost_packets), + black_holes_detected: Some(stats.black_holes_detected), + current_mtu: Some(stats.current_mtu), + udp_tx_datagrams: Some(stats.udp_tx.datagrams), + udp_rx_datagrams: Some(stats.udp_rx.datagrams), + } + }) + .collect() +} #[derive(Debug, Clone)] pub struct Conn { api: Handle, + id: u64, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ConnState { - Connecting, // ConnActor::connect() called, waiting for connection to be established (in background) - Idle, // no active connection, can be connected - Open, // open bi directional streams - Closed, // connection closed by user or error - Disconnected, // connection closed by remote peer, can be recovered within 5 retries after Closed +impl Eq for Conn {} + +impl PartialEq for Conn { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } } #[derive(Debug)] struct ConnActor { - rx: Receiver>, - self_handle: Handle, - state: ConnState, + self_handle: Option>, // all of these need to be optionals so that we can create an empty // shell of the actor and then fill in the values later so we don't wait @@ -45,362 +237,1105 @@ struct ConnActor { // route_packet failed conn: Option, conn_endpoint_id: EndpointId, - send_stream: Option, - recv_stream: Option, - endpoint: Endpoint, + id: u64, + - last_reconnect: tokio::time::Instant, - reconnect_backoff: Duration, - reconnect_count: AtomicUsize, + external_sender: tokio::sync::mpsc::Sender, - external_sender: tokio::sync::broadcast::Sender, + write_task: Option>, + write_tx: Option>, - receiver_queue: VecDeque, - receiver_notify: tokio::sync::Notify, + read_task: Option>, + + connected_task: Option>, + + queue_len: Arc, + dropped_packets: Arc, sender_queue: VecDeque, - sender_notify: tokio::sync::Notify, + rx_count: Arc, + tx_count: Arc, + write_timeouts: Arc, + consecutive_write_errors: Arc, + + is_open_side: bool, + conn_state: Arc>, + last_keep_alive: Arc>, + health: Arc>, + + dest_ip: Option, + + latest_frame: Watchable>, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)>, } impl Conn { - pub async fn new( - endpoint: Endpoint, - conn: iroh::endpoint::Connection, - send_stream: SendStream, - recv_stream: RecvStream, - external_sender: tokio::sync::broadcast::Sender, - ) -> Result { - let (api, rx) = Handle::channel(); - let mut actor = ConnActor::new( - rx, - api.clone(), - external_sender, - endpoint, - conn.remote_id(), - Some(conn), - Some(send_stream), - Some(recv_stream), - ) - .await; - tokio::spawn(async move { actor.run().await }); - Ok(Self { api }) + pub fn id(&self) -> u64 { + self.id } - pub async fn connect( - endpoint: Endpoint, - endpoint_id: EndpointId, - external_sender: tokio::sync::broadcast::Sender, - ) -> Self { - let (api, rx) = Handle::channel(); - let mut actor = ConnActor::new( - rx, - api.clone(), - external_sender, - endpoint.clone(), - endpoint_id, - None, - None, - None, + pub async fn is_alive(&self) -> bool { + matches!( + self.snapshot().await.map(|snapshot| snapshot.liveness), + Some(ConnLiveness::Usable | ConnLiveness::Suspect) ) - .await; + } - tokio::spawn(async move { - actor.set_state(ConnState::Connecting); - actor.run().await - }); - let s = Self { api }; + pub async fn snapshot(&self) -> Option { + self.api + .call(act_ok!(actor => async move { actor.snapshot().await })) + .await + .ok() + } - tokio::spawn({ - let s = s.clone(); - async move { - if let Ok(conn) = endpoint.connect(endpoint_id, crate::Direct::ALPN).await { - let _ = s.incoming_connection(conn, false).await; - } - } - }); + pub async fn accept_connection( + conn: iroh::endpoint::Connection, + external_sender: tokio::sync::mpsc::Sender, + latest_frame: Watchable>, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)> + ) -> Result { + let conn_state = Arc::new(Mutex::new(InnerConnState::Connecting)); + let last_keep_alive = Arc::new(Mutex::new(Instant::now())); + let id = rand::random(); + let (api, _) = Handle::spawn_with( + ConnActor::new( + id, + external_sender, + conn.remote_id(), + false, + conn_state.clone(), + last_keep_alive.clone(), + latest_frame, + remote_frame_tx + ), + |mut actor, rx| async move { actor.run(rx).await }, + ); + let s = Self { id, api }; + let self_handle = s.api.clone(); + s.api + .call(act_ok!(actor => async move { + actor.self_handle = Some(self_handle); + })) + .await?; + + if let Err(err) = s.establish_connection(conn.clone()).await { + warn!( + "Failed to establish connection with {}: {}", + conn.remote_id(), + err + ); + s.drop().await; + anyhow::bail!("Failed to establish connection: {}", err); + } - s + Ok(s) } - pub async fn get_state(&self) -> ConnState { - if let Ok(state) = self - .api + pub async fn open_connection( + endpoint: Endpoint, + remote_endpoint_id: EndpointId, + external_sender: tokio::sync::mpsc::Sender, + latest_frame: Watchable>, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)>, + ) -> Result { + let conn_state = Arc::new(Mutex::new(InnerConnState::Connecting)); + let last_keep_alive = Arc::new(Mutex::new(Instant::now())); + let id = rand::random(); + let (api, _) = Handle::spawn_with( + ConnActor::new( + id, + external_sender, + remote_endpoint_id, + true, + conn_state.clone(), + last_keep_alive.clone(), + latest_frame, + remote_frame_tx, + ), + |mut actor, rx| async move { actor.run(rx).await }, + ); + let s = Self { id, api }; + let self_handle = s.api.clone(); + s.api .call(act_ok!(actor => async move { - actor.state + actor.self_handle = Some(self_handle); })) - .await + .await?; + + let endpoint_addr = resolve_addr(&endpoint, remote_endpoint_id).await; + info!("Connecting to EndpointAddr: {:?}", endpoint_addr); + + let conn = match tokio::time::timeout( + CONNECTING_TIMEOUT, + endpoint.connect(endpoint_addr, crate::Direct::ALPN), + ) + .await { - state - } else { - ConnState::Closed + Ok(Ok(conn)) => conn, + Ok(Err(e)) => { + warn!( + "Initial connection to {} failed: {:?}", + remote_endpoint_id, e + ); + s.drop().await; + anyhow::bail!("Failed to establish connection: {}: {:?}", e, e); + } + Err(_) => { + warn!( + "Initial connection to {} timed out after {}s", + remote_endpoint_id, + CONNECTING_TIMEOUT.as_secs() + ); + s.drop().await; + anyhow::bail!("Connection timed out"); + } + }; + + if let Err(err) = s.establish_connection(conn).await { + warn!( + "Failed to establish connection with {}: {}", + remote_endpoint_id, err + ); + s.drop().await; + anyhow::bail!("Failed to establish connection: {}: {:?}", err, err); } - } - pub async fn close(&self) -> Result<()> { - self.api.call(act_ok!(actor => actor.close())).await + Ok(s) } pub async fn write(&self, pkg: DirectMessage) -> Result<()> { self.api.call(act_ok!(actor => actor.write(pkg))).await } - pub async fn incoming_connection(&self, conn: Connection, accept_not_open: bool) -> Result<()> { + pub async fn establish_connection(&self, conn: Connection) -> Result<()> { self.api - .call(act!(actor => actor.incoming_connection(conn, accept_not_open))) + .call(act!(actor => actor.establish_connection(conn))) .await } + + pub async fn drop(&self) { + if self.api.state() == ActorState::Stopped { + return; + } + self.api + .call(act_ok!(actor => async { + actor.close().await; + })) + .await + .ok(); + } } -impl Actor for ConnActor { - async fn run(&mut self) -> Result<()> { - let mut reconnect_ticker = tokio::time::interval(Duration::from_millis(500)); - let mut notification_ticker = tokio::time::interval(Duration::from_millis(500)); +#[allow(dead_code)] +async fn handshake(conn: Connection, handshake_timeout: Duration) -> Result<()> { + let handshake_task = async { + let (mut send, mut recv) = if conn.side() == iroh::endpoint::Side::Client { + conn.open_bi().await? + } else { + conn.accept_bi().await? + }; + let mut buf = [0u8; 1]; + info!( + "Performing connection handshake for #1: {}", + conn.remote_id() + ); + send.write_all(&buf).await?; + send.finish()?; + + info!( + "Performing connection handshake for #2: {}", + conn.remote_id() + ); + recv.read_exact(&mut buf).await?; + recv.read_to_end(usize::MAX).await?; + info!( + "Performing connection handshake for #3: {}", + conn.remote_id() + ); + Ok(()) + }; - reconnect_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); - notification_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + tokio::time::timeout(handshake_timeout, handshake_task).await? +} + +impl ConnActor { + async fn run(&mut self, rx: Receiver>) -> Result<()> { + //let mut reconnect_ticker = tokio::time::interval(Duration::from_millis(500)); + //reconnect_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + let mut keepalive_ticker = tokio::time::interval(KEEPALIVE_INTERVAL); + keepalive_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + let mut stats_ticker = tokio::time::interval(STATS_LOG_INTERVAL); + stats_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + debug!("ConnActor started for peer: {}", self.conn_endpoint_id); loop { + let current_state = { + let state = self.conn_state.lock().await; + state.clone() + }; + if current_state == InnerConnState::Closed { + debug!( + "ConnActor for {} is in Closed state, exiting run loop", + self.conn_endpoint_id + ); + break; + } tokio::select! { - Ok(action) = self.rx.recv_async() => { + Ok(action) = rx.recv_async() => { action(self).await; } - _ = reconnect_ticker.tick(), if self.state != ConnState::Closed => { - - let need_reconnect = self.send_stream.is_none() - || self.conn.as_ref().and_then(|c| c.close_reason()).is_some(); - - if need_reconnect && self.last_reconnect.elapsed() > self.reconnect_backoff { - if self.reconnect_count.load(std::sync::atomic::Ordering::SeqCst) < MAX_RECONNECTS { - warn!("Send stream stopped"); - let _ = self.try_reconnect().await; - } else { - warn!("Max reconnects reached, closing connection to {}", self.conn_endpoint_id); - break; - } - } - } - _ = notification_ticker.tick(), if self.state != ConnState::Closed - && (!self.sender_queue.is_empty() - || self.receiver_queue.is_empty()) => { - - if !self.sender_queue.is_empty() { - self.sender_notify.notify_one(); + _ = keepalive_ticker.tick() => { + if current_state != InnerConnState::Open { + continue; } - if !self.receiver_queue.is_empty() { - self.receiver_notify.notify_one(); - } - } - stream_recv = async { - let recv = self.recv_stream.as_mut().expect("checked in if via self.recv_stream.is_some()"); - recv.read_u32_le().await - }, if self.state != ConnState::Closed && self.recv_stream.is_some() => { - if let Ok(frame_size) = stream_recv { - let _res = self.remote_read_next(frame_size).await; - } - } - _ = self.sender_notify.notified(), if self.conn.is_some() && self.state == ConnState::Open => { - while !self.sender_queue.is_empty() { - if self.remote_write_next().await.is_err() { - warn!("Failed to write to remote, will attempt to reconnect"); - self.set_state(ConnState::Disconnected); - break; + if let Some(tx) = &self.write_tx { + let latest_frame = self.latest_frame.get(); + if latest_frame.is_empty() { + println!("Sending empty KeepAlive"); + } + match tx.try_send(DirectMessage::IDontLikeWarnings(latest_frame.clone())) { + Ok(_) => { + //info!("Sent keepalive, i am {}", if self.is_open_side { "OPEN" } else { "ACCEPT" }); + let new_len = self.queue_len.fetch_add(1, Ordering::Relaxed) + 1; + if new_len > QUEUE_WARN_LEN { + warn!("Stream queue length high (keepalive): {}", new_len); + } + } + Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => { + self.dropped_packets.fetch_add(1, Ordering::Relaxed); + } + Err(tokio::sync::mpsc::error::TrySendError::Closed(_)) => { + self.dropped_packets.fetch_add(1, Ordering::Relaxed); + } } } } - _ = self.receiver_notify.notified(), if self.conn.is_some() && self.state != ConnState::Closed => { - - while let Some(msg) = self.receiver_queue.pop_back() { - if self.external_sender.send(msg.clone()).is_err() { - warn!("No active receivers for incoming messages"); - self.set_state(ConnState::Disconnected); - break; - } + _ = stats_ticker.tick() => { + let q_len = self.queue_len.load(Ordering::Relaxed); + if q_len > 100 { + warn!("[PROBE-QUEUE] High Queue Len: {}", q_len); } + debug!( + "{}-{} Conn stats: endpoint_id={} ip={:?} state={:?} rx_count={} tx_count={} queue_len={} write_timeouts={} write_errors={} dropped_packets={}", + if self.is_open_side { "[OPEN]" } else { "[ACCEPT]" }, + self.id, + self.conn_endpoint_id, + self.dest_ip, + current_state, + self.rx_count.load(Ordering::Relaxed), + self.tx_count.load(Ordering::Relaxed), + self.queue_len.load(Ordering::Relaxed), + self.write_timeouts.load(Ordering::Relaxed), + self.consecutive_write_errors.load(Ordering::Relaxed), + self.dropped_packets.load(Ordering::Relaxed) + ); } _ = tokio::signal::ctrl_c() => { + info!("Received Ctrl-C, stopping actor"); break } } } - self.close().await; Ok(()) } } impl ConnActor { #[allow(clippy::too_many_arguments)] - pub async fn new( - rx: Receiver>, - self_handle: Handle, - external_sender: tokio::sync::broadcast::Sender, - endpoint: Endpoint, + pub fn new( + id: u64, + external_sender: tokio::sync::mpsc::Sender, conn_endpoint_id: EndpointId, - conn: Option, - send_stream: Option, - recv_stream: Option, + is_open_side: bool, + conn_state: Arc>, + last_keep_alive: Arc>, + latest_frame: Watchable>, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)>, ) -> Self { + if latest_frame.get().is_empty() { + println!("New: Setting empty frame"); + } Self { - rx, - state: if conn.is_some() && send_stream.is_some() && recv_stream.is_some() { - ConnState::Open - } else { - ConnState::Disconnected - }, + id, external_sender, - receiver_queue: VecDeque::with_capacity(QUEUE_SIZE), + read_task: None, + write_task: None, + write_tx: None, + connected_task: None, + queue_len: Arc::new(AtomicUsize::new(0)), sender_queue: VecDeque::with_capacity(QUEUE_SIZE), - conn, - send_stream, - recv_stream, - endpoint, - receiver_notify: tokio::sync::Notify::new(), - sender_notify: tokio::sync::Notify::new(), - last_reconnect: tokio::time::Instant::now(), - reconnect_backoff: Duration::from_millis(100), + conn: None, conn_endpoint_id, - self_handle, - reconnect_count: AtomicUsize::new(0), + self_handle: None, + rx_count: Arc::new(AtomicUsize::new(0)), + tx_count: Arc::new(AtomicUsize::new(0)), + write_timeouts: Arc::new(AtomicUsize::new(0)), + consecutive_write_errors: Arc::new(AtomicUsize::new(0)), + dropped_packets: Arc::new(AtomicUsize::new(0)), + is_open_side, + conn_state, + last_keep_alive, + health: Arc::new(Mutex::new(ConnHealthWindow::default())), + dest_ip: None, + latest_frame, + remote_frame_tx, } } - pub fn set_state(&mut self, state: ConnState) { - self.state = state; - } - pub async fn close(&mut self) { - self.state = ConnState::Closed; + { + let mut state_guard = self.conn_state.lock().await; + if *state_guard == InnerConnState::Closed { + debug!( + "ConnActor for {} already in Closed state, skipping close", + self.conn_endpoint_id + ); + return; + } + *state_guard = InnerConnState::Closed; + } + + info!("Closing connection actor"); if let Some(conn) = self.conn.as_mut() { conn.close(VarInt::from_u32(400), b"Connection closed by user"); } self.conn = None; - self.send_stream = None; - self.recv_stream = None; + + if let Some(task) = self.read_task.take() { + task.abort(); + } + if let Some(task) = self.write_task.take() { + task.abort(); + } + if let Some(task) = self.connected_task.take() { + task.abort(); + } } pub async fn write(&mut self, pkg: DirectMessage) { - self.sender_queue.push_front(pkg); - self.sender_notify.notify_one(); + if self.dest_ip.is_none() + && let DirectMessage::IpPacket(pkg) = &pkg + && let Ok(ip) = pkg.to_ipv4_packet() + { + self.dest_ip = Some(ip.get_destination()); + } + + if let Some(tx) = &self.write_tx { + trace!("Sending packet to write task"); + match tx.try_send(pkg) { + Ok(_) => { + let new_len = self.queue_len.fetch_add(1, Ordering::Relaxed) + 1; + if new_len > QUEUE_WARN_LEN { + warn!("Stream queue length high: {}", new_len); + } + } + Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => { + self.dropped_packets.fetch_add(1, Ordering::Relaxed); + if self + .dropped_packets + .load(Ordering::Relaxed) + .is_multiple_of(1000) + { + warn!( + "Write queue full, dropping packet (dropped={})", + self.dropped_packets.load(Ordering::Relaxed) + ); + } + } + Err(tokio::sync::mpsc::error::TrySendError::Closed(val)) => { + warn!("Write task channel closed, buffering packet."); + self.sender_queue.push_front(val); + while self.sender_queue.len() > MAX_SENDER_QUEUE { + self.sender_queue.pop_back(); + } + self.close().await; + } + } + } else { + trace!( + "Queueing packet for write. Queue size: {}", + self.sender_queue.len() + ); + self.sender_queue.push_front(pkg); + while self.sender_queue.len() > MAX_SENDER_QUEUE { + self.sender_queue.pop_back(); + } + } } - pub async fn incoming_connection( - &mut self, - conn: Connection, - accept_not_open: bool, - ) -> Result<()> { - let (send_stream, recv_stream) = if accept_not_open { - conn.accept_bi().await? + pub async fn establish_connection(&mut self, conn: Connection) -> Result<()> { + info!("Incoming connection from: {}", conn.remote_id()); + let self_handle = if let Some(api) = self.self_handle.clone() { + api } else { - conn.open_bi().await? + warn!("No API handle provided to read loop, cannot close connection on failure"); + return Err(anyhow::anyhow!("internal error: no API handle")); }; if conn.close_reason().is_some() { - self.state = ConnState::Closed; + warn!("Incoming connection already closed"); + self.close().await; return Err(anyhow::anyhow!("connection closed")); } + info!("Spawning read task for incoming connection"); + let rx_count = self.rx_count.clone(); + self.read_task = Some(tokio::spawn(retry_read_loop( + conn.clone(), + self.external_sender.clone(), + self_handle.clone(), + self.id, + rx_count, + self.last_keep_alive.clone(), + self.health.clone(), + self.remote_frame_tx.clone(), + ))); + + info!("Spawning write task for incoming connection"); + let (tx, rx) = tokio::sync::mpsc::channel(WRITE_CHANNEL_CAP); + self.queue_len.store(0, Ordering::Relaxed); + let write_timeouts = self.write_timeouts.clone(); + let tx_count = self.tx_count.clone(); + self.write_task = Some(tokio::spawn(write_loop_bounded( + conn.clone(), + rx, + self_handle.clone(), + self.id, + self.queue_len.clone(), + "main", + tx_count, + write_timeouts, + self.health.clone(), + ))); + self.write_tx = Some(tx.clone()); + + self.connected_task = Some(tokio::spawn(connection_watcher_loop( + conn.clone(), + self_handle.clone(), + self.id, + side_label(self.is_open_side), + self.health.clone(), + ))); + self.conn = Some(conn); - self.send_stream = Some(send_stream); - self.recv_stream = Some(recv_stream); - self.state = ConnState::Open; - self.sender_notify.notify_one(); - self.receiver_notify.notify_one(); - self.reconnect_backoff = RECONNECT_BACKOFF_BASE; + if self.conn.is_some() { + let snapshot = self.snapshot().await; + info!("iroh-conn-established {}", snapshot); + debug!( + "iroh-qlog-filename-hint peer={} conn_actor_id={} quic_stable_id={} side={} qlog_filename_format=--<{}>.qlog", + self.conn_endpoint_id, + self.id, + snapshot + .quic_stable_id + .map(|value| value.to_string()) + .unwrap_or_else(|| "unknown".to_string()), + snapshot.side, + snapshot.side + ); + } + self.consecutive_write_errors.store(0, Ordering::Relaxed); + self.rx_count.store(0, Ordering::Relaxed); + self.tx_count.store(0, Ordering::Relaxed); + { + let mut health = self.health.lock().await; + *health = ConnHealthWindow::default(); + } - // SHOULD NOT CHANGE but just for sanity - //self.conn_node_id = self.conn.clone().expect("new_conn").remote_node_id()?; + while let Some(msg) = self.sender_queue.pop_back() { + match tx.try_send(msg) { + Ok(_) => { + let new_len = self.queue_len.fetch_add(1, Ordering::Relaxed) + 1; + if new_len > QUEUE_WARN_LEN { + warn!("Stream queue length high (flush): {}", new_len); + } + } + Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => { + self.dropped_packets.fetch_add(1, Ordering::Relaxed); + warn!( + "Write task channel full while flushing queued messages, dropping {} messages", + self.sender_queue.len() + ); + } + Err(tokio::sync::mpsc::error::TrySendError::Closed(_)) => { + self.dropped_packets.fetch_add(1, Ordering::Relaxed); + warn!( + "Write task channel closed while flushing queued messages, dropping {} messages", + self.sender_queue.len() + ); + self.close().await; + return Err(anyhow::anyhow!("connection closed")); + } + } + } + + let mut state_guard = self.conn_state.lock().await; + *state_guard = InnerConnState::Open; Ok(()) } - async fn try_reconnect(&mut self) -> Result<()> { - if self.state == ConnState::Closed { - return Err(anyhow::anyhow!("actor closed for good")); + pub async fn snapshot(&self) -> ConnSnapshot { + let state = self.conn_state.lock().await.clone(); + let keep_alive = *self.last_keep_alive.lock().await; + let idle_for_ms = Instant::now().duration_since(keep_alive).as_millis(); + let ( + quic_stable_id, + selected_path, + paths, + total_lost_packets, + total_udp_tx_datagrams, + total_udp_rx_datagrams, + ) = if let Some(conn) = self.conn.as_ref() { + let paths = snapshot_paths(conn); + let selected_path = paths.iter().find(|path| path.is_selected).cloned(); + let stats = conn.stats(); + ( + Some(conn.stable_id()), + selected_path, + paths, + Some(stats.lost_packets), + Some(stats.udp_tx.datagrams), + Some(stats.udp_rx.datagrams), + ) + } else { + (None, None, Vec::new(), None, None, None) + }; + + let rx_count = self.rx_count.load(Ordering::Relaxed); + let tx_count = self.tx_count.load(Ordering::Relaxed); + let write_timeouts = self.write_timeouts.load(Ordering::Relaxed); + let consecutive_write_errors = self.consecutive_write_errors.load(Ordering::Relaxed); + let dropped_packets = self.dropped_packets.load(Ordering::Relaxed); + + let total_lost = total_lost_packets.unwrap_or(0); + let total_udp_tx = total_udp_tx_datagrams.unwrap_or(0); + let total_udp_rx = total_udp_rx_datagrams.unwrap_or(0); + + let mut health = self.health.lock().await; + let rx_progress = rx_count > health.last_rx_count || total_udp_rx > health.last_udp_rx; + let tx_progress = tx_count > health.last_tx_count || total_udp_tx > health.last_udp_tx; + let loss_jump = total_lost > health.last_lost; + + let liveness = classify_liveness( + state.clone(), + selected_path.as_ref(), + &paths, + rx_progress, + tx_progress, + loss_jump, + &health, + ); + + let snapshot = ConnSnapshot { + conn_actor_id: self.id, + peer: self.conn_endpoint_id, + quic_stable_id, + side: side_label(self.is_open_side), + state, + liveness, + idle_for_ms, + rx_count, + tx_count, + queue_len: self.queue_len.load(Ordering::Relaxed), + write_timeouts, + consecutive_write_errors, + consecutive_read_timeouts: health.consecutive_read_timeouts, + consecutive_write_timeouts: health.consecutive_write_timeouts, + no_active_paths: health.no_active_paths, + dropped_packets, + total_lost_packets, + total_udp_tx_datagrams, + total_udp_rx_datagrams, + selected_path, + paths, + }; + + health.last_rx_count = rx_count; + health.last_tx_count = tx_count; + health.last_udp_rx = total_udp_rx; + health.last_udp_tx = total_udp_tx; + health.last_lost = total_lost; + + snapshot + } +} + +fn classify_liveness( + state: InnerConnState, + selected_path: Option<&ConnPathSnapshot>, + paths: &[ConnPathSnapshot], + rx_progress: bool, + tx_progress: bool, + loss_jump: bool, + health: &ConnHealthWindow, +) -> ConnLiveness { + if state != InnerConnState::Open { + return ConnLiveness::Dead; + } + + if health.no_active_paths { + return ConnLiveness::Dead; + } + + let has_open_path = paths.iter().any(|path| !path.is_closed); + if !has_open_path { + return ConnLiveness::Dead; + } + + let has_selected_open_path = selected_path.is_some_and(|path| !path.is_closed); + let blackhole_seen = selected_path + .and_then(|path| path.black_holes_detected) + .unwrap_or(0) + > 0; + + if has_selected_open_path && rx_progress { + return ConnLiveness::Usable; + } + + if has_selected_open_path + && tx_progress + && health.consecutive_read_timeouts < MAX_CONSECUTIVE_READ_TIMEOUTS + && health.consecutive_write_timeouts < MAX_CONSECUTIVE_WRITE_TIMEOUTS + && !blackhole_seen + { + return ConnLiveness::Suspect; + } + + if !has_selected_open_path + && has_open_path + && health.consecutive_read_timeouts < MAX_CONSECUTIVE_READ_TIMEOUTS + { + return ConnLiveness::Suspect; + } + + if health.consecutive_read_timeouts >= MAX_CONSECUTIVE_READ_TIMEOUTS + && !rx_progress + && (blackhole_seen + || loss_jump + || health.consecutive_write_timeouts >= MAX_CONSECUTIVE_WRITE_TIMEOUTS) + { + return ConnLiveness::Dead; + } + + ConnLiveness::Suspect +} + +async fn connection_watcher_loop( + conn: Connection, + api: Handle, + conn_actor_id: u64, + side: &'static str, + health: Arc>, +) { + let mut watcher = conn.paths_stream(); + while let Some(update) = watcher.next().await { + let path_snapshot = snapshot_paths(&conn) + .into_iter() + .map(|path| path.to_string()) + .collect::>() + .join(" | "); + debug!( + "iroh-path-update peer={} conn_actor_id={} quic_stable_id={} side={} update={:?} paths=[{}]", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + side, + update, + path_snapshot + ); + if conn.weak_handle().upgrade().is_none() { + warn!( + "iroh-path-abandoned peer={} conn_actor_id={} quic_stable_id={} side={} paths=[{}]", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + side, + path_snapshot + ); + break; } + } + + // all paths abandoned, connection is dead + warn!( + "iroh-no-active-paths peer={} conn_actor_id={} quic_stable_id={} side={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + side + ); + { + let mut health = health.lock().await; + health.no_active_paths = true; + } + let _ = api.call(act_ok!(actor => actor.close())).await; +} - self.state = ConnState::Connecting; - self.reconnect_backoff *= 3; - self.last_reconnect = tokio::time::Instant::now(); +#[allow(clippy::too_many_arguments)] +async fn write_loop_bounded( + conn: Connection, + mut rx: tokio::sync::mpsc::Receiver, + api: Handle, + conn_actor_id: u64, + queue_len: Arc, + label: &'static str, + tx_count: Arc, + write_timeout: Arc, + health: Arc>, +) { + info!("Write task started ({})", label); + while let Some(msg) = rx.recv().await { + let _ = queue_len.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |v| { + Some(v.saturating_sub(1)) + }); + let msg_kind = msg.kind_name(); + let payload_len = msg.payload_len(); + let bytes = match postcard::to_stdvec(&msg) { + Ok(b) => b, + Err(e) => { + warn!("Failed to serialize message: {}", e); + continue; + } + }; + let mut buf = vec![DATAGRAM_PREFIX]; + buf.extend_from_slice(&bytes); + let datagram_len = buf.len(); - self.send_stream = None; - self.recv_stream = None; - self.conn = None; + let mut retries = 0; + while retries < 1 { + /*debug!( + "iroh-send peer={} conn_actor_id={} quic_stable_id={} kind={} payload_bytes={} datagram_bytes={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + msg_kind, + payload_len, + datagram_len + );*/ + match time::timeout(KEEPALIVE_INTERVAL * 3, async { + conn.send_datagram(Bytes::from(buf.clone())) + }) + .await + { + Ok(Ok(())) => { + { + let mut health = health.lock().await; + health.consecutive_write_timeouts = 0; + } + /*debug!( + "iroh-send-ok peer={} conn_actor_id={} quic_stable_id={} kind={} payload_bytes={} datagram_bytes={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + msg_kind, + payload_len, + datagram_len + );*/ + break; + } + Ok(Err(err)) => { + warn!("Write error (frame): {}, {:?}, retrying...", err, err); + { + let mut health = health.lock().await; + health.consecutive_write_timeouts = + health.consecutive_write_timeouts.saturating_add(1); + } + retries += 1; + time::sleep(Duration::from_millis(100)).await; + } + Err(_) => { + warn!("Write error timeout (frame)"); + write_timeout.fetch_add(1, Ordering::SeqCst); + { + let mut health = health.lock().await; + health.consecutive_write_timeouts = + health.consecutive_write_timeouts.saturating_add(1); + } + time::sleep(Duration::from_millis(100)).await; + break; + } + } + } - tokio::spawn({ - let api = self.self_handle.clone(); - let endpoint = self.endpoint.clone(); - let conn_node_id = self.conn_endpoint_id; - async move { - if let Ok(conn) = endpoint.connect(conn_node_id, crate::Direct::ALPN).await { - let _ = api - .call(act!(actor => actor.incoming_connection(conn, false))) - .await; - let _ = api.call(act_ok!(actor => async move { actor.reconnect_count.store(0, std::sync::atomic::Ordering::SeqCst) })).await; + if retries >= 1 { + let liveness = api + .call(act_ok!(actor => async move { actor.snapshot().await.liveness })) + .await + .unwrap_or(ConnLiveness::Dead); + warn!( + "Write failed after 1 retries, keeping connection in {:?} state for peer_id: {}", + liveness, + if let Ok(peer_id) = api + .call(act_ok!(actor => async move { actor.conn_endpoint_id })) + .await + { + peer_id.to_string() } else { - let _ = api.call(act_ok!(actor => async move { actor.reconnect_count.fetch_add(1, std::sync::atomic::Ordering::SeqCst) })).await; + "unknown".to_string() } + ); + if liveness == ConnLiveness::Dead { + info!("Write task stopped ({})", label); + let _ = api.call(act_ok!(actor => actor.close())).await; + break; } - }); - Ok(()) + continue; + } + + tx_count.fetch_add(1, Ordering::SeqCst); } +} - async fn remote_write_next(&mut self) -> Result<()> { - let start = SystemTime::now(); - let mut wrote = 0; - if let Some(send_stream) = &mut self.send_stream { - while let Some(msg) = self.sender_queue.back() { - let bytes = postcard::to_stdvec(msg)?; - send_stream.write_u32_le(bytes.len() as u32).await?; - send_stream.write_all(bytes.as_slice()).await?; - let _ = self.sender_queue.pop_back(); - wrote += 1; - if wrote >= 256 { +async fn retry_read_loop( + conn: Connection, + sender: tokio::sync::mpsc::Sender, + api: Handle, + conn_actor_id: u64, + rx_count: Arc, + last_keep_alive: Arc>, + health: Arc>, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)>, +) { + info!("Read task started"); + loop { + match tokio::time::timeout(KEEPALIVE_INTERVAL * 3, read_next_msg(&conn)).await { + Ok(Ok((msg, datagram_len))) => { + { + let mut health = health.lock().await; + health.consecutive_read_timeouts = 0; + } + rx_count.fetch_add(1, Ordering::SeqCst); + //trace!("Read message from stream, forwarding to network actor"); + let start = std::time::Instant::now(); + let msg_kind = msg.kind_name(); + let payload_len = msg.payload_len(); + /*debug!( + "iroh-raw-recv peer={} conn_actor_id={} quic_stable_id={} kind={} payload_bytes={} datagram_bytes={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + msg_kind, + payload_len, + datagram_len + );*/ + let mut last_keep_alive = last_keep_alive.lock().await; + *last_keep_alive = Instant::now(); + if let DirectMessage::IDontLikeWarnings(frame) = msg { + /*debug!( + "Received keepalive message, not forwarding to network actor: peer={} conn_actor_id={} quic_stable_id={} datagram_bytes={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + datagram_len + );*/ + if frame.is_empty() { + let remote_id = conn.remote_id(); + debug!(%remote_id, "received empty keepalive frame"); + continue; + } + remote_frame_tx.send((conn.remote_id(), frame)).await.ok(); + continue; + } + + /*debug!( + "iroh-recv peer={} conn_actor_id={} quic_stable_id={} kind={} payload_bytes={} datagram_bytes={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + msg_kind, + payload_len, + datagram_len + );*/ + + if let Err(e) = sender.send(msg).await { + warn!("Failed to forward message to network actor: {}", e); break; } + /*debug!( + "iroh-forwarded-to-network peer={} conn_actor_id={} quic_stable_id={} kind={} payload_bytes={} datagram_bytes={}", + conn.remote_id(), + conn_actor_id, + conn.stable_id(), + msg_kind, + payload_len, + datagram_len + );*/ + if start.elapsed().as_millis() > BACKPRESSURE_WARN_MS { + warn!( + "Direct->Network backpressure: send blocked {} ms", + start.elapsed().as_millis() + ); + } + } + Ok(Err(ReadError::Multiplex(err))) => { + warn!("Multiplex error: {:?}", err); + continue; + } + Ok(Err(e)) => { + warn!("Stream read error: {:?}", e); + info!("paths info: {:?}", conn.paths()); + info!("Read task stopped"); + warn!( + "Read failed after hard error, dropping connection: peer_id: {}", + if let Ok(peer_id) = api + .call(act_ok!(actor => async move { actor.conn_endpoint_id })) + .await + { + peer_id.to_string() + } else { + "unknown".to_string() + } + ); + let _ = api.call(act_ok!(actor => actor.close())).await; + break; + } + Err(e) => { + warn!("Stream read error: timeout after {}", e); + { + let mut health = health.lock().await; + health.consecutive_read_timeouts = + health.consecutive_read_timeouts.saturating_add(1); + } + + let snapshot = api + .call(act_ok!(actor => async move { actor.snapshot().await })) + .await; + match snapshot.map(|snapshot| snapshot.liveness) { + Ok(ConnLiveness::Dead) => { + info!("Read task stopped"); + warn!( + "Read failed after timeout evidence, dropping connection: peer_id: {}", + if let Ok(peer_id) = api + .call(act_ok!(actor => async move { actor.conn_endpoint_id })) + .await + { + peer_id.to_string() + } else { + "unknown".to_string() + } + ); + let _ = api.call(act_ok!(actor => actor.close())).await; + break; + } + Ok(liveness) => { + warn!( + "Read timeout moved connection to {:?}, keeping it for recovery: peer={} conn_actor_id={} quic_stable_id={}", + liveness, + conn.remote_id(), + conn_actor_id, + conn.stable_id() + ); + + warn!( + "Stopping read task just because it doesnt open a new conn if it is kept" + ); + let _ = api.call(act_ok!(actor => actor.close())).await; + break; + } + Err(err) => { + warn!("Failed to classify timed out connection: {}", err); + } + } } - } else { - return Err(anyhow::anyhow!("no send stream")); } + } +} + +#[derive(Debug)] +enum ReadError { + Datagram(String), + Multiplex(String), + Deserialize(String), +} - if !self.sender_queue.is_empty() { - self.sender_notify.notify_one(); +impl Display for ReadError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ReadError::Datagram(e) => write!(f, "Read error: {}", e), + ReadError::Multiplex(e) => write!(f, "Read error: {}", e), + ReadError::Deserialize(e) => write!(f, "Read error: {}", e), } + } +} - let end = SystemTime::now(); - let duration = end.duration_since(start).unwrap(); - debug!("write_remote: {wrote}; elapsed: {}", duration.as_millis()); - Ok(()) +impl std::error::Error for ReadError {} + +async fn read_next_msg(conn: &Connection) -> Result<(DirectMessage, usize), ReadError> { + let buf = conn + .read_datagram() + .await + .map_err(|e| ReadError::Datagram(format!("failed to read datagram: {}", e)))?; + let datagram_len = buf.len(); + let prefix = buf.first().copied(); + let preview_len = buf.len().min(8); + let preview = buf[..preview_len].to_vec(); + /*debug!( + "iroh-read-datagram peer={} quic_stable_id={} datagram_bytes={} prefix={:?} preview={:02X?}", + conn.remote_id(), + conn.stable_id(), + datagram_len, + prefix, + preview + );*/ + if buf.len() > 1 && buf[0] == DATAGRAM_PREFIX { + let msg: DirectMessage = postcard::from_bytes(&buf[1..]) + .map_err(|e| { + warn!( + "iroh-read-deserialize-failed peer={} quic_stable_id={} datagram_bytes={} prefix={:?} preview={:02X?} error={}", + conn.remote_id(), + conn.stable_id(), + datagram_len, + prefix, + preview, + e + ); + ReadError::Deserialize(format!("failed to deserialize message: {}", e)) + })?; + /*debug!( + "iroh-read-deserialized peer={} quic_stable_id={} kind={} payload_bytes={} datagram_bytes={}", + conn.remote_id(), + conn.stable_id(), + msg.kind_name(), + msg.payload_len(), + datagram_len + );*/ + Ok((msg, datagram_len)) + } else { + debug!( + "iroh-raw-recv-unhandled peer={} datagram_bytes={} prefix={:?} preview={:02X?}", + conn.remote_id(), + datagram_len, + prefix, + preview + ); + Err(ReadError::Multiplex(format!( + "not meant for us: len={} prefix={:?}", + datagram_len, prefix + ))) } +} - async fn remote_read_next(&mut self, frame_len: u32) -> Result { - if let Some(recv_stream) = &mut self.recv_stream { - let mut buf = vec![0; frame_len as usize]; - - let start = SystemTime::now(); - recv_stream.read_exact(&mut buf).await?; - - if let Ok(pkg) = postcard::from_bytes(&buf) { - match pkg { - DirectMessage::IpPacket(ip_pkg) => { - if let Ok(ip_pkg) = ip_pkg.to_ipv4_packet() { - let msg = DirectMessage::IpPacket(ip_pkg.into()); - self.receiver_queue.push_front(msg.clone()); - self.receiver_notify.notify_one(); - let end = SystemTime::now(); - let duration = end.duration_since(start).unwrap(); - debug!("read_remote: elapsed: {}", duration.as_millis()); - Ok(msg) - } else { - Err(anyhow::anyhow!("failed to convert to IPv4 packet")) - } - } - #[allow(unreachable_patterns)] - _ => Err(anyhow::anyhow!("unsupported message type")), - } - } else { - Err(anyhow::anyhow!("failed to deserialize message")) - } - } else { - Err(anyhow::anyhow!("no recv stream")) +async fn resolve_addr(ep: &Endpoint, peer_id: EndpointId) -> EndpointAddr { + let dns = DnsAddressLookup::n0_dns() + .dns_resolver(ep.dns_resolver().unwrap().clone()) + .build(); + + let relay_url = match dns.resolve(peer_id) { + None => None, + Some(stream) => { + // Take the first successful result + stream + .filter_map(|item| item.ok()) // unwrap Result + .find_map(|item| item.relay_urls().next().cloned()) + .await } + }; + + match relay_url { + Some(url) => EndpointAddr::new(peer_id).with_relay_url(url), + None => EndpointAddr::new(peer_id), } } diff --git a/src/direct_connect.rs b/src/direct_connect.rs index cabad4e..53a765f 100644 --- a/src/direct_connect.rs +++ b/src/direct_connect.rs @@ -1,45 +1,108 @@ -use actor_helper::{Action, Handle, act}; +use actor_helper::{Action, Handle, Receiver, act, act_ok}; use anyhow::Result; -use iroh::{EndpointId, endpoint::Connection, protocol::ProtocolHandler}; +use iroh::{ + Endpoint, EndpointId, + endpoint::{Connection, VarInt}, + protocol::ProtocolHandler, +}; +use n0_watcher::Watchable; use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, hash_map::Entry}; -use tracing::{debug, info}; +use std::{ + collections::{HashMap, HashSet, hash_map::Entry}, + ops::{Add, Div}, + sync::{Arc, atomic::AtomicUsize}, +}; +use tokio::{ + sync::{Mutex, RwLock}, + time::Instant, +}; +use tracing::{debug, error, info, trace, warn}; -use crate::{connection::Conn, local_networking::Ipv4Pkg}; +use crate::{ + connection::{Conn, ConnLiveness, ConnSnapshot, InnerConnState}, + tun::Ipv4Pkg, +}; + +const MAX_RECONNECT_ATTEMPTS: usize = 100; +const CONN_COUNT_TARGET: usize = 2; #[derive(Debug, Clone)] pub struct Direct { api: Handle, } +#[derive(Debug, Clone)] +pub struct ConnGen { + conn_pool: Arc>>, + conn_counter: Arc, + last_conn_attempt: Arc>>, + attempts: Watchable, +} + +impl Default for ConnGen { + fn default() -> Self { + Self { + conn_pool: Arc::new(Mutex::new(Vec::new())), + conn_counter: Arc::new(AtomicUsize::new(0)), + last_conn_attempt: Arc::new(RwLock::new(None)), + attempts: Watchable::new(0), + } + } +} + #[derive(Debug)] struct DirectActor { - peers: HashMap, + peers: HashMap, endpoint: iroh::endpoint::Endpoint, - rx: actor_helper::Receiver>, - direct_connect_tx: tokio::sync::broadcast::Sender, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)>, + remote_to_tun_tx: tokio::sync::mpsc::Sender, + transmit_frame_rx: tokio::sync::mpsc::Receiver<(EndpointId, Vec)>, + latest_frames: HashMap>, + latest_global_frame: Watchable>, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub enum DirectMessage { IpPacket(Ipv4Pkg), - IDontLikeWarnings, + IDontLikeWarnings(Vec), +} + +impl DirectMessage { + pub fn kind_name(&self) -> &'static str { + match self { + Self::IpPacket(_) => "ip", + Self::IDontLikeWarnings(_) => "keepalive", + } + } + + pub fn payload_len(&self) -> usize { + match self { + Self::IpPacket(pkg) => pkg.as_slice().len(), + Self::IDontLikeWarnings(_) => 0, + } + } } impl Direct { - pub const ALPN: &[u8] = b"/iroh/lan-direct/1"; + pub const ALPN: &[u8] = b"/iroh/lan-direct/2"; pub fn new( endpoint: iroh::endpoint::Endpoint, - direct_connect_tx: tokio::sync::broadcast::Sender, + remote_to_tun_tx: tokio::sync::mpsc::Sender, + transmit_frame_rx: tokio::sync::mpsc::Receiver<(EndpointId, Vec)>, + remote_frame_tx: tokio::sync::mpsc::Sender<(EndpointId, Vec)>, ) -> Self { - let (api, rx) = Handle::channel(); - let mut actor = DirectActor { - peers: HashMap::new(), - endpoint, - rx, - direct_connect_tx, - }; - tokio::spawn(async move { actor.run().await }); + let (api, _) = Handle::spawn_with( + DirectActor { + peers: HashMap::new(), + endpoint, + remote_frame_tx, + remote_to_tun_tx, + transmit_frame_rx, + latest_frames: HashMap::new(), + latest_global_frame: Watchable::new(Vec::new()), + }, + |mut actor, rx| async move { actor.run(rx).await }, + ); Self { api } } @@ -55,17 +118,11 @@ impl Direct { .await } - pub async fn get_endpoint(&self) -> iroh::endpoint::Endpoint { - self.api - .call(act!(actor => actor.get_endpoint())) - .await - .unwrap() + pub async fn ensure_connection(&self, to: EndpointId) -> Result<()> { + self.api.call(act!(actor => actor.ensure_peer(to))).await } - pub async fn get_conn_state( - &self, - endpoint_id: EndpointId, - ) -> Result { + pub async fn get_conn_state(&self, endpoint_id: EndpointId) -> Result { self.api .call(act!(actor => actor.get_conn_state(endpoint_id))) .await @@ -74,91 +131,355 @@ impl Direct { pub async fn close(&self) -> Result<()> { self.api.call(act!(actor => actor.close())).await } + + pub async fn get_connected_peers(&self) -> Result> { + self.api + .call(act_ok!(actor => async { + actor.peers.keys().cloned().collect::>() + } + )) + .await + } } impl DirectActor { - async fn run(&mut self) { + async fn run(&mut self, rx: Receiver>) -> Result<(), anyhow::Error> { + let mut reconnect_interval = tokio::time::interval(std::time::Duration::from_millis(500)); + reconnect_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + debug!("DirectActor run loop started"); loop { tokio::select! { - Ok(action) = self.rx.recv_async() => { + Ok(action) = rx.recv_async() => { action(self).await; } - _ = tokio::signal::ctrl_c() => { - break + _ = reconnect_interval.tick() => { + self.connection_driver().await; } + Some((.., bytes)) = self.transmit_frame_rx.recv() => { + if bytes.is_empty() { + println!("transmit_frame_rx: Received empty frame"); + } + if bytes != self.latest_global_frame.get() { + println!("transmit_frame_rx: Setting new frame"); + let _ = self.latest_global_frame.set(bytes.clone()); + } + /* + match self.latest_frames.entry(to) { + Entry::Occupied(mut entry) => { + if !entry.get().eq(&bytes) { + trace!(%to, "updated peer frame"); + entry.insert(bytes.clone()); + } + } + Entry::Vacant(entry) => { + debug!(%to, "initial peer frame"); + entry.insert(bytes.clone()); + } + } + if let Some(peer) = self.peers.get_mut(&to) { + for conn in peer.conn_pool.lock().await.iter() { + conn.set_latest_frame(bytes.clone()).await; + } + } */ + } + else => break, } } + Ok(()) } +} - async fn handle_connection(&mut self, conn: iroh::endpoint::Connection) -> Result<()> { - info!("New direct connection from {:?}", conn.remote_id()); - let remote_id = conn.remote_id(); +impl DirectActor { + async fn connection_driver(&mut self) { + for (id, peer) in self.peers.clone() { + // check reserve connections for alive + { + let mut tbd = Vec::new(); + let mut guard = peer.conn_pool.lock().await; + for conn in guard.iter_mut() { + if !conn.is_alive().await { + let snapshot = conn + .snapshot() + .await + .map(|snapshot| snapshot.to_string()) + .unwrap_or_else(|| { + format!("conn_actor_id={} snapshot=unavailable", conn.id()) + }); + debug!("iroh-pool-drop-dead peer={} snapshot=[{}]", id, snapshot); + conn.drop().await; + tbd.push(conn.id()); + peer.conn_counter + .fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + } + } + guard.retain(|conn| !tbd.contains(&conn.id())); - match self.peers.entry(remote_id) { - Entry::Occupied(mut entry) => { - entry.get_mut().incoming_connection(conn, true).await?; - } - Entry::Vacant(entry) => { - let (send_stream, recv_stream) = conn.accept_bi().await?; - entry.insert( - Conn::new( + if peer.conn_counter.load(std::sync::atomic::Ordering::SeqCst) < CONN_COUNT_TARGET + && peer.attempts.get() <= MAX_RECONNECT_ATTEMPTS + && peer + .last_conn_attempt + .read() + .await + .as_ref() + .map(|last_attempt| { + let should_wait_for = (peer.attempts.get() as f32) + .powf(2f32) + .div(10f32) + .add(2f32) + .min(300f32); + info!( + "last_attempt={} should_wait_for={should_wait_for:?}", + last_attempt.elapsed().as_secs_f32() + ); + should_wait_for <= last_attempt.elapsed().as_secs_f32() + }) + .unwrap_or(true) + { + peer.last_conn_attempt.write().await.replace(Instant::now()); + + info!( + "Peer {} has not enough open connections and {} attempts, will try to reconnect", + id, + peer.attempts.get() + ); + drop(guard); + self.open_new_connection( + id, + peer.clone(), self.endpoint.clone(), - conn, - send_stream, - recv_stream, - self.direct_connect_tx.clone(), + self.remote_to_tun_tx.clone(), ) - .await?, - ); + .await; + } } } + } - Ok(()) + async fn open_new_connection( + &self, + remote_eid: EndpointId, + peer: ConnGen, + endpoint: Endpoint, + direct_connect_tx: tokio::sync::mpsc::Sender, + ) { + peer.conn_counter + .fetch_add(1, std::sync::atomic::Ordering::SeqCst); + let attempts = peer.attempts.get(); + peer.attempts.set(attempts.saturating_add(1)).ok(); + + // Try open new connection + let last_frame = self.latest_global_frame.clone();//self.latest_frames.get(&remote_eid).cloned().unwrap_or_default(); + let remote_frame_tx = self.remote_frame_tx.clone(); + tokio::spawn(async move { + info!(%remote_eid, "attempting to open new connection"); + match Conn::open_connection(endpoint.clone(), remote_eid, direct_connect_tx, last_frame, remote_frame_tx).await { + Ok(new_conn) => { + debug!(%remote_eid, "successfully established connection"); + if new_conn.is_alive().await { + let snapshot = new_conn + .snapshot() + .await + .map(|snapshot| snapshot.to_string()) + .unwrap_or_else(|| { + format!("conn_actor_id={} snapshot=unavailable", new_conn.id()) + }); + let mut guard = peer.conn_pool.lock().await; + guard.push(new_conn.clone()); + info!( + "iroh-pool-add-open peer={} snapshot=[{}]", + remote_eid, snapshot + ); + peer.attempts.set(0).ok(); + } else { + debug!( + %remote_eid, "new connection is not alive after establishment, dropping" + ); + peer.conn_counter + .fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + new_conn.drop().await; + } + } + Err(err) => { + peer.conn_counter + .fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + error!("Failed to establish connection to {}: {}", remote_eid, err); + } + } + }); + } + + async fn handle_connection(&mut self, conn: iroh::endpoint::Connection) -> Result<()> { + let remote_eid = conn.remote_id(); + info!(%remote_eid, "handling new connection"); + let peer = self.peers.entry(remote_eid).or_default().clone(); + let direct_connect_tx = self.remote_to_tun_tx.clone(); + + peer.conn_counter + .fetch_add(1, std::sync::atomic::Ordering::SeqCst); + + let remote_eid = conn.remote_id(); + let last_frame = self.latest_global_frame.clone();//self.latest_frames.get(&remote_eid).cloned().unwrap_or_default(); + match Conn::accept_connection(conn.clone(), direct_connect_tx.clone(), last_frame, self.remote_frame_tx.clone()).await { + Ok(remote_conn) => { + debug!(%remote_eid, "successfully accepted connection"); + if remote_conn.is_alive().await { + let snapshot = remote_conn + .snapshot() + .await + .map(|snapshot| snapshot.to_string()) + .unwrap_or_else(|| { + format!("conn_actor_id={} snapshot=unavailable", remote_conn.id()) + }); + let mut guard = peer.conn_pool.lock().await; + guard.push(remote_conn.clone()); + peer.attempts.set(0).ok(); + info!( + "iroh-pool-add-accept peer={} snapshot=[{}]", + remote_eid, snapshot + ); + } else { + debug!(%remote_eid, "accepted connection is not alive after establishment, dropping"); + remote_conn.drop().await; + peer.conn_counter + .fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + return Err(anyhow::anyhow!( + "Accepted connection from {} is not alive after establishment", + remote_eid + )); + } + Ok(()) + } + Err(err) => { + error!(%remote_eid, ?err, "failed to accept connection"); + conn.close(VarInt::from_u32(411), b"Failed to accept connection"); + peer.conn_counter + .fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + Err(anyhow::anyhow!( + "Failed to accept connection from {}: {}", + remote_eid, + err + )) + } + } } async fn route_packet(&mut self, to: EndpointId, pkg: DirectMessage) -> Result<()> { + //trace!("Routing packet to {}", to); match self.peers.entry(to) { Entry::Occupied(entry) => { - if entry.get().get_state().await == crate::connection::ConnState::Closed { - debug!("Connection to peer {} closed, removing", to); - entry.remove(); - return Err(anyhow::anyhow!("connection to peer is not running")); + let peer = entry.get(); + let msg_kind = pkg.kind_name(); + let payload_len = pkg.payload_len(); + + let mut attempt_order: Vec<(u8, u128, Conn, ConnSnapshot)> = Vec::new(); + let mut pool_snapshots = Vec::new(); + let guard = peer.conn_pool.lock().await; + for conn in guard.iter() { + if let Some(snapshot) = conn.snapshot().await { + pool_snapshots.push(snapshot.to_string()); + if snapshot.liveness != ConnLiveness::Dead { + let priority = match snapshot.liveness { + ConnLiveness::Usable => 0, + ConnLiveness::Suspect => 1, + ConnLiveness::Dead => 2, + }; + attempt_order.push(( + priority, + snapshot.idle_for_ms, + conn.clone(), + snapshot, + )); + } + } } + drop(guard); + attempt_order + .sort_by_key(|(priority, idle_for_ms, _, _)| (*priority, *idle_for_ms)); - entry.get().write(pkg).await?; + /* + debug!( + "iroh-route-pool peer={} kind={} payload_bytes={} pool_size={} open_candidates={} snapshots=[{}]", + to, + msg_kind, + payload_len, + pool_snapshots.len(), + attempt_order.len(), + if pool_snapshots.is_empty() { + "none".to_string() + } else { + pool_snapshots.join(" || ") + } + ); + */ + + for (_, _idle_for_ms, conn, snapshot) in attempt_order { + /*debug!( + "iroh-route-selected peer={} kind={} payload_bytes={} attempted_liveness={} attempted_idle_for_ms={} snapshot=[{}]", + to, msg_kind, payload_len, snapshot.liveness, idle_for_ms, snapshot + );*/ + if conn.write(pkg.clone()).await.is_ok() { + return Ok(()); + } + warn!( + "iroh-route-write-failed peer={} kind={} payload_bytes={} snapshot=[{}]", + to, msg_kind, payload_len, snapshot + ); + } + error!("Failed to write packet to peer {}: no open connections", to); + Err(anyhow::anyhow!( + "Failed to write packet to peer {}: no open connections", + to + )) } Entry::Vacant(entry) => { - let conn = - Conn::connect(self.endpoint.clone(), to, self.direct_connect_tx.clone()).await; - - conn.write(pkg).await?; - entry.insert(conn); + info!("No active connection to {}, initiating new connection", to); + entry.insert(Default::default()); + Err(anyhow::anyhow!( + "No active connection to {}, initiating new connection", + to + )) } } + } + + async fn ensure_peer(&mut self, to: EndpointId) -> Result<()> { + if self.peers.contains_key(&to) { + return Ok(()); + } + info!( + "No active connection to {}, initiating new connection (ensure_peer)", + to + ); + self.peers.insert(to, Default::default()); Ok(()) } - pub async fn get_conn_state( - &self, - endpoint_id: EndpointId, - ) -> Result { - Ok(self + pub async fn get_conn_state(&self, endpoint_id: EndpointId) -> Result { + let peer = self .peers .get(&endpoint_id) - .cloned() - .ok_or(anyhow::anyhow!("no connection to peer"))? - .get_state() - .await) - } + .ok_or(anyhow::anyhow!("no connection to peer"))?; - pub async fn get_endpoint(&self) -> Result { - Ok(self.endpoint.clone()) + let guard = peer.conn_pool.lock().await; + for conn in guard.iter() { + if conn.is_alive().await { + return Ok(InnerConnState::Open); + } + } + Ok(InnerConnState::Closed) } pub async fn close(&mut self) -> Result<()> { - for (_, conn) in self.peers.drain() { - let _ = conn.close().await; + for (_, conn_gen) in self.peers.drain() { + let guard = conn_gen.conn_pool.lock().await; + conn_gen + .conn_counter + .store(0, std::sync::atomic::Ordering::SeqCst); + for conn in guard.iter() { + conn.drop().await; + } } Ok(()) } @@ -169,6 +490,7 @@ impl ProtocolHandler for Direct { &self, connection: iroh::endpoint::Connection, ) -> Result<(), iroh::protocol::AcceptError> { + info!("ProtocolHandler: new conn: {}", connection.remote_id()); let _ = self.handle_connection(connection).await; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index a595c20..a916b9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,23 @@ -//mod direct_connect; -//mod local_networking; mod connection; mod direct_connect; -mod local_networking; -pub mod network; -mod router; +mod tun; +mod network; +mod overlay; +mod state; +pub mod cli; -pub use connection::ConnState; + +pub use network::Network; pub use direct_connect::{Direct, DirectMessage}; -pub use local_networking::Tun; -pub use router::{IpAssignment, IpCandidate, Router, RouterIp}; +pub use tun::Tun; +pub use overlay::Overlay; +pub use connection::InnerConnState; + + +pub(crate) fn current_time() -> u64 { + chrono::Utc::now().timestamp() as u64 +} + +pub(crate) fn build_ip(base_ip: u16, suffix: u16) -> std::net::Ipv4Addr { + std::net::Ipv4Addr::from((base_ip as u32) << 16 | (suffix as u32)) +} \ No newline at end of file diff --git a/src/local_networking.rs b/src/local_networking.rs deleted file mode 100644 index d9d1731..0000000 --- a/src/local_networking.rs +++ /dev/null @@ -1,197 +0,0 @@ -use anyhow::Result; -use pnet_packet::{Packet, ip::IpNextHeaderProtocols, ipv4::Ipv4Packet}; -use serde::{Deserialize, Serialize}; -use std::{fmt::Debug, net::Ipv4Addr}; -use tracing::debug; -use tun_rs::{AsyncDevice, DeviceBuilder, Layer}; - -use actor_helper::{Action, Handle, act}; - -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Ipv4Pkg(Vec); - -impl<'a> From> for Ipv4Pkg { - fn from(value: Ipv4Packet<'a>) -> Self { - Ipv4Pkg(value.packet().to_vec()) - } -} - -impl Ipv4Pkg { - // Accept anything that can be viewed as a byte slice. - pub fn new>(buf: B) -> Result { - let v = buf.as_ref().to_vec(); - let pkg = Ipv4Pkg(v); - // validate - pkg.to_ipv4_packet()?; - Ok(pkg) - } - - // Borrowing view over the internal bytes. - pub fn to_ipv4_packet(&self) -> Result> { - Ipv4Packet::new(&self.0).ok_or_else(|| anyhow::anyhow!("Invalid IPv4 packet")) - } - - pub fn as_slice(&self) -> &[u8] { - &self.0 - } -} - -#[derive(Debug, Clone)] -pub struct Tun { - api: Handle, -} - -struct TunActor { - ip: Ipv4Addr, - dev: AsyncDevice, - rx: actor_helper::Receiver>, - to_remote_writer: tokio::sync::broadcast::Sender, - _keep_alive_to_remote_writer: tokio::sync::broadcast::Receiver, -} - -impl Debug for TunActor { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("TunActor") - .field("ip", &self.ip) - .field("dev", &"AsyncDevice") - .finish() - } -} - -impl Tun { - pub async fn new( - free_ip_ending: (u8, u8), - to_remote_writer: tokio::sync::broadcast::Sender, - ) -> Result { - let ip = Ipv4Addr::new(172, 22, free_ip_ending.0, free_ip_ending.1); - - #[cfg(target_os = "windows")] - dll_export().await?; - - let dev = DeviceBuilder::new() - .ipv4(ip, 24, None) - .layer(Layer::L3) - .mtu(1280) - .build_async()?; - - let (api, rx) = Handle::channel(); - - tokio::spawn(async move { - let mut actor = TunActor { - ip, - to_remote_writer: to_remote_writer.clone(), - dev, - rx, - _keep_alive_to_remote_writer: to_remote_writer.subscribe(), - }; - let _ = actor.run().await; - }); - - Ok(Self { api }) - } - - pub async fn write(&self, pkg: Ipv4Pkg) -> Result<()> { - self.api.call(act!(actor => actor.write_to_tun(pkg))).await - } - - pub async fn subscribe(&self) -> Result> { - self.api.call(act!(actor => actor.subscribe())).await - } - - pub async fn close(&self) -> Result<()> { - self.api - .call(act!(actor => - actor.close() - )) - .await - } -} - -impl TunActor { - async fn run(&mut self) -> Result<()> { - let mut dev_buf = [0u8; 1024 * 128]; - loop { - tokio::select! { - - // Handle API actions - Ok(action) = self.rx.recv_async() => { - action(self).await; - } - Ok(len) = self.dev.recv(&mut dev_buf) => { - if let Ok(ip_pkg) = Ipv4Pkg::new(&dev_buf[..len]) { - let ip_pkg = ip_pkg.to_ipv4_packet().expect("this should have been validated during 'Ipv4Pkg::new' creation"); - if matches!( - ip_pkg.get_next_level_protocol(), - IpNextHeaderProtocols::Tcp | IpNextHeaderProtocols::Udp | IpNextHeaderProtocols::Icmp - ) { - // if packet is ment for local ip: write - // if ment for ip of remote node: vpn -> write - - debug!( - "{} {} {}", - ip_pkg.get_next_level_protocol(), - ip_pkg.get_source(), - ip_pkg.get_destination(), - ); - - if ip_pkg.get_destination() == self.ip { - debug!("injected in local tun"); - let _ = self.dev.send(ip_pkg.packet()).await; - } else { - let _res = self.to_remote_writer.send(ip_pkg.into()); - - debug!("forwarding_to_remote_writer {}", _res.is_ok()); - } - - } - } - } - _ = tokio::signal::ctrl_c() => { - break - } - } - } - Ok(()) - } - - // validated write - pub async fn write_to_tun(&self, pkg: Ipv4Pkg) -> Result<()> { - let data = pkg.to_ipv4_packet()?.packet().to_vec(); - let _l = self.dev.send(&data).await?; - debug!("tun_send-size: {} {}", data.len(), _l); - Ok(()) - } - - pub async fn subscribe(&mut self) -> Result> { - Ok(self.to_remote_writer.subscribe()) - } - - pub async fn close(&mut self) -> Result<()> { - let _ = &self.dev; - Ok(()) - } -} - -#[cfg(all(windows, target_arch = "x86"))] -const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/x86/wintun.dll"); -#[cfg(all(windows, target_arch = "x86_64"))] -const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/amd64/wintun.dll"); -#[cfg(all(windows, target_arch = "aarch64"))] -const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/arm64/wintun.dll"); -#[cfg(all(windows, target_arch = "arm"))] -const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/arm/wintun.dll"); - -#[cfg(target_os = "windows")] -async fn dll_export() -> anyhow::Result<()> { - let working_dir = std::env::current_exe()? - .parent() - .ok_or(anyhow::anyhow!("Failed to get parent directory"))? - .to_path_buf(); - let dll_path = working_dir.join("wintun.dll"); - if tokio::fs::try_exists(dll_path.clone()).await? { - return Ok(()); - } else { - tokio::fs::write(&dll_path, WINTUN_DLL_EMBEDDED).await?; - } - Ok(()) -} diff --git a/src/network.rs b/src/network.rs index 5243ce0..4cc711e 100644 --- a/src/network.rs +++ b/src/network.rs @@ -1,14 +1,84 @@ -use std::time::Duration; - -use actor_helper::{Action, Actor, Handle, act, act_ok}; +use std::{ + collections::HashMap, + io::BufWriter, + net::Ipv4Addr, + path::PathBuf, + str::FromStr, + sync::Arc, + time::{Duration, Instant}, +}; + +use actor_helper::{Action, Handle, Receiver, act, act_ok}; use anyhow::Result; -use iroh::{Endpoint, EndpointId, SecretKey}; -use iroh_blobs::store::mem::MemStore; -use iroh_docs::protocol::Docs; +use ipnet::Ipv4Net; +use iroh::{ + Endpoint, EndpointId, RelayMap, RelayUrl, SecretKey, + endpoint::{IdleTimeout, QlogConfig, QlogFactory, QuicTransportConfig, VarInt}, +}; +use iroh_auth::Authenticator; + use iroh_gossip::{net::Gossip, proto::HyparviewConfig}; -use tracing::warn; +use noq_proto::ConnectionId; +use sha2::Digest; +use tracing::{debug, error, info, trace, warn}; + +use crate::{ + Direct, DirectMessage, Overlay, Tun, + state::{Config, NodeState}, + tun::{Ipv4Pkg, TunEvent}, +}; + +#[derive(Debug)] +struct LoggingQlogFactory { + dir: PathBuf, + prefix: String, +} + +impl LoggingQlogFactory { + fn new(dir: PathBuf, prefix: impl Into) -> Self { + Self { + dir, + prefix: prefix.into(), + } + } +} -use crate::{Direct, DirectMessage, Router, Tun, local_networking::Ipv4Pkg, router::RouterIp}; +impl QlogFactory for LoggingQlogFactory { + fn for_connection( + &self, + side: iroh::endpoint::Side, + remote: std::net::SocketAddr, + initial_dst_cid: ConnectionId, + now: Instant, + ) -> Option { + let timestamp = std::time::SystemTime::now() + .checked_sub(Instant::now().duration_since(now))? + .duration_since(std::time::SystemTime::UNIX_EPOCH) + .ok()? + .as_millis(); + let side_text = format!("{side:?}").to_lowercase(); + let prefix = if self.prefix.is_empty() { + String::new() + } else { + format!("{}-", self.prefix) + }; + let file_name = format!("{prefix}{timestamp}-{initial_dst_cid}-{side_text}.qlog"); + let path = self.dir.join(file_name); + let file = std::fs::File::create(&path) + .inspect_err(|err| warn!("Failed to create qlog file at {}: {}", path.display(), err)) + .ok()?; + + info!( + "iroh-qlog-created remote_addr={} side={} initial_dst_cid={} path={}", + remote, + side_text, + initial_dst_cid, + path.display() + ); + + Some(QlogConfig::new(Box::new(BufWriter::new(file)))) + } +} #[derive(Debug, Clone)] pub struct Network { @@ -17,113 +87,212 @@ pub struct Network { #[derive(Debug)] struct NetworkActor { - rx: actor_helper::Receiver>, - - router: Router, + overlay: Overlay, direct: Direct, + _auth: Authenticator, - _router: iroh::protocol::Router, - _endpoint: iroh::endpoint::Endpoint, + _iroh_router: iroh::protocol::Router, + iroh_endpoint: iroh::endpoint::Endpoint, tun: Option, + tun_config_rx: tokio::sync::mpsc::Receiver, + + tun_ip_debug: Option, + + tun_to_remote_tx: tokio::sync::mpsc::Sender, + tun_to_remote_rx: tokio::sync::mpsc::Receiver, - _local_to_direct_tx: tokio::sync::broadcast::Sender, - local_to_direct_rx: tokio::sync::broadcast::Receiver, + remote_to_tun_rx: tokio::sync::mpsc::Receiver, - _direct_to_local_tx: tokio::sync::broadcast::Sender, - direct_to_local_rx: tokio::sync::broadcast::Receiver, + eid_ip_mapping_update_rx: tokio::sync::mpsc::Receiver<(EndpointId, Option)>, + + ip_cache: HashMap, } -impl Network { - pub async fn new(name: &str, password: &str) -> Result { - let secret_key = SecretKey::generate(&mut rand::rng()); +fn transport_config(log_path: Option) -> QuicTransportConfig { + let mut transport = QuicTransportConfig::builder() + .enable_segmentation_offload(false) + .max_idle_timeout(Some(IdleTimeout::from(VarInt::from_u32(10_000)))) + //.keep_alive_interval(Duration::from_millis(1_000)) + .initial_mtu(1200) + //.mtu_discovery_config(None) + .min_mtu(1200); + + if let Some(log_path) = log_path { + if !log_path.exists() + && let Err(e) = std::fs::create_dir_all(&log_path) + { + error!("Failed to create qlog directory at {:?}: {}", log_path, e); + } + transport = transport.qlog_factory(Arc::new(LoggingQlogFactory::new(log_path, "iroh-lan"))); + } + + transport.build() +} + +/* +fn rustonbsd_relay() -> RelayConfig { + let url: Url = format!("https://iroh-relay.rustonbsd.com/") + .parse() + .expect("default url"); + RelayConfig { + url: url.into(), + quic: Some(RelayQuicConfig::default()), + } +} */ - let endpoint = Endpoint::builder() +impl Network { + pub async fn new( + name: &str, + password: &str, + relay_url: Option, + config: Config, + ) -> Result { + Self::new_logs_dir(name, password, None, relay_url, config).await + } + pub async fn new_logs_dir( + name: &str, + password: &str, + log_dir: Option, + relay_url: Option, + config: Config, + ) -> Result { + let secret_key = SecretKey::generate(); + + let mut network_secret = sha2::Sha512::new(); + network_secret.update(format!("iroh-lan-network-name-{}", name)); + network_secret.update(format!("iroh-lan-network-secret-{password}")); + let network_secret: [u8; 64] = network_secret.finalize().into(); + + let auth = Authenticator::new(&network_secret); + //let relay_map = RelayMap::from_iter([rustonbsd_relay()]); + //relay_map.extend(&iroh::defaults::prod::default_relay_map()); + + netwatch::add_ipnet_exclusion(ipnet::IpNet::V4(Ipv4Net::new( + Ipv4Addr::from_octets([ + ((config.net_prefix & 0xFF00) >> 8) as u8, + (config.net_prefix & 0x00FF) as u8, + 0, + 0, + ]), + 16, + )?)); + + let mut endpoint_builder = Endpoint::builder(iroh::endpoint::presets::N0) + //.relay_mode(iroh::RelayMode::Custom(relay_map)) + .hooks(auth.clone()) .secret_key(secret_key.clone()) - .bind() - .await?; + .transport_config(transport_config(log_dir)); + + if let Some(relay_url) = relay_url { + endpoint_builder = endpoint_builder.relay_mode(iroh::RelayMode::Custom( + RelayMap::from(RelayUrl::from_str(&relay_url)?), + )); + info!("Using custom relay URL: {}", relay_url); + } - let gossip_config = HyparviewConfig { - neighbor_request_timeout: Duration::from_millis(2000), + let endpoint = endpoint_builder.bind().await?; + + auth.set_endpoint(&endpoint).await; + endpoint.online().await; + let socks = endpoint.bound_sockets(); + info!( + "Endpoint online with ID: {}. Bound sockets: {:?}", + endpoint.id(), + socks + ); + + let gossip_hyparview_config = HyparviewConfig { + //neighbor_request_timeout: Duration::from_millis(3000), + //shuffle_interval: Duration::from_secs(120), + ..Default::default() + }; + + let gossip_plumtree_config = iroh_gossip::proto::PlumtreeConfig { + message_cache_retention: Duration::from_secs(300), + cache_evict_interval: Duration::from_secs(60), + message_id_retention: Duration::from_secs(300), ..Default::default() }; let gossip = Gossip::builder() - .membership_config(gossip_config) + .max_message_size(64 * 1024) + .membership_config(gossip_hyparview_config) + .broadcast_config(gossip_plumtree_config) .spawn(endpoint.clone()); - let blobs = MemStore::default(); - let docs = Docs::memory() - .spawn(endpoint.clone(), (*blobs).clone(), gossip.clone()) - .await?; + // Pipes + let (remote_to_tun_tx, remote_to_tun_rx) = tokio::sync::mpsc::channel(1024 * 16); + let (tun_to_remote_tx, tun_to_remote_rx) = tokio::sync::mpsc::channel(1024 * 16); + let (remote_frame_tx, remote_frame_rx) = tokio::sync::mpsc::channel(1024); + let (transmit_frame_tx, transmit_frame_rx) = tokio::sync::mpsc::channel(1024); + let (tun_config_tx, tun_config_rx) = tokio::sync::mpsc::channel(1024); + let (eid_ip_mapping_update_tx, eid_ip_mapping_update_rx) = tokio::sync::mpsc::channel(1024); - let (direct_connect_tx, direct_connect_rx) = tokio::sync::broadcast::channel(1024 * 16); - let direct = Direct::new(endpoint.clone(), direct_connect_tx.clone()); + let direct = Direct::new(endpoint.clone(), remote_to_tun_tx, transmit_frame_rx, remote_frame_tx); - let _router = iroh::protocol::Router::builder(endpoint.clone()) - .accept(iroh_gossip::ALPN, gossip.clone()) + let _iroh_router = iroh::protocol::Router::builder(endpoint.clone()) + .accept(iroh_auth::ALPN, auth.clone()) .accept(crate::Direct::ALPN, direct.clone()) - .accept(iroh_docs::ALPN, docs.clone()) - .accept( - iroh_blobs::ALPN, - iroh_blobs::BlobsProtocol::new(&blobs, None), - ) + .accept(iroh_gossip::ALPN, gossip.clone()) .spawn(); - let router = crate::Router::builder() - .entry_name(name) - .password(password) - .secret_key(secret_key) - .endpoint(endpoint.clone()) - .gossip(gossip) - .docs(docs) - .blobs(blobs) - .build() - .await?; - - let (api, rx) = Handle::channel(); - tokio::spawn(async move { - let (to_remote_writer, to_remote_reader) = tokio::sync::broadcast::channel(1024 * 16); - let mut actor = NetworkActor { - rx, - router, + let overlay = crate::Overlay::builder( + endpoint.clone(), + gossip, + remote_frame_rx, + transmit_frame_tx, + tun_config_tx, + eid_ip_mapping_update_tx, + ) + .network_name(name) + .password(password) + .build() + .await?; + + let (api, _) = Handle::spawn_with( + NetworkActor { + overlay, direct, + _auth: auth, - _router, - _endpoint: endpoint, + _iroh_router, + iroh_endpoint: endpoint, tun: None, - _local_to_direct_tx: to_remote_writer, - local_to_direct_rx: to_remote_reader, - _direct_to_local_tx: direct_connect_tx, - direct_to_local_rx: direct_connect_rx, - }; - let _ = actor.run().await; - }); + tun_config_rx, - Ok(Self { api }) - } + tun_ip_debug: None, + tun_to_remote_tx, + tun_to_remote_rx, + remote_to_tun_rx, - pub async fn get_router_state(&self) -> Result { - self.api - .call(act!(actor => actor.router.get_ip_state())) - .await + eid_ip_mapping_update_rx, + + ip_cache: HashMap::new(), + }, + |mut actor, rx| async move { actor.run(rx).await }, + ); + + Ok(Self { api }) } - pub async fn get_router_handle(&self) -> Result { + pub async fn get_router_handle(&self) -> Result { self.api - .call(act_ok!(actor => async move { actor.router.clone() })) + .call(act_ok!(actor => async move { actor.overlay.clone() })) .await } pub async fn get_node_id(&self) -> Result { self.api - .call(act!(actor => actor.router.get_node_id())) + .call(act!(actor => actor.overlay.get_endpoint_id())) .await } pub async fn get_peers(&self) -> Result)>> { - self.api.call(act!(actor => actor.router.get_peers())).await + self.api + .call(act!(actor => actor.overlay.get_peers())) + .await } pub async fn get_direct_handle(&self) -> Result { @@ -132,12 +301,20 @@ impl Network { .await } + pub async fn get_own_state(&self) -> Result { + self.api + .call(act!(actor => async move { + actor.overlay.get_own_state().await + })) + .await + } + pub async fn close(&self) -> Result<()> { warn!("Closing network TODO!"); self.api .call(act_ok!(actor => async move { - let _ = actor._router.shutdown().await; + let _ = actor._iroh_router.shutdown().await; tokio::time::sleep(Duration::from_millis(500)).await; //actor._endpoint.close().await; })) @@ -145,50 +322,105 @@ impl Network { } } -impl Actor for NetworkActor { - async fn run(&mut self) -> Result<()> { - let mut ip_tick = tokio::time::interval(Duration::from_millis(500)); - ip_tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); +impl NetworkActor { + async fn run(&mut self, rx: Receiver>) -> Result<()> { + debug!("NetworkActor started"); loop { tokio::select! { - Ok(action) = self.rx.recv_async() => { + Ok(action) = rx.recv_async() => { + trace!("NetworkActor action received"); action(self).await; } - _ = tokio::signal::ctrl_c() => { - break - } - // init tun after ip is assigned - _ = ip_tick.tick(), if self.tun.is_none() && matches!(self.router.get_ip_state().await, Ok(RouterIp::AssignedIp(_))) => { - if let Ok(RouterIp::AssignedIp(ip)) = self.router.get_ip_state().await { - if let Ok(tun) = Tun::new((ip.octets()[2],ip.octets()[3]), self._local_to_direct_tx.clone()).await { - self.tun = Some(tun); + Some(tun_event) = self.tun_config_rx.recv() => { + match tun_event { + TunEvent::Configure { ip } => { + println!("My IP is {}", ip); + self.create_tun(ip).await; } + TunEvent::Reconfigure { to, .. } => { + if let Some(tun) = self.tun.take() + && let Err(err) = tun.close().await { + warn!(?err, "failed to close TUN for reconfigure"); + } + self.create_tun(to).await; + }, + TunEvent::Teardown => { + if let Some(tun) = self.tun.take() + && let Err(err) = tun.close().await { + warn!(?err, "failed to close TUN for reconfigure"); + } + } + } + } + + Some((peer, ip_event)) = self.eid_ip_mapping_update_rx.recv() => { + info!(%peer, "peer ip update"); + if peer == self.iroh_endpoint.id() { + continue; } + if let Some(ip) = ip_event { + self.ip_cache.insert(ip, peer); + } + self.direct.ensure_connection(peer).await?; } - Ok(tun_recv) = self.local_to_direct_rx.recv(), if self.tun.is_some() => { - // Tun initialized, route packets - if let Ok(ip_pkg) = tun_recv.to_ipv4_packet() { + Some(tun_to_remote) = self.tun_to_remote_rx.recv(), if self.tun.is_some() => { + if let Ok(ip_pkg) = tun_to_remote.to_ipv4_packet() { let dest = ip_pkg.get_destination(); - if let Ok(to) = self.router.get_endpoint_id_from_ip(dest).await { - let _ = self.direct.route_packet(to, DirectMessage::IpPacket(tun_recv)).await; + if let Ok(Some(to)) = match self.ip_cache.get(&dest) { + Some(peer) => Ok(Some(*peer)), + None => self.overlay.get_endpoint_id_from_ip(dest).await, } + && to != self.iroh_endpoint.id() { + trace!(%to, "routing packet from TUN"); + if let Err(err) = self.direct.route_packet(to, DirectMessage::IpPacket(tun_to_remote)).await { + warn!(%to, ?err, "failed to route packet"); + } + } + } } - Ok(direct_msg) = self.direct_to_local_rx.recv(), if self.tun.is_some() => { - // Route remote packet to tun if our ip - if let Some(tun) = &self.tun { - if let DirectMessage::IpPacket(ip_pkg) = direct_msg { - let _ = tun.write(ip_pkg).await; + Some(remote_to_tun) = self.remote_to_tun_rx.recv(), if self.tun.is_some() => { + if let Some(tun) = &self.tun && let DirectMessage::IpPacket(ip_pkg) = remote_to_tun { + trace!("Routing remote packet to TUN"); + if let Err(err) = tun.write(ip_pkg).await { + warn!(?err,"Failed to write to TUN"); } } } + else => break, } } + warn!("NetworkActor stopped"); Ok(()) } -} + + async fn create_tun(&mut self, tun_ip: Ipv4Addr) { + match tokio::time::timeout( + Duration::from_secs(10), + Tun::new( + tun_ip, + self.tun_to_remote_tx.clone(), + self.iroh_endpoint.clone(), + ), + ) + .await + { + Ok(Ok(tun)) => { + info!("TUN initialized successfully"); + self.tun_ip_debug = Some(tun_ip); + self.tun = Some(tun); + } + Ok(Err(err)) => { + error!(?err, "failed to initialize TUN"); + } + Err(timeout) => { + error!(?timeout, "timeout waiting for TUN to initialize"); + } + } + } +} \ No newline at end of file diff --git a/src/overlay.rs b/src/overlay.rs new file mode 100644 index 0000000..153db1a --- /dev/null +++ b/src/overlay.rs @@ -0,0 +1,327 @@ +use std::{net::Ipv4Addr, time::Duration}; + +use futures::StreamExt; +use iroh_gossip::{ + api::{Event as GossipEvent, GossipReceiver, GossipSender}, + net::Gossip, +}; +use iroh_topic_tracker::{TopicDiscoveryConfig, TopicDiscoveryExt, TopicDiscoveryHandle}; +use tokio::sync::mpsc::{Receiver, Sender}; +use tracing::{debug, info, warn}; + +use anyhow::Result; +use iroh::{Endpoint, EndpointId}; + +use actor_helper::{Action, Handle, Receiver as ActorReceiver, act_ok}; + +use crate::{ + build_ip, current_time, + state::{Config, MeshEvent, NodeState, State, TunDirective}, + tun::TunEvent, +}; + +#[derive(Debug)] +pub struct Builder { + endpoint: Endpoint, + gossip: Gossip, + remote_frame_rx: Option)>>, + transmit_frame_tx: Sender<(EndpointId, Vec)>, + tun_config_tx: Sender, + eid_ip_mapping_update_tx: Sender<(EndpointId, Option)>, + network_name: String, + password: String, + state_config: Config, +} + +impl Builder { + pub fn network_name(mut self, network_name: &str) -> Self { + self.network_name = network_name.to_string(); + self + } + + pub fn password(mut self, password: &str) -> Self { + self.password = password.to_string(); + self + } + + pub fn config(mut self, config: Config) -> Self { + self.state_config = config; + self + } + + pub async fn build(mut self) -> Result { + let topic_initials = format!("lanparty-{}", self.network_name); + let secret_initials = format!("{topic_initials}-{}-secret", self.password) + .as_bytes() + .to_vec(); + + let mut topic_hasher = blake3::Hasher::new(); + topic_hasher.update(b"iroh-lan-topic"); + topic_hasher.update(&secret_initials); + let topic_hash = *topic_hasher.finalize().as_bytes(); + + let topic_discovery_config = TopicDiscoveryConfig::builder(self.endpoint.clone()) + .connection_timeout(Duration::from_secs(30)) + .announce_interval(Duration::from_secs(15 * 60)) + .first_connected_duration(Some(Duration::from_secs(60))) + .discovery_interval_first_connected(Duration::from_secs(4)) + .dht_retries(None) + .build(); + let (gossip_sender, gossip_receiver, topic_handle) = loop { + if let Ok((gossip_sender, gossip_receiver, topic_handle)) = self + .gossip + .subscribe_with_discovery_joined( + topic_hash.to_vec(), + vec![], + topic_discovery_config.clone(), + ) + .await + { + break (gossip_sender, gossip_receiver, Some(topic_handle)); + } else { + warn!("Failed to join topic; retrying in 2 second"); + tokio::time::sleep(Duration::from_secs(2)).await; + } + }; + + info!("Joined topic with hash: {:x?}", topic_hash); + + let (api, _) = Handle::spawn_with( + OverlayActor { + _topic: topic_handle, + state: State::new(self.endpoint.secret_key(), self.state_config.clone(), None), + + received_frame_rx: self + .remote_frame_rx + .take() + .ok_or_else(|| anyhow::anyhow!("remote frame rx not set"))?, + + transmit_frame_tx: self.transmit_frame_tx.to_owned(), + + tun_config_tx: self.tun_config_tx.to_owned(), + + eid_ip_mapping_update_tx: self.eid_ip_mapping_update_tx.to_owned(), + + _gossip_sender: gossip_sender, + gossip_receiver, + }, + |mut actor, rx| async move { actor.run(rx).await }, + ); + Ok(Overlay { api }) + } +} + +#[derive(Debug, Clone)] +pub struct Overlay { + api: Handle, +} + +#[derive(Debug)] +struct OverlayActor { + _topic: Option, + state: State, + + // channel for `DirectConnect` `Connection`'s to write their received frames to + received_frame_rx: Receiver<(EndpointId, Vec)>, + + // write frames to `DirectConnect` that will inturn write them to the specified peer `Connection` + transmit_frame_tx: Sender<(EndpointId, Vec)>, + // [!] TODO wire this into direct and thorugh to connection + tun_config_tx: Sender, + + eid_ip_mapping_update_tx: Sender<(EndpointId, Option)>, + + _gossip_sender: GossipSender, + gossip_receiver: GossipReceiver, +} + +impl Overlay { + pub fn builder( + endpoint: Endpoint, + gossip: Gossip, + remote_frame_rx: Receiver<(EndpointId, Vec)>, + transmit_frame_tx: Sender<(EndpointId, Vec)>, + tun_config_tx: Sender, + eid_ip_mapping_update_tx: Sender<(EndpointId, Option)>, + ) -> Builder { + Builder { + endpoint, + gossip, + remote_frame_rx: Some(remote_frame_rx), + transmit_frame_tx, + tun_config_tx, + eid_ip_mapping_update_tx, + network_name: String::default(), + password: String::default(), + state_config: Config::default(), + } + } + + pub async fn get_endpoint_id(&self) -> Result { + self.api + .call(act_ok!(actor => async move { + *actor.state.endpoint_id() + })) + .await + } + + pub async fn get_ip_from_endpoint_id( + &self, + endpoint_id: EndpointId, + ) -> Result> { + self.api + .call(act_ok!(actor => async move { + actor.state.get_node_states() + .iter() + .find(|state| state.endpoint_id == endpoint_id) + .and_then(|state| state.ip_claim.to_ipv4(actor.state.config().net_prefix)) + })) + .await + } + + pub async fn get_endpoint_id_from_ip(&self, ip: Ipv4Addr) -> Result> { + self.api + .call(act_ok!(actor => async move { + actor.state.get_node_states() + .iter() + .filter_map(|state| { + if state.ip_claim.to_ipv4(actor.state.config().net_prefix) == Some(ip) { + Some(state.endpoint_id) + } else { + None + } + }).next() + })) + .await + } + + pub async fn get_peers(&self) -> Result)>> { + self.api + .call(act_ok!(actor => async move { + actor.state.get_node_states() + .iter() + .map(|state| (state.endpoint_id, state.ip_claim.to_ipv4(actor.state.config().net_prefix))) + .collect::>() + })) + .await + } + + pub async fn get_own_state(&self) -> Result { + self.api + .call(act_ok!(actor => async move { actor.state.own().clone() })) + .await + } +} + +impl OverlayActor { + async fn run(&mut self, rx: ActorReceiver>) -> Result<()> { + let mut ticker = tokio::time::interval(self.state.config().tick_interval); + ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + debug!( + "RouterActor started. EndpointId: {}", + self.state.endpoint_id() + ); + loop { + tokio::select! { + Ok(action) = rx.recv_async() => { + action(self).await; + } + _ = ticker.tick() => { + self.state.tick(current_time()); + let _ =self.process_event().await; + }, + Some((from, bytes)) = self.received_frame_rx.recv() => { + debug!(%from, "received frame"); + if let Err(err) = self.state.on_frame(from, &bytes, current_time()) { + tracing::warn!(%from, ?err, "dropping bad frame"); + } + let _ = self.process_event().await; + }, + gossip_event = self.gossip_receiver.next() => { + match gossip_event { + Some(Ok(GossipEvent::NeighborUp(endpoint_id))) => { + self.state.on_peer_connected(endpoint_id, current_time()); + let _ = self.process_event().await; + let _ = self.eid_ip_mapping_update_tx.send((endpoint_id, None)).await; + } + Some(Ok(GossipEvent::NeighborDown(endpoint_id))) => { + self.state.on_peer_disconnected(endpoint_id); + let _ =self.process_event().await; + } + Some(Ok(GossipEvent::Received(_))) => { + // we use keep alive packets for faster and more reliable state exchange + } + Some(Ok(_)) => {} + Some(Err(err)) => { + warn!(?err, "failed to read gossip event"); + } + None => { + warn!("Gossip receiver closed"); + break; + } + }; + } + else => break, + } + } + warn!("OverlayActor stopped."); + Ok(()) + } + + async fn process_event(&mut self) -> Result<()> { + for (to, frame) in self.state.drain_outbound() { + if frame.is_empty() { + println!("Process_Event: Sending empty frame"); + } + if let Err(err) = self.transmit_frame_tx.send((to, frame)).await { + warn!(%to, ?err, "failed to write frame"); + } + } + + for event in self.state.drain_events() { + match event { + MeshEvent::Tun(TunDirective::Configure { ip }) => { + self.tun_config_tx + .send(TunEvent::Configure { + ip: build_ip(self.state.config().net_prefix, ip), + }) + .await?; + } + MeshEvent::Tun(TunDirective::Reconfigure { from, to }) => { + tracing::info!(?from, ?to, "renumbering"); + self.tun_config_tx + .send(TunEvent::Reconfigure { + from: build_ip(self.state.config().net_prefix, from), + to: build_ip(self.state.config().net_prefix, to), + }) + .await?; + } + MeshEvent::Tun(TunDirective::Teardown { .. }) => { + self.tun_config_tx.send(TunEvent::Teardown).await?; + } + MeshEvent::PeerChanged { peer, state } => { + // update ip mapping + let ip_update = if let Some(ip) = state.ip_claim.ip() { + Some(build_ip(self.state.config().net_prefix, ip)) + } else { + None + }; + self.eid_ip_mapping_update_tx + .send((peer, ip_update)) + .await?; + + // update allowed ports + //todo!("update allowed ports"); + } + MeshEvent::PeerDisconnected { peer } => { + info!(%peer, "peer disconnected (MeshEvent::PeerDisconnected)"); + } + MeshEvent::ClaimResolved { ip, winner, loser } => { + tracing::info!(?ip, %winner, %loser, "claim resolved"); + } + } + } + Ok(()) + } +} diff --git a/src/router.rs b/src/router.rs deleted file mode 100644 index 4a7384f..0000000 --- a/src/router.rs +++ /dev/null @@ -1,600 +0,0 @@ -use std::{collections::BTreeMap, net::Ipv4Addr, time::Duration}; - -use distributed_topic_tracker::{ - AutoDiscoveryGossip, GossipReceiver, GossipSender, RecordPublisher, Topic, TopicId, -}; -use ed25519_dalek::{SigningKey, VerifyingKey}; -use futures::StreamExt; -use iroh_blobs::store::mem::MemStore; -use iroh_docs::{ - AuthorId, Entry, NamespaceSecret, - api::Doc, - protocol::Docs, - store::{Query, QueryBuilder, SingleLatestPerKeyQuery}, -}; - -use anyhow::{Context, Result, bail}; -use iroh::{Endpoint, EndpointAddr, EndpointId, SecretKey}; -use iroh_gossip::net::Gossip; -use serde::{Deserialize, Serialize}; -use sha2::Digest; -use tracing::{debug, info}; - -use actor_helper::{Action, Actor, Handle, act, act_ok}; - -#[derive(Debug, Clone)] -pub struct Builder { - entry_name: String, - secret_key: SecretKey, - creator_mode: bool, - password: String, - endpoint: Option, - gossip: Option, - docs: Option, - blobs: MemStore, -} - -impl Builder { - pub fn new() -> Builder { - Builder::default() - } - - pub fn entry_name(mut self, entry_name: &str) -> Self { - self.entry_name = entry_name.to_string(); - self - } - - pub fn secret_key(mut self, secret_key: SecretKey) -> Self { - self.secret_key = secret_key; - self - } - - pub fn creator_mode(mut self) -> Self { - self.creator_mode = true; - self - } - - pub fn password(mut self, password: &str) -> Self { - self.password = password.to_string(); - self - } - - pub fn endpoint(mut self, endpoint: Endpoint) -> Self { - self.endpoint = Some(endpoint); - self - } - - pub fn gossip(mut self, gossip: Gossip) -> Self { - self.gossip = Some(gossip); - self - } - - pub fn docs(mut self, docs: Docs) -> Self { - self.docs = Some(docs); - self - } - - pub fn blobs(mut self, blobs: MemStore) -> Self { - self.blobs = blobs; - self - } - - pub async fn build(&self) -> Result { - let endpoint = if let Some(ep) = &self.endpoint { - ep.clone() - } else { - bail!("endpoint must be set"); - }; - let gossip = if let Some(g) = &self.gossip { - g.clone() - } else { - bail!("gossip must be set"); - }; - let docs = if let Some(d) = &self.docs { - d.clone() - } else { - bail!("docs must be set"); - }; - let blobs = self.blobs.clone(); - - let topic_initials = format!("lanparty-{}", self.entry_name); - let secret_initials = format!("{topic_initials}-{}-secret", self.password) - .as_bytes() - .to_vec(); - - let mut topic_hasher = sha2::Sha512::new(); - topic_hasher.update("iroh-lan-topic"); - topic_hasher.update(&secret_initials); - let topic_hash: [u8; 32] = topic_hasher.finalize()[..32].try_into()?; - - let signing_key = SigningKey::from_bytes(&self.secret_key.to_bytes()); - let record_publisher = RecordPublisher::new( - TopicId::new(z32::encode(&topic_hash)), - VerifyingKey::from_bytes(endpoint.id().as_bytes())?, - signing_key, - None, - secret_initials, - ); - let topic = if self.creator_mode { - gossip - .subscribe_and_join_with_auto_discovery_no_wait(record_publisher) - .await? - } else { - gossip - .subscribe_and_join_with_auto_discovery(record_publisher) - .await? - }; - let (gossip_sender, gossip_receiver) = topic.split().await?; - - let doc_peers = gossip_receiver - .neighbors() - .await - .iter() - .map(|pub_key| EndpointAddr::new(*pub_key)) - .collect::>(); - - debug!("[Doc peers]: {:?}", doc_peers); - - let author_id = docs.author_create().await?; - let doc = docs - .import(iroh_docs::DocTicket { - capability: iroh_docs::Capability::Write(NamespaceSecret::from_bytes(&topic_hash)), - nodes: doc_peers.clone(), - }) - .await?; - - while match doc.get_sync_peers().await { - Ok(Some(peers)) => peers.is_empty(), - Ok(None) => true, - Err(_) => true, - } { - debug!("Waiting for doc to be ready..."); - tokio::time::sleep(Duration::from_millis(100)).await; - } - - let (api, rx) = Handle::channel(); - tokio::spawn(async move { - let mut router_actor = RouterActor { - _gossip_sender: gossip_sender, - _gossip_receiver: gossip_receiver, - author_id, - _docs: docs, - doc, - endpoint_id: endpoint.id(), - _topic: Some(topic), - rx, - blobs, - my_ip: RouterIp::NoIp, - }; - router_actor.run().await - }); - - Ok(Router { api }) - } -} - -impl Default for Builder { - fn default() -> Self { - Self { - creator_mode: false, - entry_name: String::default(), - secret_key: SecretKey::generate(&mut rand::rng()), - password: String::default(), - endpoint: None, - gossip: None, - docs: None, - blobs: MemStore::new(), - } - } -} - -#[derive(Debug, Clone)] -pub struct Router { - api: Handle, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum RouterIp { - NoIp, - AquiringIp(IpCandidate, tokio::time::Instant), - AssignedIp(Ipv4Addr), -} - -#[derive(Debug)] -struct RouterActor { - pub(crate) rx: actor_helper::Receiver>, - - pub _gossip_sender: GossipSender, - pub _gossip_receiver: GossipReceiver, - - pub(crate) blobs: MemStore, - pub(crate) _docs: Docs, - pub(crate) doc: Doc, - pub(crate) author_id: AuthorId, - - pub endpoint_id: EndpointId, - pub(crate) _topic: Option, - - pub my_ip: RouterIp, -} - -impl Router { - pub fn builder() -> Builder { - Builder::new() - } - - pub async fn get_ip_state(&self) -> Result { - self.api - .call(act_ok!(actor => async move { - actor.my_ip.clone() - })) - .await - } - - pub async fn get_node_id(&self) -> Result { - self.api - .call(act_ok!(actor => async move { - actor.endpoint_id - })) - .await - } - - pub async fn get_ip_from_endpoint_id(&self, endpoint_id: EndpointId) -> Result { - self.api - .call(act!(actor => actor.get_ip_from_endpoint_id(endpoint_id))) - .await - } - - pub async fn get_endpoint_id_from_ip(&self, ip: Ipv4Addr) -> Result { - self.api - .call(act!(actor => actor.get_endpoint_id_from_ip(ip))) - .await - } - - pub async fn get_peers(&self) -> Result)>> { - self.api - .call(act!(actor => async move { - let mut map: BTreeMap> = BTreeMap::new(); - - if let Ok(assignments) = actor.read_all_ip_assignments().await { - for a in assignments { - map.insert(a.endpoint_id, Some(a.ip)); - } - } - - if let Ok(cands) = actor.read_all_ip_candidates().await { - for c in cands { - map.entry(c.endpoint_id).or_insert(None); - } - } - - map.remove(&actor.endpoint_id); - - Ok(map.into_iter().collect()) - })) - .await - } - - pub async fn close(&self) -> Result<()> { - self.api.call(act!(actor => actor.doc.close())).await - } -} - -impl Actor for RouterActor { - async fn run(&mut self) -> Result<()> { - let mut ip_tick = tokio::time::interval(Duration::from_millis(500)); - ip_tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); - - loop { - tokio::select! { - Ok(action) = self.rx.recv_async() => { - action(self).await; - } - _ = tokio::signal::ctrl_c() => { - break - } - - // advance ip state machine - _ = ip_tick.tick(), if !matches!(self.my_ip, RouterIp::AssignedIp(_)) => { - if let Ok(true) = self.advance_ip_state().await { - info!("Acquired IP: {:?}", self.my_ip); - } - } - } - } - - Ok(()) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct IpAssignment { - pub ip: Ipv4Addr, - pub endpoint_id: EndpointId, -} - -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] -pub struct IpCandidate { - pub ip: Ipv4Addr, - pub endpoint_id: EndpointId, -} - -async fn entry_to_value Deserialize<'a>>( - blobs: MemStore, - entry: &Entry, -) -> anyhow::Result { - let b = blobs.get_bytes(entry.content_hash()).await?; - postcard::from_bytes::(&b).context("failed to deserialize value") -} - -fn query(q: impl Into) -> impl Into { - QueryBuilder::::default() - .key_exact(q.into()) - .build() -} - -fn query_prefix(q: impl Into) -> impl Into { - QueryBuilder::::default() - .key_prefix(q.into()) - .build() -} - -fn key_ip_assigned(ip: Ipv4Addr) -> String { - format!("/assigned/ip/{ip}") -} - -fn key_ip_assigned_prefix() -> String { - "/assigned/ip/".to_string() -} - -fn key_ip_candidate(ip: Ipv4Addr, endpoint_id: EndpointId) -> String { - format!("/candidates/ip/{ip}/{endpoint_id}") -} - -fn key_ip_candidate_prefix() -> String { - "/candidates/ip/".to_string() -} - -fn key_prefix_ip_candidates(ip: Ipv4Addr) -> String { - format!("/candidates/ip/{ip}/") -} - -impl RouterActor { - async fn read_all_ip_assignments(&mut self) -> Result> { - let entries = self - .doc - .get_many(query_prefix(key_ip_assigned_prefix())) - .await? - .collect::>() - .await - .iter() - .filter_map(|entry| entry.as_ref().ok()) - .cloned() - .collect::>(); - - let mut assignments = Vec::new(); - for entry in entries { - if let Ok(assignment) = entry_to_value::(self.blobs.clone(), &entry).await - { - assignments.push(assignment); - } - } - - Ok(assignments) - } - - async fn read_all_ip_candidates(&mut self) -> Result> { - let entries = self - .doc - .get_many(query_prefix(key_ip_candidate_prefix())) - .await? - .collect::>() - .await - .iter() - .filter_map(|entry| entry.as_ref().ok()) - .cloned() - .collect::>(); - - let mut candidates = Vec::new(); - for entry in entries { - if let Ok(candidate) = entry_to_value::(self.blobs.clone(), &entry).await { - candidates.push(candidate); - } - } - - Ok(candidates) - } - - // Assigned IPs - async fn read_ip_assignment(&mut self, ip: Ipv4Addr) -> Result { - postcard::from_bytes::( - &self - .doc - .get_one(query(key_ip_assigned(ip))) - .await? - .context("no assignment found")? - .to_vec(), - ) - .context("failed to deserialize endpoint_id") - } - - // Candidate IPs - async fn read_ip_candidates(&mut self, ip: Ipv4Addr) -> Result> { - let entries = self - .doc - .get_many(query_prefix(key_prefix_ip_candidates(ip))) - .await? - .collect::>() - .await; - debug!( - "candidates for {ip}: {:?}", - entries - .iter() - .map(|e| e.as_ref().ok().map(|e| e.content_hash())) - .collect::>() - ); - let mut candidates = Vec::new(); - for entry in entries.into_iter().flatten() { - if let Ok(b) = self.blobs.get_bytes(entry.content_hash()).await { - if let Ok(candidate) = postcard::from_bytes::(&b) { - candidates.push(candidate); - } - } - } - - Ok(candidates) - } - - // write ip assigned - async fn write_ip_assignment(&mut self, ip: Ipv4Addr, endpoint_id: EndpointId) -> Result<()> { - if self.read_ip_assignment(ip).await.is_ok() { - anyhow::bail!("ip already assigned"); - } - - // check for multiple candidates - let mut candidates = self.read_ip_candidates(ip).await?; - if candidates.is_empty() { - bail!("no candidates for this ip"); - } - - candidates.sort_by_key(|c| { - let mut hasher = sha2::Sha256::new(); - hasher.update(c.endpoint_id.as_bytes()); - hasher.update(ip.to_string().as_bytes()); - hasher.finalize() - }); - - if candidates[0].endpoint_id != endpoint_id { - bail!("not the chosen candidate"); - } - - // We are the chosen one! - // 1. write our ip assignment - // 2. delete all candidates for this ip - let data = postcard::to_stdvec(&IpAssignment { ip, endpoint_id })?; - self.doc - .set_bytes(self.author_id, key_ip_assigned(ip), data) - .await?; - - let _ = self - .doc - .del(self.author_id, key_prefix_ip_candidates(ip)) - .await; - - Ok(()) - } - - // write ip candidate - async fn write_ip_candidate( - &mut self, - ip: Ipv4Addr, - endpoint_id: EndpointId, - ) -> Result { - // already assigned? don't write - if self.read_ip_assignment(ip).await.is_ok() { - anyhow::bail!("ip already assigned"); - } - - // read existing candidates; Ok(vec![]) when none exist - let candidates = self.read_ip_candidates(ip).await.unwrap_or_default(); - - // if someone else is already a candidate, treat as contested and skip writing - if candidates.iter().any(|c| c.endpoint_id != endpoint_id) { - anyhow::bail!("ip candidate already exists"); - } - - // idempotent for our own node_id - let candidate = IpCandidate { ip, endpoint_id }; - let data = postcard::to_stdvec(&candidate)?; - self.doc - .set_bytes(self.author_id, key_ip_candidate(ip, endpoint_id), data) - .await?; - Ok(candidate) - } - - async fn get_endpoint_id_from_ip(&mut self, ip: Ipv4Addr) -> Result { - self.read_all_ip_assignments() - .await? - .iter() - .find(|assignment| assignment.ip == ip) - .map(|a| a.endpoint_id) - .ok_or_else(|| anyhow::anyhow!("no endpoint_id found for ip")) - } - - async fn get_ip_from_endpoint_id(&mut self, endpoint_id: EndpointId) -> Result { - self.read_all_ip_assignments() - .await? - .iter() - .find(|assignment| assignment.endpoint_id == endpoint_id) - .map(|a| a.ip) - .ok_or_else(|| anyhow::anyhow!("no ip found for endpoint_id")) - } -} - -impl RouterActor { - async fn advance_ip_state(&mut self) -> Result { - match self.my_ip.clone() { - RouterIp::NoIp => { - let next_ip = self.get_next_ip().await?; - - self.my_ip = RouterIp::AquiringIp( - self.write_ip_candidate(next_ip, self.endpoint_id).await?, - tokio::time::Instant::now(), - ); - Ok(false) - } - RouterIp::AquiringIp(ip_candidate, start_time) => { - if start_time.elapsed() > Duration::from_secs(5) { - if self - .write_ip_assignment(ip_candidate.ip, ip_candidate.endpoint_id) - .await - .is_ok() - { - self.my_ip = RouterIp::AssignedIp(ip_candidate.ip); - } else { - self.my_ip = RouterIp::NoIp; - } - } - Ok(false) - } - _ => Ok(true), - } - } - - async fn get_next_ip(&mut self) -> Result { - let all_assigned = self.read_all_ip_assignments().await?; - let all_candidates = self.read_all_ip_candidates().await?; - - let all_ips = all_assigned - .iter() - .map(|assigned| assigned.ip) - .chain(all_candidates.iter().map(|candidate| candidate.ip)) - .collect::>(); - - let highest_ip = if all_ips.is_empty() { - Ipv4Addr::new(172, 22, 0, 2) - } else { - *all_ips - .iter() - .max_by_key(|&&ip| ip.octets()[2] as u16 * 256u16 + ip.octets()[3] as u16) - .expect("no ips found") - }; - - let next_ip = Ipv4Addr::new( - 172, - 22, - if highest_ip.octets()[3] == 255 { 1 } else { 0 } + highest_ip.octets()[2], - if highest_ip.octets()[3] == 255 { - 0 - } else { - highest_ip.octets()[3] + 1 - }, - ); - - // to avoid overflow and therefore duplicates we check if this ip is already contained - if all_ips.contains(&next_ip) { - bail!("no more ips available"); - } - Ok(next_ip) - } -} diff --git a/src/state.rs b/src/state.rs new file mode 100644 index 0000000..39033f8 --- /dev/null +++ b/src/state.rs @@ -0,0 +1,631 @@ +use std::{ + collections::{BTreeMap, HashMap, HashSet}, + time::Duration, +}; + +use iroh::{EndpointId, SecretKey, Signature}; +use serde::{Deserialize, Serialize}; +use tracing::info; +use std::cmp::Ordering; + +use crate::{build_ip, current_time}; + +type WallMs = u64; +type Frame = Vec; + +#[derive(Debug, thiserror::Error)] +pub enum MeshError { + #[error("codec: {0}")] + Codec(#[from] postcard::Error), + #[error("bad signature")] + BadSignature, + #[error("ip space exhausted")] + IpSpaceExhausted, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] +pub struct Version { + pub wall_ms: WallMs, + pub counter: u64, +} + +impl Version { + fn bump(self, now_ms: WallMs) -> Self { + // never go backwards, even if the clock does + if now_ms > self.wall_ms { + Version { + wall_ms: now_ms, + counter: 0, + } + } else { + Version { + wall_ms: self.wall_ms, + counter: self.counter + 1, + } + } + } +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct NodeState { + pub endpoint_id: EndpointId, + pub version: Version, + pub ip_claim: IpClaim, + pub exposed_ports: Ports, +} + +impl NodeState { + fn sign(self, sk: &SecretKey) -> Result { + let bin = postcard::to_stdvec(&self)?; + let signature = sk.sign(&bin); + Ok(SignedNodeState { + inner: self, + signature, + }) + } +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct SignedNodeState { + inner: NodeState, + signature: Signature, +} + +impl SignedNodeState { + pub fn get(&self) -> &NodeState { + &self.inner + } + + fn verify(self) -> Result { + self.inner + .endpoint_id + .verify(&postcard::to_stdvec(&self.inner)?, &self.signature) + .map_err(|_| MeshError::BadSignature)?; + Ok(self) + } +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum IpClaim { + Unclaimed, + Claimed(Claim), +} + +impl IpClaim { + pub fn claim(&self) -> Option<&Claim> { + match self { + IpClaim::Unclaimed => None, + IpClaim::Claimed(c) => Some(c), + } + } + + pub fn ip(&self) -> Option { + self.claim().map(|c| c.ip) + } + pub fn to_ipv4(&self, net_prefix: u16) -> Option { + self.ip().map(|ip| build_ip(net_prefix, ip)) + } +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +pub struct Claim { + /// host bits within the /16 + pub ip: u16, + /// which candidate index of our personal sequence this ip is + pub k: u64, + /// first claim + pub claimed_at_ms: WallMs, +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum Ports { + Any, + List(Vec), +} + +#[derive(Debug, Serialize, Deserialize)] +enum Wire { + FullSync { states: Vec }, +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum MeshEvent { + Tun(TunDirective), + PeerChanged { + peer: EndpointId, + state: NodeState, + }, + PeerDisconnected { + peer: EndpointId, + }, + ClaimResolved { + ip: u16, + winner: EndpointId, + loser: EndpointId, + }, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum TunDirective { + Configure { + ip: u16, + }, + Reconfigure { + from: u16, + to: u16, + }, + /// We lost our claim and have no valid ip yet + Teardown { + from: u16, + }, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum TunState { + Down, + Up { ip: u16 }, +} + +#[derive(Debug, Clone)] +pub struct Config { + pub tick_interval: Duration, + /// Base ip prefix for the mesh network (default: 172.30 => 172u16 << 8 | 30u16 ) + pub net_prefix: u16, + /// Time until we consider a node disconnected + pub disconnect_timeout: Duration, + /// Time without change until we expect to have a settled view of our peers + pub settle_ticks: u64, + /// During ip conflict we consider two nodes timestamps identical when they are within this range + pub simultaneous_range: Duration, + /// Min peer num before we have a minimum viable network (wait to bring up tun until we have enough peers) + pub min_viable_network: usize, +} + +impl Default for Config { + fn default() -> Self { + Self { + tick_interval: Duration::from_millis(500), + net_prefix: 172u16 << 8 | 30u16, + disconnect_timeout: Duration::from_secs(60), + settle_ticks: 20, + simultaneous_range: Duration::from_secs(30), + min_viable_network: 2, + } + } +} + +#[derive(Debug, Clone, Copy)] +struct PeerMeta { + /// TODO: wire into DirectConnect + connected: bool, + last_fresh_ms: WallMs, +} + +#[derive(Debug)] +pub struct State { + eid: EndpointId, + signing_key: SecretKey, + config: Config, + + /// CRDT: per-author LWW register keyed by endpoint id + states: BTreeMap, + peers: HashMap, + + tun: TunState, + /// Ticks since the last view change (new peer / claim change) + quiet_ticks: u64, + + outbound: Vec<(EndpointId, Frame)>, + events: Vec, +} + +/// Public: API +impl State { + pub fn new(secret_key: &SecretKey, config: Config, now_ms: Option) -> Self { + let mut mesh = Self { + eid: secret_key.public(), + signing_key: secret_key.clone(), + config, + states: BTreeMap::new(), + peers: HashMap::new(), + tun: TunState::Down, + quiet_ticks: 0, + outbound: Vec::new(), + events: Vec::new(), + }; + // start unclaimed, we don't pick an ip until we've seen the network. + mesh.write_own(now_ms.unwrap_or_else(current_time), |state| { + state.ip_claim = IpClaim::Unclaimed; + state.exposed_ports = Ports::Any; + }); + mesh + } + + /// for later if we want to add persistence + #[allow(dead_code)] + pub fn resume( + secret_key: &SecretKey, + config: Config, + persisted: PersistedState, + now_ms: WallMs, + ) -> Self { + let mut mesh = Self::new(secret_key, config, Some(now_ms)); + mesh.write_own(now_ms, |state| { + state.ip_claim = IpClaim::Claimed(persisted.claim); + state.exposed_ports = persisted.exposed_ports; + }); + mesh + } + + pub fn endpoint_id(&self) -> &EndpointId { + &self.eid + } + + pub fn own(&self) -> &NodeState { + self.states + .get(&self.eid) + .expect("own state always present") + .get() + } + + pub fn get_node_states(&self) -> Vec<&NodeState> { + self.states.values().map(|signed| &signed.inner).collect() + } + + pub fn config(&self) -> &Config { + &self.config + } + + pub fn tick(&mut self, now_ms: WallMs) { + self.expire_departed(now_ms); + + // bump tick + self.write_own(now_ms, |_| {}); + + self.quiet_ticks = self.quiet_ticks.saturating_add(1); + self.maybe_claim_ip(now_ms); + self.send_sync_to_all(); + } + + #[allow(dead_code)] + pub fn set_exposed_ports(&mut self, ports: Ports, now_ms: WallMs) { + if self.own().exposed_ports == ports { + return; + } + self.write_own(now_ms, |state| state.exposed_ports = ports); + self.send_sync_to_all(); + } + + pub fn on_frame( + &mut self, + from: EndpointId, + bytes: &[u8], + now_ms: WallMs, + ) -> Result<(), MeshError> { + let Wire::FullSync { states } = postcard::from_bytes(bytes)?; + let mut changed = false; + for signed in states { + changed |= self.merge_one(signed, now_ms)?; + } + if let Some(meta) = self.peers.get_mut(&from) { + meta.last_fresh_ms = now_ms; + } + if changed { + info!(%from, "received frame"); + self.resolve_conflicts(now_ms); + self.maybe_claim_ip(now_ms); + } + Ok(()) + } + + pub fn on_peer_connected(&mut self, eid: EndpointId, now_ms: WallMs) { + let meta = self.peers.entry(eid).or_insert(PeerMeta { + connected: false, + last_fresh_ms: now_ms, + }); + meta.last_fresh_ms = now_ms; + + if !std::mem::replace(&mut meta.connected, true) { + self.reset_quiet_ticks(); + } + self.send_sync_to(eid); + } + + pub fn on_peer_disconnected(&mut self, eid: EndpointId) { + if let Some(meta) = self.peers.get_mut(&eid) { + meta.connected = false; + } + } +} + +/// Internals: general +impl State { + #[must_use] + pub fn drain_outbound(&mut self) -> Vec<(EndpointId, Frame)> { + std::mem::take(&mut self.outbound) + } + + #[must_use] + pub fn drain_events(&mut self) -> Vec { + std::mem::take(&mut self.events) + } + + fn write_own(&mut self, now_ms: WallMs, f: impl FnOnce(&mut NodeState)) { + let mut state = match self.states.get(&self.eid) { + Some(s) => s.get().clone(), + None => NodeState { + endpoint_id: self.eid, + version: Version { + wall_ms: now_ms, + counter: 0, + }, + ip_claim: IpClaim::Unclaimed, + exposed_ports: Ports::Any, + }, + }; + f(&mut state); + state.version = state.version.bump(now_ms); + let signed = state.sign(&self.signing_key).expect("sign own state"); + self.states.insert(self.eid, signed); + } + + fn expire_departed(&mut self, now_ms: WallMs) { + let timeout = self.config.disconnect_timeout.as_millis() as u64; + let gone: Vec = self + .peers + .iter() + .filter(|(eid, peer_meta)| { + **eid != self.eid + && !peer_meta.connected + && now_ms.saturating_sub(peer_meta.last_fresh_ms) >= timeout + }) + .map(|(&eid, _)| eid) + .collect(); + for eid in gone { + self.peers.remove(&eid); + self.states.remove(&eid); + self.events.push(MeshEvent::PeerDisconnected { peer: eid }); + self.reset_quiet_ticks(); + } + } + + fn reset_quiet_ticks(&mut self) { + self.quiet_ticks = 0; + } + + fn maybe_claim_ip(&mut self, now_ms: WallMs) { + if self.own().ip_claim.claim().is_some() { + self.sync_tun(); + return; + } + let live_peers = self.live_peer_count(now_ms); + let ready = live_peers >= self.config.min_viable_network + && self.quiet_ticks >= self.config.settle_ticks; + if !ready { + return; + } + let _ = self.take_ip(0, now_ms); + } + + fn live_peer_count(&self, now_ms: WallMs) -> usize { + let timeout = self.config.disconnect_timeout.as_millis() as u64; + self.peers + .iter() + .filter(|(id, m)| { + **id != self.eid + && (m.connected || now_ms.saturating_sub(m.last_fresh_ms) < timeout) + }) + .count() + } + + /// LWW merge for one author, returns true if view changed + fn merge_one(&mut self, signed: SignedNodeState, now_ms: WallMs) -> Result { + let signed = signed.verify()?; + + let author = signed.get().endpoint_id; + if author == self.eid { + return Ok(false); + } + + // if same or stale version, no change + let incoming_version = signed.get().version; + let old = self.states.get(&author).map(|s| s.get().clone()); + if let Some(old) = &old + && old.version >= incoming_version + { + return Ok(false); + } + + let semantic_change = match &old { + Some(prev) => { + prev.ip_claim != signed.get().ip_claim + || prev.exposed_ports != signed.get().exposed_ports + } + None => true, + }; + + self.states.insert(author, signed.clone()); + + self.peers + .entry(author) + .or_insert(PeerMeta { + connected: false, + last_fresh_ms: now_ms, + }) + .last_fresh_ms = now_ms; + + if old.is_none() + || old.as_ref().map(|p| p.ip_claim.clone()) != Some(signed.get().ip_claim.clone()) + { + self.reset_quiet_ticks(); + } + if semantic_change { + self.events.push(MeshEvent::PeerChanged { + peer: author, + state: signed.get().clone(), + }); + } + Ok(semantic_change) + } + + fn resolve_conflicts(&mut self, now_ms: WallMs) { + let mut by_ip: HashMap> = HashMap::new(); + for (eid, signed_state) in &self.states { + if let Some(claim) = signed_state.get().ip_claim.claim() { + by_ip.entry(claim.ip).or_default().push((*eid, *claim)); + } + } + + let mut i_lost: Option = None; + for (ip, mut claimants) in by_ip { + if claimants.len() < 2 { + continue; + } + claimants.sort_by(|a, b| self.claim_priority((&a.0, &a.1), (&b.0, &b.1))); + let winner = claimants.last().copied().expect("non-empty"); + for (loser_id, loser_claim) in claimants.iter().take(claimants.len() - 1) { + self.events.push(MeshEvent::ClaimResolved { + ip, + winner: winner.0, + loser: *loser_id, + }); + if *loser_id == self.eid { + i_lost = Some(loser_claim.k.saturating_add(1)); + } else { + // drop the losers claim locally they'll re-announce. + // this should be fine since we only update peers with newer versions + // so stale duplicates should just be ignored + if let Some(state) = self.states.get_mut(loser_id) { + state.inner.ip_claim = IpClaim::Unclaimed; + } + } + } + } + + if let Some(next_k) = i_lost { + let _ = self.take_ip(next_k, now_ms); + } + } + + /// Total order over two claims for the same IP. `std::cmp::Ordering::Greater` wins. + /// + /// 1. seniority (older claimed_at wins): protects long-running nodes + /// 2. lower k wins + /// 3. higher endpoint id: deterministic tiebreaker + fn claim_priority( + &self, + a: (&EndpointId, &Claim), + b: (&EndpointId, &Claim), + ) -> std::cmp::Ordering { + let (a_eid, a_claim) = a; + let (b_eid, b_claim) = b; + let delta = a_claim.claimed_at_ms.abs_diff(b_claim.claimed_at_ms); + if delta > self.config.simultaneous_range.as_millis() as u64 { + // older timestamps are smaller and have priority + // we flip comparison to make the smallest timestamp the winner + return b_claim.claimed_at_ms.cmp(&a_claim.claimed_at_ms); + } + match b_claim.k.cmp(&a_claim.k) { + Ordering::Equal => a_eid.as_bytes().cmp(b_eid.as_bytes()), + ord => ord, + } + } +} + +/// Internals: ip claims stuff +impl State { + fn take_ip(&mut self, start_k: u64, now_ms: WallMs) -> Result<(), MeshError> { + let occupied = self.occupied_ips(&self.eid); + let (ip, k) = (start_k..) + .map(|k| (Self::candidate(&self.eid, k), k)) + .find(|(ip, _)| !occupied.contains(ip)) + .ok_or(MeshError::IpSpaceExhausted)?; + + self.write_own(now_ms, |state| { + state.ip_claim = IpClaim::Claimed(Claim { + ip, + k, + claimed_at_ms: now_ms, + }); + }); + self.sync_tun(); + self.send_sync_to_all(); + Ok(()) + } + + fn occupied_ips(&self, excluding: &EndpointId) -> HashSet { + self.states + .iter() + .filter(|(eid, _)| *eid != excluding) + .filter_map(|(_, s)| s.get().ip_claim.ip()) + .collect() + } + + /// k-th candidate host address for a node. anyone who knows the + /// endpoint id can compute it. uniform over the space => collision + /// probability 1/65533 per pair. + pub fn candidate(endpoint_id: &EndpointId, k: u64) -> u16 { + let mut h = blake3::Hasher::new(); + h.update(endpoint_id.as_bytes()); + h.update(&k.to_le_bytes()); + let d = h.finalize(); + let raw = u16::from_le_bytes([d.as_bytes()[0], d.as_bytes()[1]]); + 2 + (raw % 65_533) // skip .0.0, .0.1, .255.255 + } +} + +/// Internals: sync stuff +impl State { + fn sync_tun(&mut self) { + let desired = self.own().ip_claim.ip(); + match (self.tun, desired) { + (TunState::Down, Some(ip)) => { + self.tun = TunState::Up { ip }; + self.events + .push(MeshEvent::Tun(TunDirective::Configure { ip })); + } + (TunState::Up { ip: from }, Some(to)) if from != to => { + self.tun = TunState::Up { ip: to }; + self.events + .push(MeshEvent::Tun(TunDirective::Reconfigure { from, to })); + } + (TunState::Up { ip: from }, None) => { + self.tun = TunState::Down; + self.events + .push(MeshEvent::Tun(TunDirective::Teardown { from })); + } + _ => {} + } + } + + fn send_sync_to_all(&mut self) { + let frame = self.sync_frame(); + let targets: Vec = self + .peers + .iter() + .filter(|(_, peer_meta)| peer_meta.connected) + .map(|(eid, _)| *eid) + .collect(); + for peer in targets { + self.outbound.push((peer, frame.clone())); + } + } + + fn sync_frame(&self) -> Frame { + let wire = Wire::FullSync { + states: self.states.values().cloned().collect(), + }; + postcard::to_stdvec(&wire).expect("encode sync") + } + + fn send_sync_to(&mut self, eid: EndpointId) { + let frame = self.sync_frame(); + self.outbound.push((eid, frame)); + } +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct PersistedState { + pub claim: Claim, + pub exposed_ports: Ports, +} diff --git a/src/tun.rs b/src/tun.rs new file mode 100644 index 0000000..7da317a --- /dev/null +++ b/src/tun.rs @@ -0,0 +1,330 @@ +use anyhow::Result; +use iroh::Endpoint; +use pnet_packet::{ + MutablePacket, Packet, + icmp::{MutableIcmpPacket, checksum as icmp_checksum}, + ip::IpNextHeaderProtocols, + ipv4::{Ipv4Flags, Ipv4Packet, MutableIpv4Packet, checksum}, + tcp::{MutableTcpPacket, TcpPacket, ipv4_checksum as tcp_ipv4_checksum}, + udp::{MutableUdpPacket, UdpPacket, ipv4_checksum as udp_ipv4_checksum}, +}; +use serde::{Deserialize, Serialize}; +use std::{ + fmt::Debug, + net::Ipv4Addr, + time::{Duration, Instant}, +}; +use tracing::{debug, info, trace, warn}; +use tun_rs::{AsyncDevice, DeviceBuilder, Layer}; + +use actor_helper::{Action, Handle, Receiver, act}; + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum TunEvent { + Configure { ip: Ipv4Addr }, + Reconfigure { from: Ipv4Addr, to: Ipv4Addr }, + Teardown, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Ipv4Pkg(Vec); + +impl<'a> From> for Ipv4Pkg { + fn from(value: Ipv4Packet<'a>) -> Self { + Ipv4Pkg(value.packet().to_vec()) + } +} + +impl Ipv4Pkg { + // Accept anything that can be viewed as a byte slice. + pub fn new>(buf: B) -> Result { + let v = buf.as_ref().to_vec(); + let pkg = Ipv4Pkg(v); + // validate + pkg.to_ipv4_packet()?; + Ok(pkg) + } + + // Borrowing view over the internal bytes. + pub fn to_ipv4_packet(&self) -> Result> { + Ipv4Packet::new(&self.0).ok_or_else(|| anyhow::anyhow!("Invalid IPv4 packet")) + } + + pub fn as_slice(&self) -> &[u8] { + &self.0 + } +} + +#[derive(Debug, Clone)] +pub struct Tun { + api: Handle, + inner_remote_to_tun_tx: tokio::sync::mpsc::Sender, +} + +struct TunActor { + ip: Ipv4Addr, + dev: AsyncDevice, + inner_remote_to_tun_rx: tokio::sync::mpsc::Receiver, + tun_to_remote_tx: tokio::sync::mpsc::Sender, + endpoint: Endpoint, +} + +impl Debug for TunActor { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TunActor") + .field("ip", &self.ip) + .field("dev", &"AsyncDevice") + .finish() + } +} + +impl Tun { + pub async fn new( + tun_ip: Ipv4Addr, + tun_to_remote_tx: tokio::sync::mpsc::Sender, + endpoint: Endpoint, + ) -> Result { + #[cfg(target_os = "windows")] + dll_export().await?; + + let dev = DeviceBuilder::new() + .ipv4(tun_ip, 16, None) + .layer(Layer::L3) + .mtu(1400) + .build_async()?; + + let (inner_remote_to_tun_tx, inner_remote_to_tun_rx) = + tokio::sync::mpsc::channel(1024 * 16); + let (api, _) = Handle::spawn_with( + TunActor { + ip: tun_ip, + tun_to_remote_tx, + inner_remote_to_tun_rx, + dev, + endpoint, + }, + |mut actor, rx| async move { actor.run(rx).await }, + ); + Ok(Self { + api, + inner_remote_to_tun_tx, + }) + } + + pub async fn write(&self, pkg: Ipv4Pkg) -> Result<()> { + let cap = self.inner_remote_to_tun_tx.capacity(); + if cap < 1000 { + warn!( + "TunActor write channel saturated ({} free). Packet flow stalled.", + cap + ); + } + + match self.inner_remote_to_tun_tx.send(pkg).await { + Ok(_) => Ok(()), + Err(e) => Err(anyhow::anyhow!("Tun actor closed: {}", e)), + } + } + + pub async fn close(&self) -> Result<()> { + self.api + .call(act!(actor => + actor.close() + )) + .await + } +} + +impl TunActor { + async fn run(&mut self, rx: Receiver>) -> Result<()> { + let mut socket_binding_timer = tokio::time::interval(Duration::from_secs(5)); + socket_binding_timer.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + let mut bound_socket_ports = Vec::new(); + + let mut dev_buf = [0u8; 1024 * 128]; + info!("TunActor started for IP: {}", self.ip); + loop { + tokio::select! { + Ok(action) = rx.recv_async() => { + action(self).await; + } + + // Write path: Network -> TUN + Some(pkg) = self.inner_remote_to_tun_rx.recv() => { + if let Ok(packet) = pkg.to_ipv4_packet() { + let data = packet.packet(); + + // logging + let protocol = packet.get_next_level_protocol(); + let dest = packet.get_destination(); + let src = packet.get_source(); + match packet.get_next_level_protocol() { + IpNextHeaderProtocols::Tcp => { + if let Some(tcp) = TcpPacket::new(packet.payload()) { + let src_port = tcp.get_source(); + let dst_port = tcp.get_destination(); + debug!(%protocol, %dest, %src, %src_port, %dst_port, "received from peer"); + } + } + IpNextHeaderProtocols::Udp => { + if let Some(udp) = UdpPacket::new(packet.payload()) { + let src_port = udp.get_source(); + let dst_port = udp.get_destination(); + debug!(%protocol, %dest, %src, %src_port, %dst_port, "received from peer"); + } + } + _ => { + debug!(%protocol, %dest, %src, "received from peer (not TCP/UDP)"); + } + } + + if dest != self.ip { + warn!(%dest,"dropping packet that are not meant for us"); + continue; + } + if src == self.ip { + warn!(%src, "dropping packet authored by us"); + continue; + } + if let Err(err) = self.dev.send(data).await { + warn!(%protocol, %dest, %src, ?err, "failed to write packet to TUN device"); + } + } + } + + // Read path: TUN -> Network + Ok(len) = self.dev.recv(&mut dev_buf) => { + if let Some(mut packet) = MutableIpv4Packet::new(&mut dev_buf[..len]) { + let src = packet.get_source(); + let dest = packet.get_destination(); + let protocol = packet.get_next_level_protocol(); + + // drop broadcast packets to prevent loops (broadcast storms) + if dest.octets()[2] == 255 && dest.octets()[3] == 255 { + trace!( + %protocol, %dest, %src, "dropping broadcast packet to *.*.*.255 to prevent loop" + ); + continue; + } + + if !matches!( + packet.get_next_level_protocol(), + IpNextHeaderProtocols::Tcp | IpNextHeaderProtocols::Udp | IpNextHeaderProtocols::Icmp + ) { + trace!(%protocol, %dest, %src, "ignored packet protocol"); + continue; + } + + // re-calculate and set checksum for the IP header + packet.set_checksum(checksum(&packet.to_immutable())); + + // Check if this is a fragment + // If offset > 0, it's a tail fragment (no L4 header). + // If MF (MoreFragments) flag is set, it's a head fragment (checksum covers future data we don't have). + let is_fragment = (packet.get_flags() & Ipv4Flags::MoreFragments) != 0 + || packet.get_fragment_offset() > 0; + + if !is_fragment { + // ONLY calculate L4 checksums for whole packets + match packet.get_next_level_protocol() { + IpNextHeaderProtocols::Tcp => { + if let Some(mut tcp_packet) = + MutableTcpPacket::new(packet.payload_mut()) + { + tcp_packet.set_checksum(tcp_ipv4_checksum( + &tcp_packet.to_immutable(), + &src, + &dest, + )); + } + } + IpNextHeaderProtocols::Udp => { + if let Some(mut udp_packet) = + MutableUdpPacket::new(packet.payload_mut()) + { + if bound_socket_ports.contains(&udp_packet.get_source()) { + warn!(%protocol, %src, %dest, "filtered iroh UDP packet from socket port"); + continue; + } + + udp_packet.set_checksum(udp_ipv4_checksum( + &udp_packet.to_immutable(), + &src, + &dest, + )); + } + } + IpNextHeaderProtocols::Icmp => { + if let Some(mut icmp_packet) = + MutableIcmpPacket::new(packet.payload_mut()) + { + icmp_packet.set_checksum(icmp_checksum( + &icmp_packet.to_immutable(), + )); + } + } + _ => {} + } + } + + if let Ok(pkg) = Ipv4Pkg::new(packet.packet()) { + let send_timer = Instant::now(); + if let Err(err) = self.tun_to_remote_tx.send(pkg).await { + warn!(%protocol, %dest, %src, ?err, "failed to forward packet from TUN to network"); + } else if send_timer.elapsed() > Duration::from_millis(5) { + warn!(%protocol, %dest, %src, "TUN->network backpressure: send blocked {} ms", send_timer.elapsed().as_millis()); + } + } + } else { + warn!("failed to parse packet from TUN"); + } + } + + _ = socket_binding_timer.tick() => { + bound_socket_ports = self.endpoint + .bound_sockets() + .iter() + .filter_map(|addr: &std::net::SocketAddr| if addr.ip().is_ipv4() { Some(addr.port()) } else { None }) + .collect(); + } + + else => break, + } + } + self.close().await?; + Ok(()) + } +} + +impl TunActor { + pub async fn close(&mut self) -> Result<()> { + info!("closing TunActor"); + let _ = &self.dev; + Ok(()) + } +} + +#[cfg(all(windows, target_arch = "x86"))] +const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/x86/wintun.dll"); +#[cfg(all(windows, target_arch = "x86_64"))] +const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/amd64/wintun.dll"); +#[cfg(all(windows, target_arch = "aarch64"))] +const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/arm64/wintun.dll"); +#[cfg(all(windows, target_arch = "arm"))] +const WINTUN_DLL_EMBEDDED: &[u8] = include_bytes!("../dependencies/wintun/bin/arm/wintun.dll"); + +#[cfg(target_os = "windows")] +async fn dll_export() -> anyhow::Result<()> { + let working_dir = std::env::current_exe()? + .parent() + .ok_or(anyhow::anyhow!("Failed to get parent directory"))? + .to_path_buf(); + let dll_path = working_dir.join("wintun.dll"); + if tokio::fs::try_exists(dll_path.clone()).await? { + return Ok(()); + } else { + tokio::fs::write(&dll_path, WINTUN_DLL_EMBEDDED).await?; + } + Ok(()) +} diff --git a/ui/src-tauri/Cargo.lock b/ui/src-tauri/Cargo.lock index dd3692a..48b6949 100644 --- a/ui/src-tauri/Cargo.lock +++ b/ui/src-tauri/Cargo.lock @@ -4,26 +4,17 @@ version = 4 [[package]] name = "actor-helper" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9378545a9ebea2fb1aee5a06030736ccb4d64e6558e96ac056e77fc7ac13d4b2" +checksum = "e27b633e8510b190e2a968f872136b8a53b38d855089f56030ce0ead131b3377" dependencies = [ "anyhow", - "flume", + "flume 0.12.0", "futures-executor", "futures-util", "tokio", ] -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -36,21 +27,10 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ - "crypto-common 0.1.6", + "crypto-common 0.1.7", "generic-array", ] -[[package]] -name = "aead" -version = "0.6.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" -dependencies = [ - "bytes", - "crypto-common 0.2.0-rc.4", - "inout 0.2.1", -] - [[package]] name = "aes" version = "0.8.4" @@ -58,8 +38,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", - "cipher 0.4.4", - "cpufeatures", + "cipher", + "cpufeatures 0.2.17", ] [[package]] @@ -68,19 +48,30 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ - "aead 0.5.2", + "aead", "aes", - "cipher 0.4.4", + "cipher", "ctr", "ghash", "subtle", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -107,10 +98,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] -name = "android-tzdata" -version = "0.1.1" +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] [[package]] name = "android_system_properties" @@ -122,14 +124,61 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.100" +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ - "backtrace", + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", ] +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + [[package]] name = "arrayref" version = "0.3.9" @@ -166,24 +215,11 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "async-compat" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ba85bc55464dcbf728b56d97e119d673f4cf9062be330a9a26f3acf504a590" -dependencies = [ - "futures-core", - "futures-io", - "once_cell", - "pin-project-lite", - "tokio", -] - [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -195,27 +231,27 @@ dependencies = [ [[package]] name = "async-io" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", "futures-lite", "parking", "polling", - "rustix 1.0.8", + "rustix 1.1.4", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -224,9 +260,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", "async-io", @@ -237,7 +273,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix 1.0.8", + "rustix 1.1.4", ] [[package]] @@ -248,14 +284,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "async-signal" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1" +checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485" dependencies = [ "async-io", "async-lock", @@ -263,10 +299,10 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.0.8", + "rustix 1.1.4", "signal-hook-registry", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -283,7 +319,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -320,6 +356,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -355,67 +400,15 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backon" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592277618714fbcecda9a02ba7a8781f319d26532a88553bbacc77ba5d2b3a8d" +checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" dependencies = [ "fastrand", "gloo-timers", "tokio", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "bao-tree" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06384416b1825e6e04fde63262fda2dc408f5b64c02d04e0d8b70ae72c17a52b" -dependencies = [ - "blake3", - "bytes", - "futures-lite", - "genawaiter", - "iroh-io", - "positioned-io", - "range-collections", - "self_cell", - "serde", - "smallvec", - "tokio", -] - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base16ct" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" - -[[package]] -name = "base32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" - [[package]] name = "base64" version = "0.21.7" @@ -430,15 +423,24 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] -name = "binary-merge" -version = "0.1.2" +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" @@ -448,24 +450,37 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ - "serde", + "serde_core", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", ] [[package]] name = "blake3" -version = "1.8.2" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", + "cpufeatures 0.3.0", ] [[package]] @@ -479,30 +494,20 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0-rc.5" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", - "zeroize", -] - -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2 0.5.2", ] [[package]] name = "block2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.2", + "objc2", ] [[package]] @@ -518,6 +523,30 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "brotli" version = "8.0.2" @@ -540,22 +569,50 @@ dependencies = [ ] [[package]] -name = "btparse" -version = "0.2.0" +name = "bumpalo" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387e80962b798815a2b5c4bcfdb6bf626fa922ffe9f74e373103b858738e9f31" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] -name = "bumpalo" -version = "3.19.0" +name = "byte-unit" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" +dependencies = [ + "rust_decimal", + "schemars 1.2.1", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] name = "bytemuck" -version = "1.23.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -565,9 +622,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -589,7 +646,7 @@ checksum = "3b457277798202ccd365b9c112ebee08ddd57f1033916c8b8ea52f222e5b715d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -598,7 +655,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "cairo-sys-rs", "glib", "libc", @@ -619,11 +676,11 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.12" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0b03af37dad7a14518b7691d81acb0f8222604ad3d1b02f6b4bed5188c0cd5" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -646,7 +703,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] @@ -656,14 +713,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77" dependencies = [ "serde", - "toml 0.9.5", + "toml 0.9.12+spec-1.1.0", +] + +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", ] [[package]] name = "cc" -version = "1.2.35" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "590f9024a68a8c40351881787f1934dc11afd69090f5edb6831464694d836ea3" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "shlex", @@ -698,9 +764,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -710,97 +776,99 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" dependencies = [ "cfg-if", - "cipher 0.4.4", - "cpufeatures", + "cpufeatures 0.3.0", + "rand_core 0.10.1", ] [[package]] -name = "chacha20" -version = "0.10.0-rc.2" +name = "chrono" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd162f2b8af3e0639d83f28a637e4e55657b7a74508dba5a9bf4da523d5c9e9" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "cfg-if", - "cipher 0.5.0-rc.1", - "cpufeatures", - "zeroize", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link 0.2.1", ] [[package]] -name = "chacha20poly1305" -version = "0.10.1" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "aead 0.5.2", - "chacha20 0.9.1", - "cipher 0.4.4", - "poly1305 0.8.0", - "zeroize", + "crypto-common 0.1.7", + "inout", ] [[package]] -name = "chrono" -version = "0.4.41" +name = "clap" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link 0.1.3", + "clap_builder", + "clap_derive", ] [[package]] -name = "cipher" -version = "0.4.4" +name = "clap_builder" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "crypto-common 0.1.6", - "inout 0.1.4", - "zeroize", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "cipher" -version = "0.5.0-rc.1" +name = "clap_derive" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ - "block-buffer 0.11.0-rc.5", - "crypto-common 0.2.0-rc.4", - "inout 0.2.1", - "zeroize", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", ] +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + [[package]] name = "cobs" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] -name = "color-backtrace" -version = "0.7.1" +name = "colorchoice" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49b1973af2a47b5b44f7dd0a344598da95c872e1556b045607888784e973b91" -dependencies = [ - "backtrace", - "btparse", - "termcolor", -] +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" @@ -812,6 +880,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "compact_str" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -823,21 +905,15 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.6" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const-oid" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "convert_case" @@ -845,6 +921,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cookie" version = "0.18.1" @@ -893,11 +978,11 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-graphics-types", "foreign-types", @@ -910,7 +995,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "core-foundation 0.10.1", "libc", ] @@ -924,11 +1009,20 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" dependencies = [ "crc-catalog", ] @@ -979,68 +1073,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "crypto-bigint" -version = "0.5.5" +name = "crossterm" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", + "bitflags 2.11.1", + "crossterm_winapi", + "derive_more 2.1.1", + "document-features", + "mio", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "signal-hook-mio", + "winapi", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "crossterm_winapi" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", + "winapi", ] [[package]] name = "crypto-common" -version = "0.2.0-rc.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "hybrid-array", - "rand_core 0.9.3", + "generic-array", + "typenum", ] [[package]] -name = "crypto_box" -version = "0.10.0-pre.0" +name = "crypto-common" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bda4de3e070830cf3a27a394de135b6709aefcc54d1e16f2f029271254a6ed9" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ - "aead 0.6.0-rc.2", - "chacha20 0.10.0-rc.2", - "crypto_secretbox", - "curve25519-dalek 5.0.0-pre.1", - "salsa20", - "serdect", - "subtle", - "zeroize", + "hybrid-array", ] [[package]] -name = "crypto_secretbox" -version = "0.2.0-pre.0" +name = "csscolorparser" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54532aae6546084a52cef855593daf9555945719eeeda9974150e0def854873e" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" dependencies = [ - "aead 0.6.0-rc.2", - "chacha20 0.10.0-rc.2", - "cipher 0.5.0-rc.1", - "hybrid-array", - "poly1305 0.9.0-rc.2", - "salsa20", - "subtle", - "zeroize", + "lab", + "phf 0.11.3", ] [[package]] @@ -1067,7 +1152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1077,7 +1162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1086,7 +1171,16 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cipher 0.4.4", + "cipher", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", ] [[package]] @@ -1096,26 +1190,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "fiat-crypto 0.2.9", + "rand_core 0.6.4", "rustc_version", "subtle", - "zeroize", ] [[package]] name = "curve25519-dalek" -version = "5.0.0-pre.1" +version = "5.0.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" +checksum = "335f1947f241137a14106b6f5acc5918a5ede29c9d71d3f2cb1678d5075d9fc3" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", - "digest 0.11.0-rc.3", + "digest 0.11.2", "fiat-crypto 0.3.0", - "rand_core 0.9.3", + "rand_core 0.10.1", "rustc_version", "serde", "subtle", @@ -1130,7 +1224,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1139,8 +1233,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -1154,7 +1258,20 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", ] [[package]] @@ -1163,101 +1280,162 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] -name = "der" -version = "0.7.10" +name = "data-encoding-macro" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" dependencies = [ - "const-oid 0.9.6", - "zeroize", + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" +dependencies = [ + "data-encoding", + "syn 2.0.117", ] +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + [[package]] name = "der" -version = "0.8.0-rc.9" +version = "0.8.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" +checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653" dependencies = [ - "const-oid 0.10.1", + "const-oid", "pem-rfc7468", "zeroize", ] [[package]] name = "deranged" -version = "0.5.3" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] -name = "derive_more" -version = "0.99.20" +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "convert_case", + "darling 0.20.11", "proc-macro2", "quote", - "rustc_version", - "syn 2.0.106", + "syn 2.0.117", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.117", ] [[package]] name = "derive_more" -version = "1.0.0" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ - "derive_more-impl 1.0.0", + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", ] [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "derive_more-impl 2.0.1", + "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "1.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case 0.10.0", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version", + "syn 2.0.117", "unicode-xid", ] [[package]] -name = "derive_more-impl" -version = "2.0.1" +name = "dht" +version = "6.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "bf85ef918f33294d98b8833ab7bd095700480b095295b275d36c8fdd86daafdd" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "unicode-xid", + "crc", + "document-features", + "dyn-clone", + "ed25519-dalek", + "flume 0.11.1", + "futures-lite", + "getrandom 0.3.4", + "lru 0.13.0", + "serde", + "serde_bencode", + "serde_bytes", + "sha1_smol", + "thiserror 2.0.18", + "tracing", ] [[package]] @@ -1273,19 +1451,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "crypto-common 0.1.6", + "crypto-common 0.1.7", "subtle", ] [[package]] name = "digest" -version = "0.11.0-rc.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" +checksum = "4850db49bf08e663084f7fb5c87d202ef91a3907271aff24a94eb97ff039153c" dependencies = [ - "block-buffer 0.11.0-rc.5", - "const-oid 0.10.1", - "crypto-common 0.2.0-rc.4", + "block-buffer 0.12.0", + "const-oid", + "crypto-common 0.2.1", ] [[package]] @@ -1306,23 +1484,19 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", + "bitflags 2.11.1", + "block2", + "libc", + "objc2", ] [[package]] @@ -1333,49 +1507,14 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", -] - -[[package]] -name = "distributed-topic-tracker" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c1ed9a2484b742d78d0a1e1cc93cbc1a5de784e1138a2e69414851a9fe39bc" -dependencies = [ - "actor-helper", - "anyhow", - "chrono", - "ed25519-dalek", - "ed25519-dalek-hpke", - "futures-lite", - "iroh", - "iroh-gossip", - "mainline", - "postcard", - "rand 0.9.2", - "serde", - "sha2 0.10.9", - "tokio", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "dlopen2" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" -dependencies = [ - "libc", - "once_cell", - "winapi", + "syn 2.0.117", ] [[package]] name = "dlopen2" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b54f373ccf864bf587a89e880fb7610f8d73f3045f13580948ccbcaff26febff" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" dependencies = [ "dlopen2_derive", "libc", @@ -1385,20 +1524,20 @@ dependencies = [ [[package]] name = "dlopen2_derive" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788160fb30de9cdd857af31c6a2675904b16ece8fc2737b2c7127ba368c9d0f4" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -1414,9 +1553,9 @@ dependencies = [ [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dtoa-short" @@ -1441,9 +1580,9 @@ checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "ed25519" -version = "3.0.0-rc.1" +version = "3.0.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef49c0b20c0ad088893ad2a790a29c06a012b3f05bcfc66661fd22a94b32129" +checksum = "c6e914c7c52decb085cea910552e24c63ac019e3ab8bf001ff736da9a9d9d890" dependencies = [ "pkcs8", "serde", @@ -1452,69 +1591,38 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "3.0.0-pre.1" +version = "3.0.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" +checksum = "053618a4c3d3bc24f188aa660ae75a46eeab74ef07fb415c61431e5e7cd4749b" dependencies = [ - "curve25519-dalek 5.0.0-pre.1", + "curve25519-dalek 5.0.0-pre.6", "ed25519", - "rand_core 0.9.3", + "rand_core 0.10.1", "serde", - "sha2 0.11.0-rc.2", + "sha2 0.11.0-rc.5", "signature", "subtle", "zeroize", ] -[[package]] -name = "ed25519-dalek-hpke" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3553f25a4e38b5ca64b26c54f34e1dd5092d18a5dea03797ac235baab53eaf8f" -dependencies = [ - "ed25519-dalek", - "hpke", - "rand 0.9.2", - "x25519-dalek", -] - [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "hkdf", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "embed-resource" -version = "3.0.5" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6d81016d6c977deefb2ef8d8290da019e27cc26167e102185da528e6c0ab38" +checksum = "63a1d0de4f2249aa0ff5884d7080814f446bb241a559af6c170a41e878ed2d45" dependencies = [ "cc", "memchr", "rustc_version", - "toml 0.9.5", + "toml 0.9.12+spec-1.1.0", "vswhom", - "winreg 0.55.0", + "winreg", ] [[package]] @@ -1546,20 +1654,19 @@ dependencies = [ [[package]] name = "endi" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] -name = "enum-as-inner" -version = "0.6.1" +name = "enum-assoc" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +checksum = "3ed8956bd5c1f0415200516e78ff07ec9e16415ade83c056c230d7b7ea0d55b7" dependencies = [ - "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1580,7 +1687,17 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", ] [[package]] @@ -1591,22 +1708,32 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", + "serde_core", "typeid", ] [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", ] [[package]] @@ -1630,11 +1757,36 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "fastbloom" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8" +dependencies = [ + "foldhash 0.2.0", + "libm", + "portable-atomic", + "siphasher 1.0.2", +] + [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +dependencies = [ + "getrandom 0.3.4", +] [[package]] name = "fdeflate" @@ -1646,13 +1798,12 @@ dependencies = [ ] [[package]] -name = "ff" -version = "0.13.1" +name = "fern" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" dependencies = [ - "rand_core 0.6.4", - "subtle", + "log", ] [[package]] @@ -1678,22 +1829,45 @@ dependencies = [ ] [[package]] -name = "find-msvc-tools" -version = "0.1.0" +name = "filedescriptor" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e178e4fba8a2726903f6ba98a6d221e76f9c12c650d5dc0e6afdc50677b49650" - -[[package]] -name = "fixedbitset" -version = "0.5.7" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "finl_unicode" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fixedbitset" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1707,7 +1881,18 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "nanorand", + "spin 0.9.8", +] + +[[package]] +name = "flume" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" +dependencies = [ + "fastrand", + "futures-core", + "futures-sink", "spin 0.9.8", ] @@ -1717,6 +1902,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foldhash" version = "0.2.0" @@ -1741,7 +1932,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1759,6 +1950,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -1771,9 +1968,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1786,9 +1983,9 @@ dependencies = [ [[package]] name = "futures-buffered" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd" +checksum = "4421cb78ee172b6b06080093479d3c50f058e7c81b7d577bbb8d118d551d4cd5" dependencies = [ "cordyceps", "diatomic-waker", @@ -1799,9 +1996,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1809,30 +2006,28 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.3" +version = "7.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" +checksum = "175cd8cca9e1d45b87f18ffa75088f2099e3c4fe5e2f83e42de112560bea8ea6" dependencies = [ - "fixedbitset", - "futures-buffered", + "fixedbitset 0.5.7", "futures-core", "futures-lite", "pin-project", - "slab", "smallvec", ] [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1841,9 +2036,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -1860,32 +2055,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1895,7 +2090,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -2007,49 +2201,19 @@ dependencies = [ "x11", ] -[[package]] -name = "genawaiter" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" -dependencies = [ - "futures-core", - "genawaiter-macro", - "genawaiter-proc-macro", - "proc-macro-hack", -] - -[[package]] -name = "genawaiter-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" - -[[package]] -name = "genawaiter-proc-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738" -dependencies = [ - "proc-macro-error 0.4.12", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "generator" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" dependencies = [ "cc", "cfg-if", "libc", "log", "rustversion", - "windows 0.61.3", + "windows-link 0.2.1", + "windows-result 0.4.1", ] [[package]] @@ -2060,16 +2224,15 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] name = "getifaddrs" -version = "0.2.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c016cebf305060d144de015c98191ede05c210af588857bc2d4f8611c04663" +checksum = "802c6e75f730346652928a55c200ca680741aaaa60c4973d52a999f520c4fde4" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "libc", "windows-sys 0.59.0", ] @@ -2087,9 +2250,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -2100,15 +2263,31 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", - "wasi 0.14.3+wasi-0.2.4", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", "wasm-bindgen", ] @@ -2122,12 +2301,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "gio" version = "0.18.4" @@ -2166,7 +2339,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "futures-channel", "futures-core", "futures-executor", @@ -2190,11 +2363,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" dependencies = [ "heck 0.4.1", - "proc-macro-crate 2.0.0", - "proc-macro-error 1.0.4", + "proc-macro-crate 2.0.2", + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -2236,17 +2409,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "gtk" version = "0.18.2" @@ -2293,17 +2455,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro-error 1.0.4", + "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -2311,7 +2473,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.11.0", + "indexmap 2.14.0", "slab", "tokio", "tokio-util", @@ -2332,22 +2494,39 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hashbrown" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", ] [[package]] @@ -2389,28 +2568,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "hickory-proto" -version = "0.25.2" +name = "hickory-net" +version = "0.26.0-beta.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +checksum = "1e232f503c4cfe3f4ea6594971255ecab9f6a0080c4c8e0e17630cc701322aa4" dependencies = [ "async-trait", "bytes", "cfg-if", "data-encoding", - "enum-as-inner", "futures-channel", "futures-io", "futures-util", "h2", + "hickory-proto", "http", "idna", "ipnet", - "once_cell", - "rand 0.9.2", - "ring", + "jni 0.22.4", + "rand 0.10.1", "rustls", - "thiserror 2.0.16", + "thiserror 2.0.18", "tinyvec", "tokio", "tokio-rustls", @@ -2418,24 +2596,49 @@ dependencies = [ "url", ] +[[package]] +name = "hickory-proto" +version = "0.26.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcca12171ce774c549f35510be702f4da00ef12ca486f0f2acb2ee96f2f5ca0f" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni 0.22.4", + "once_cell", + "prefix-trie", + "rand 0.10.1", + "ring", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "url", +] + [[package]] name = "hickory-resolver" -version = "0.25.2" +version = "0.26.0-beta.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +checksum = "1e7d2c928fa078e6640f26cf1b537b212e1688829c3944780025c7084e8bbbf6" dependencies = [ "cfg-if", "futures-util", + "hickory-net", "hickory-proto", "ipconfig", + "ipnet", + "jni 0.22.4", "moka", + "ndk-context", "once_cell", "parking_lot", - "rand 0.9.2", + "rand 0.10.1", "resolv-conf", "rustls", "smallvec", - "thiserror 2.0.16", + "system-configuration", + "thiserror 2.0.18", "tokio", "tokio-rustls", "tracing", @@ -2461,32 +2664,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "hpke" -version = "0.13.0" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65d16b699dd1a1fa2d851c970b0c971b388eeeb40f744252b8de48860980c8f" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "aead 0.5.2", - "aes-gcm", - "chacha20poly1305", - "digest 0.10.7", - "generic-array", - "hkdf", - "hmac", - "p256", - "rand_core 0.9.3", - "sha2 0.10.9", - "subtle", - "x25519-dalek", - "zeroize", + "windows-sys 0.61.2", ] [[package]] @@ -2503,12 +2685,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -2549,19 +2730,18 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ "typenum", - "zeroize", ] [[package]] name = "hyper" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -2574,7 +2754,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -2582,31 +2761,28 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", "hyper-util", "rustls", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", - "webpki-roots", ] [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -2615,7 +2791,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2", "tokio", "tower-service", "tracing", @@ -2623,9 +2799,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2633,7 +2809,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -2647,9 +2823,9 @@ dependencies = [ [[package]] name = "ico" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98" +checksum = "3e795dff5605e0f04bff85ca41b51a96b83e80b281e96231bcaaf1ac35103371" dependencies = [ "byteorder", "png", @@ -2657,12 +2833,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -2670,9 +2847,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -2683,11 +2860,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -2698,42 +2874,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2741,12 +2913,24 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "identity-hash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdd7caa900436d8f13b2346fe10257e0c05c1f1f9e351f4f5d57c03bd5f45da" + [[package]] name = "idna" version = "1.1.0" @@ -2768,13 +2952,22 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "if-addrs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0a05c691e1fae256cf7013d99dad472dc52d5543322761f83ec8d47eab40d2b" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "igd-next" -version = "0.16.2" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516893339c97f6011282d5825ac94fc1c7aad5cad26bdc2d0cee068c0bf97f97" +checksum = "bac9a3c8278f43b4cd8463380f4a25653ac843e5b177e1d3eaf849cc9ba10d4d" dependencies = [ - "async-trait", "attohttpc", "bytes", "futures", @@ -2783,7 +2976,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.9.2", + "rand 0.10.1", "tokio", "url", "xmltree", @@ -2802,13 +2995,23 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.17.0", "serde", + "serde_core", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", ] [[package]] @@ -2830,69 +3033,45 @@ dependencies = [ ] [[package]] -name = "inout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7357b6e7aa75618c7864ebd0634b115a7218b0615f4cb1df33ac3eca23943d4" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "inplace-vec-builder" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" -dependencies = [ - "smallvec", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "io-uring" -version = "0.7.10" +name = "instability" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +checksum = "5eb2d60ef19920a3a9193c3e371f726ec1dafc045dac788d0fb3704272458971" dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", + "darling 0.23.0", + "indoc", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] name = "ipconfig" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" dependencies = [ - "socket2 0.5.10", + "socket2", "widestring", - "windows-sys 0.48.0", - "winreg 0.50.0", + "windows-registry", + "windows-result 0.4.1", + "windows-sys 0.61.2", ] [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +dependencies = [ + "serde", +] [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -2900,48 +3079,50 @@ dependencies = [ [[package]] name = "iroh" -version = "0.95.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2374ba3cdaac152dc6ada92d971f7328e6408286faab3b7350842b2ebbed4789" +checksum = "9881b221c7c645d90594cbd331012f7cccb914894288a6cf5538a9115f6d0f3e" dependencies = [ - "aead 0.6.0-rc.2", "backon", + "blake3", "bytes", "cfg_aliases", - "crypto_box", + "ctutils", "data-encoding", - "derive_more 2.0.1", + "der", + "derive_more 2.1.1", "ed25519-dalek", "futures-util", - "getrandom 0.3.3", + "getrandom 0.4.2", "hickory-resolver", "http", - "igd-next", - "instant", + "ipnet", "iroh-base", + "iroh-dns", "iroh-metrics", - "iroh-quinn", - "iroh-quinn-proto", - "iroh-quinn-udp", "iroh-relay", + "mainline", "n0-error", "n0-future", "n0-watcher", - "netdev", "netwatch", + "noq", + "noq-proto", + "noq-udp", + "papaya", "pin-project", - "pkarr", "pkcs8", + "portable-atomic", "portmapper", - "rand 0.9.2", - "reqwest", + "rand 0.10.1", + "reqwest 0.13.2", + "rustc-hash", "rustls", "rustls-pki-types", - "rustls-platform-verifier", "rustls-webpki", "serde", "smallvec", - "strum 0.27.2", + "strum 0.28.0", "time", "tokio", "tokio-stream", @@ -2950,126 +3131,80 @@ dependencies = [ "url", "wasm-bindgen-futures", "webpki-roots", - "z32", +] + +[[package]] +name = "iroh-auth" +version = "0.2.0-pre.1" +source = "git+https://github.com/rustonbsd/iroh-auth?rev=8143b334819fe56863249e5b14e912f1964865e7#8143b334819fe56863249e5b14e912f1964865e7" +dependencies = [ + "hkdf", + "iroh", + "lru 0.17.0", + "n0-future", + "n0-watcher", + "rand 0.10.1", + "secrecy", + "sha2 0.10.9", + "spake2", + "subtle", + "tokio", + "tracing", ] [[package]] name = "iroh-base" -version = "0.95.1" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a8c5fb1cc65589f0d7ab44269a76f615a8c4458356952c9b0ef1c93ea45ff8" +checksum = "738865784637830fb14204ebd3047922db83bc1816a59027af29579b9c27bd99" dependencies = [ - "curve25519-dalek 5.0.0-pre.1", + "curve25519-dalek 5.0.0-pre.6", "data-encoding", - "derive_more 2.0.1", + "data-encoding-macro", + "derive_more 2.1.1", + "digest 0.11.2", "ed25519-dalek", + "getrandom 0.4.2", "n0-error", - "rand_core 0.9.3", + "rand 0.10.1", "serde", + "sha2 0.11.0-rc.5", "url", "zeroize", "zeroize_derive", ] [[package]] -name = "iroh-blobs" -version = "0.97.0" +name = "iroh-dns" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c901304c1c28f257fcf9aae8c9149e54e0baf62f5eb2788cecde3bf1206a04e6" +checksum = "ca474630d1e62ddef83149db6babe6a1055d901df9054349d31b22df99811b92" dependencies = [ - "anyhow", - "arrayvec", - "bao-tree", - "bytes", - "cfg_aliases", - "chrono", - "data-encoding", - "derive_more 2.0.1", - "futures-lite", - "genawaiter", - "hex", - "iroh", + "derive_more 2.1.1", "iroh-base", - "iroh-io", - "iroh-metrics", - "iroh-quinn", - "iroh-tickets", - "irpc", "n0-error", "n0-future", - "n0-snafu", - "nested_enum_utils", - "postcard", - "rand 0.9.2", - "range-collections", - "redb", - "ref-cast", - "reflink-copy", - "self_cell", - "serde", - "smallvec", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "iroh-docs" -version = "0.95.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fe6dc5524c65b401ebb5de204af8921c8cb329316eb972538622d708b4636c" -dependencies = [ - "anyhow", - "async-channel", - "blake3", - "bytes", - "derive_more 2.0.1", - "ed25519-dalek", - "futures-buffered", - "futures-lite", - "futures-util", - "hex", - "iroh", - "iroh-blobs", - "iroh-gossip", - "iroh-metrics", - "iroh-quinn", - "iroh-tickets", - "irpc", - "n0-error", - "n0-future", - "num_enum", - "postcard", - "rand 0.9.2", - "redb", - "self_cell", - "serde", - "serde-error", - "strum 0.26.3", - "tempfile", - "thiserror 2.0.16", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", + "simple-dns", + "strum 0.28.0", ] [[package]] name = "iroh-gossip" -version = "0.95.0" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "026dd31b487ec5e80ac0240f4eb70cd6c0a2800f6ef44beca5329443c194bb22" +checksum = "b349a9ab58e3b56cf41df693bc1812add192ad70ce7c8d0dbdc7d0319d71b11f" dependencies = [ "blake3", "bytes", + "constant_time_eq", "data-encoding", - "derive_more 2.0.1", + "derive_more 2.1.1", "ed25519-dalek", "futures-concurrency", "futures-lite", "futures-util", "hex", - "indexmap 2.11.0", + "indexmap 2.14.0", "iroh", "iroh-base", "iroh-metrics", @@ -3077,43 +3212,40 @@ dependencies = [ "n0-error", "n0-future", "postcard", - "rand 0.9.2", + "rand 0.10.1", "serde", "tokio", "tokio-util", "tracing", ] -[[package]] -name = "iroh-io" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a5feb781017b983ff1b155cd1faf8174da2acafd807aa482876da2d7e6577a" -dependencies = [ - "bytes", - "futures-lite", - "pin-project", - "smallvec", - "tokio", -] - [[package]] name = "iroh-lan" -version = "0.1.2" +version = "1.0.0-pre.1" dependencies = [ "actor-helper", "anyhow", - "distributed-topic-tracker", + "bytes", + "chrono", + "clap", + "crossterm", "ed25519-dalek", "futures", + "futures-lite", + "if-addrs", + "ipnet", "iroh", - "iroh-blobs", - "iroh-docs", + "iroh-auth", "iroh-gossip", - "nix 0.30.1", + "iroh-relay", + "iroh-topic-tracker", + "n0-watcher", + "nix 0.31.2", + "noq", "pnet_packet", "postcard", - "rand 0.9.2", + "rand 0.9.4", + "ratatui", "runas", "self-runas", "serde", @@ -3122,12 +3254,13 @@ dependencies = [ "tracing", "tracing-subscriber", "tun-rs", + "url", "z32", ] [[package]] name = "iroh-lan-ui" -version = "0.1.1" +version = "1.0.0-debug.9" dependencies = [ "anyhow", "iroh-lan", @@ -3137,21 +3270,22 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-log", "tauri-plugin-opener", "tokio", "tracing", - "tracing-subscriber", ] [[package]] name = "iroh-metrics" -version = "0.37.0" +version = "0.38.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e3381da7c93c12d353230c74bba26131d1c8bf3a4d8af0fec041546454582e" +checksum = "761b45ba046134b11eb3e432fa501616b45c4bf3a30c21717578bc07aa6461dd" dependencies = [ "iroh-metrics-derive", "itoa", "n0-error", + "portable-atomic", "postcard", "ryu", "serde", @@ -3160,149 +3294,98 @@ dependencies = [ [[package]] name = "iroh-metrics-derive" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e12bd0763fd16062f5cc5e8db15dd52d26e75a8af4c7fb57ccee3589b344b8" +checksum = "cab063c2bfd6c3d5a33a913d4fdb5252f140db29ec67c704f20f3da7e8f92dbf" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", -] - -[[package]] -name = "iroh-quinn" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde160ebee7aabede6ae887460cd303c8b809054224815addf1469d54a6fcf7" -dependencies = [ - "bytes", - "cfg_aliases", - "iroh-quinn-proto", - "iroh-quinn-udp", - "pin-project-lite", - "rustc-hash", - "rustls", - "socket2 0.5.10", - "thiserror 2.0.16", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "iroh-quinn-proto" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "929d5d8fa77d5c304d3ee7cae9aede31f13908bd049f9de8c7c0094ad6f7c535" -dependencies = [ - "bytes", - "getrandom 0.2.16", - "rand 0.8.5", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "slab", - "thiserror 2.0.16", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "iroh-quinn-udp" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53afaa1049f7c83ea1331f5ebb9e6ebc5fdd69c468b7a22dd598b02c9bcc973" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.5.10", - "tracing", - "windows-sys 0.59.0", + "syn 2.0.117", ] [[package]] name = "iroh-relay" -version = "0.95.1" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fbdf2aeffa7d6ede1a31f6570866c2199b1cee96a0b563994623795d1bac2c" +checksum = "4aa6e9a7277bfbb439739c52b57eb5f9288030983928412022b8e94a43d4d838" dependencies = [ "blake3", "bytes", "cfg_aliases", "data-encoding", - "derive_more 2.0.1", - "getrandom 0.3.3", + "derive_more 2.1.1", + "getrandom 0.4.2", "hickory-resolver", "http", "http-body-util", "hyper", "hyper-util", "iroh-base", + "iroh-dns", "iroh-metrics", - "iroh-quinn", - "iroh-quinn-proto", - "lru 0.16.2", + "lru 0.16.4", "n0-error", "n0-future", + "noq", + "noq-proto", "num_enum", "pin-project", - "pkarr", "postcard", - "rand 0.9.2", - "reqwest", + "rand 0.10.1", + "reqwest 0.13.2", "rustls", "rustls-pki-types", "serde", "serde_bytes", - "sha1", - "strum 0.27.2", + "strum 0.28.0", "tokio", "tokio-rustls", "tokio-util", "tokio-websockets", "tracing", "url", + "vergen-gitcl", "webpki-roots", "ws_stream_wasm", - "z32", ] [[package]] -name = "iroh-tickets" +name = "iroh-topic-tracker" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a322053cacddeca222f0999ce3cf6aa45c64ae5ad8c8911eac9b66008ffbaa5" +source = "git+https://github.com/rustonbsd/iroh-topic-tracker?rev=6c491a161c40d07a0e4613d0f68924c1fef7d2c4#6c491a161c40d07a0e4613d0f68924c1fef7d2c4" dependencies = [ - "data-encoding", - "derive_more 2.0.1", - "iroh-base", - "n0-error", + "anyhow", + "bytes", + "dht", + "ed25519-dalek", + "futures-lite", + "hex", + "iroh", + "iroh-gossip", + "n0-future", + "n0-watcher", "postcard", + "rand 0.10.1", "serde", + "serde_json", + "sha2 0.10.9", + "tokio", + "tracing", + "tracing-subscriber", ] [[package]] name = "irpc" -version = "0.11.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bee97aaa18387c4f0aae61058195dc9f9dea3e41c0e272973fe3e9bf611563d" +checksum = "26bacc8d71f54f16cb5ae82745cfca440ad8ecd09b4480d415b8d9dc78146432" dependencies = [ - "futures-buffered", "futures-util", - "iroh-quinn", "irpc-derive", "n0-error", "n0-future", - "postcard", - "rcgen", - "rustls", "serde", - "smallvec", "tokio", "tokio-util", "tracing", @@ -3310,13 +3393,13 @@ dependencies = [ [[package]] name = "irpc-derive" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58148196d2230183c9679431ac99b57e172000326d664e8456fa2cd27af6505a" +checksum = "4651422b9d7af09fa1437a5fabbd9e074162b502a1af7f5bae8b439eaf3e049f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3338,11 +3421,26 @@ dependencies = [ "once_cell", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "javascriptcore-rs" @@ -3376,25 +3474,79 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", "windows-sys 0.45.0", ] +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -3421,13 +3573,24 @@ dependencies = [ "serde_json", ] +[[package]] +name = "kasuari" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.18", +] + [[package]] name = "keyboard-types" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "serde", "unicode-segmentation", ] @@ -3440,16 +3603,28 @@ checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" dependencies = [ "cssparser", "html5ever", - "indexmap 2.11.0", + "indexmap 2.14.0", "selectors", ] +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libappindicator" version = "0.9.0" @@ -3476,9 +3651,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.177" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" @@ -3492,24 +3667,38 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.8" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link 0.2.1", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.9.4", "libc", ] +[[package]] +name = "line-clipping" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" +dependencies = [ + "bitflags 2.11.1", +] + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3518,37 +3707,39 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +dependencies = [ + "value-bag", +] [[package]] name = "loom" @@ -3571,11 +3762,20 @@ checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" [[package]] name = "lru" -version = "0.16.2" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +checksum = "0e0b564323a0fb6d54b864f625ae139de9612e27edb944dda37c109f05aac531" dependencies = [ - "hashbrown 0.16.0", + "hashbrown 0.17.0", ] [[package]] @@ -3590,6 +3790,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "mac-addr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d25b0e0b648a86960ac23b7ad4abb9717601dec6f66c165f5b037f3f03065f" + [[package]] name = "mac_address" version = "1.1.8" @@ -3602,23 +3808,23 @@ dependencies = [ [[package]] name = "mainline" -version = "6.0.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be6c12ff79bfbf65bcbec84882a4bf700177df6d83a7b866c6a01cda7db4777" +checksum = "6ff27d378ca495eaf3be8616d5d7319c1c18e93fd60e13698fcdc7e19448f1a4" dependencies = [ "crc", "document-features", "dyn-clone", "ed25519-dalek", - "flume", + "flume 0.11.1", "futures-lite", - "getrandom 0.3.3", - "lru 0.16.2", + "getrandom 0.3.4", + "lru 0.16.4", "serde", "serde_bencode", "serde_bytes", "sha1_smol", - "thiserror 2.0.16", + "thiserror 2.0.18", "tracing", ] @@ -3644,7 +3850,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3664,9 +3870,15 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmem" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" [[package]] name = "memoffset" @@ -3683,6 +3895,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3695,60 +3913,59 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", + "log", "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "moka" -version = "0.12.10" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" +checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" dependencies = [ "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", - "loom", + "equivalent", "parking_lot", "portable-atomic", - "rustc_version", "smallvec", "tagptr", - "thiserror 1.0.69", "uuid", ] [[package]] name = "muda" -version = "0.17.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +checksum = "7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177" dependencies = [ "crossbeam-channel", "dpi", "gtk", "keyboard-types", - "objc2 0.6.2", + "objc2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation", "once_cell", "png", "serde", - "thiserror 2.0.16", + "thiserror 2.0.18", "windows-sys 0.60.2", ] [[package]] name = "n0-error" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d5969a2f40e9d9ed121a789c415f4114ac2b28e5731c080bdefee217d3b3fb" +checksum = "af4782b4baf92d686d161c15460c83d16ebcfd215918763903e9619842665cae" dependencies = [ "anyhow", "n0-error-macros", @@ -3757,23 +3974,23 @@ dependencies = [ [[package]] name = "n0-error-macros" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a6908df844696d9af91c7c3950d50e52d67df327d02a95367f95bbf177d6556" +checksum = "03755949235714b2b307e5ae89dd8c1c2531fb127d9b8b7b4adf9c876cd3ed18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "n0-future" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c0709ac8235ce13b82bc4d180ee3c42364b90c1a8a628c3422d991d75a728b5" +checksum = "e2ab99dfb861450e68853d34ae665243a88b8c493d01ba957321a1e9b2312bbe" dependencies = [ "cfg_aliases", - "derive_more 1.0.0", + "derive_more 2.1.1", "futures-buffered", "futures-lite", "futures-util", @@ -3788,46 +4005,37 @@ dependencies = [ ] [[package]] -name = "n0-snafu" -version = "0.2.2" +name = "n0-qlog" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1815107e577a95bfccedb4cfabc73d709c0db6d12de3f14e0f284a8c5036dc4f" +checksum = "227d9ae7ef1e74f3e9f3e3503b06b58ff507ce754efdc29e4a44af74ad300cc3" dependencies = [ - "anyhow", - "btparse", - "color-backtrace", - "snafu", - "tracing-error", + "serde", + "serde_json", + "serde_with", + "smallvec", + "strum 0.27.2", ] [[package]] name = "n0-watcher" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38acf13c1ddafc60eb7316d52213467f8ccb70b6f02b65e7d97f7799b1f50be4" +checksum = "38795f7932e6e9d1c6e989270ef5b3ff24ebb910e2c9d4bed2d28d8bae3007dc" dependencies = [ - "derive_more 2.0.1", + "derive_more 2.1.1", "n0-error", "n0-future", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.16", -] - [[package]] name = "ndk" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.9.4", - "jni-sys", + "bitflags 2.11.1", + "jni-sys 0.3.1", "log", "ndk-sys", "num_enum", @@ -3847,116 +4055,107 @@ version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "jni-sys", -] - -[[package]] -name = "nested_enum_utils" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43fa9161ed44d30e9702fe42bd78693bceac0fed02f647da749f36109023d3a3" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 1.0.109", + "jni-sys 0.3.1", ] [[package]] name = "netconfig-rs" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "207561c8758738388c2fd851c3e759f503583d8dd70ddc895baae806753ad4c9" +checksum = "733ad7a1352f0748a620368f2ea5cd94f0e449c5108fbac86ace31df1601bf6f" dependencies = [ "cfg-if", - "core-foundation 0.9.4", + "core-foundation 0.10.1", "ipnet", "libc", - "netlink-packet-core 0.7.0", - "netlink-packet-route 0.24.0", + "netlink-packet-core", + "netlink-packet-route 0.25.1", "netlink-sys", "nix 0.30.1", "scopeguard", - "system-configuration-sys 0.5.0", - "thiserror 2.0.16", + "system-configuration-sys", + "thiserror 2.0.18", "widestring", "windows 0.61.3", ] [[package]] name = "netdev" -version = "0.38.2" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ab878b4c90faf36dab10ea51d48c69ae9019bcca47c048a7c9b273d5d7a823" +checksum = "e30af1a5073b82356d9317c18226826370b4288eba2f71c7e84e18bae51b3847" dependencies = [ - "dlopen2 0.5.0", + "block2", + "dispatch2", + "dlopen2", "ipnet", "libc", - "netlink-packet-core 0.8.1", - "netlink-packet-route 0.25.1", + "mac-addr", + "netlink-packet-core", + "netlink-packet-route 0.29.0", "netlink-sys", + "objc2-core-foundation", + "objc2-system-configuration", "once_cell", - "system-configuration", - "windows-sys 0.59.0", + "plist", + "windows-sys 0.61.2", ] [[package]] name = "netlink-packet-core" -version = "0.7.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-utils", + "paste", ] [[package]] -name = "netlink-packet-core" -version = "0.8.1" +name = "netlink-packet-route" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3463cbb78394cb0141e2c926b93fc2197e473394b761986eca3b9da2c63ae0f4" +checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef" dependencies = [ - "paste", + "bitflags 2.11.1", + "libc", + "log", + "netlink-packet-core", ] [[package]] name = "netlink-packet-route" -version = "0.24.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d83370a96813d7c977f8b63054f1162df6e5784f1c598d689236564fb5a6f2" +checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445" dependencies = [ - "anyhow", - "bitflags 2.9.4", - "byteorder", + "bitflags 2.11.1", "libc", "log", - "netlink-packet-core 0.7.0", - "netlink-packet-utils", + "netlink-packet-core", ] [[package]] name = "netlink-packet-route" -version = "0.25.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec2f5b6839be2a19d7fa5aab5bc444380f6311c2b693551cb80f45caaa7b5ef" +checksum = "df9854ea6ad14e3f4698a7f03b65bce0833dd2d81d594a0e4a984170537146b6" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "libc", "log", - "netlink-packet-core 0.8.1", + "netlink-packet-core", ] [[package]] -name = "netlink-packet-utils" -version = "0.5.2" +name = "netlink-packet-route" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +checksum = "be8919612f6028ab4eacbbfe1234a9a43e3722c6e0915e7ff519066991905092" dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror 1.0.69", + "bitflags 2.11.1", + "libc", + "log", + "netlink-packet-core", ] [[package]] @@ -3968,19 +4167,19 @@ dependencies = [ "bytes", "futures", "log", - "netlink-packet-core 0.8.1", + "netlink-packet-core", "netlink-sys", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] name = "netlink-sys" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" +checksum = "cd6c30ed10fa69cc491d491b85cc971f6bdeb8e7367b7cde2ee6cc878d583fae" dependencies = [ "bytes", - "futures", + "futures-util", "libc", "log", "tokio", @@ -3988,28 +4187,30 @@ dependencies = [ [[package]] name = "netwatch" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f2acd376ef48b6c326abf3ba23c449e0cb8aa5c2511d189dd8a8a3bfac889b" +checksum = "6fc0d4b4134425d9834e591b1a6f807ea365c6d941d738942215564af5f28a97" dependencies = [ "atomic-waker", "bytes", "cfg_aliases", - "derive_more 2.0.1", - "iroh-quinn-udp", + "derive_more 2.1.1", "js-sys", "libc", "n0-error", "n0-future", "n0-watcher", "netdev", - "netlink-packet-core 0.8.1", - "netlink-packet-route 0.25.1", + "netlink-packet-core", + "netlink-packet-route 0.30.0", "netlink-proto", "netlink-sys", + "noq-udp", + "objc2-core-foundation", + "objc2-system-configuration", "pin-project-lite", "serde", - "socket2 0.6.0", + "socket2", "time", "tokio", "tokio-util", @@ -4032,7 +4233,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", @@ -4045,7 +4246,20 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", @@ -4065,34 +4279,104 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] -name = "ntimestamp" -version = "1.0.0" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50f94c405726d3e0095e89e72f75ce7f6587b94a8bd8dc8054b73f65c0fd68c" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "base32", - "document-features", - "getrandom 0.2.16", - "httpdate", - "js-sys", - "once_cell", - "serde", + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noq" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b969bd157c3bd3bab239a1a8b14f67f2033fa012770367fcbd5b42d71ae3548" +dependencies = [ + "bytes", + "cfg_aliases", + "derive_more 2.1.1", + "noq-proto", + "noq-udp", + "pin-project-lite", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "web-time", +] + +[[package]] +name = "noq-proto" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdec6f5039d98ee5377b2f532d495a555eb664c53161b1b5780dcaeac678b60e" +dependencies = [ + "aes-gcm", + "bytes", + "derive_more 2.1.1", + "enum-assoc", + "fastbloom", + "getrandom 0.4.2", + "identity-hash", + "lru-slab", + "n0-qlog", + "rand 0.10.1", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "slab", + "sorted-index-buffer", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "noq-udp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee91b05f4f3353290936ba1f3233518868fb4e2da99cb4c90d1f8cebb064e527" +dependencies = [ + "cfg_aliases", + "libc", + "socket2", + "tracing", + "windows-sys 0.61.2", ] [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "num-traits" @@ -4105,9 +4389,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" dependencies = [ "num_enum_derive", "rustversion", @@ -4115,37 +4399,30 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.3.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" +name = "num_threads" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ - "objc-sys", - "objc2-encode", + "libc", ] [[package]] name = "objc2" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", "objc2-exception-helper", @@ -4153,77 +4430,106 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.9.4", - "block2 0.6.1", + "bitflags 2.11.1", + "block2", "libc", - "objc2 0.6.2", + "objc2", "objc2-cloud-kit", "objc2-core-data", "objc2-core-foundation", "objc2-core-graphics", "objc2-core-image", - "objc2-foundation 0.3.1", - "objc2-quartz-core 0.3.1", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation", + "objc2-quartz-core", ] [[package]] name = "objc2-cloud-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", - "objc2-foundation 0.3.1", + "bitflags 2.11.1", + "objc2", + "objc2-foundation", ] [[package]] name = "objc2-core-data" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", - "objc2-foundation 0.3.1", + "bitflags 2.11.1", + "objc2", + "objc2-foundation", ] [[package]] name = "objc2-core-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", + "block2", "dispatch2", - "objc2 0.6.2", + "libc", + "objc2", ] [[package]] name = "objc2-core-graphics" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "dispatch2", - "objc2 0.6.2", + "objc2", "objc2-core-foundation", "objc2-io-surface", ] [[package]] name = "objc2-core-image" -version = "0.3.1" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ - "objc2 0.6.2", - "objc2-foundation 0.3.1", + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", ] [[package]] @@ -4238,149 +4544,124 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" dependencies = [ - "cc", -] - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.9.4", - "block2 0.5.1", - "libc", - "objc2 0.5.2", + "cc", ] [[package]] name = "objc2-foundation" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.9.4", - "block2 0.6.1", + "bitflags 2.11.1", + "block2", "libc", - "objc2 0.6.2", + "objc2", "objc2-core-foundation", ] [[package]] name = "objc2-io-surface" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", + "bitflags 2.11.1", + "objc2", "objc2-core-foundation", ] [[package]] name = "objc2-javascript-core" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9052cb1bb50a4c161d934befcf879526fb87ae9a68858f241e693ca46225cf5a" +checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586" dependencies = [ - "objc2 0.6.2", + "objc2", "objc2-core-foundation", ] -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.9.4", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-quartz-core" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.9.4", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal", + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] -name = "objc2-quartz-core" -version = "0.3.1" +name = "objc2-security" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", - "objc2-foundation 0.3.1", + "bitflags 2.11.1", + "objc2", + "objc2-core-foundation", ] [[package]] -name = "objc2-security" -version = "0.3.1" +name = "objc2-system-configuration" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1f8e0ef3ab66b08c42644dcb34dba6ec0a574bbd8adbb8bdbdc7a2779731a44" +checksum = "7216bd11cbda54ccabcab84d523dc93b858ec75ecfb3a7d89513fa22464da396" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", + "bitflags 2.11.1", + "dispatch2", + "libc", + "objc2", "objc2-core-foundation", + "objc2-security", ] [[package]] name = "objc2-ui-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.9.4", - "objc2 0.6.2", + "bitflags 2.11.1", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation", ] [[package]] name = "objc2-web-kit" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "bitflags 2.9.4", - "block2 0.6.1", - "objc2 0.6.2", + "bitflags 2.11.1", + "block2", + "objc2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation", "objc2-javascript-core", "objc2-security", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" dependencies = [ "critical-section", "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -4389,9 +4670,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "open" -version = "5.3.2" +version = "5.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +checksum = "9f3bab717c29a857abf75fcef718d441ec7cb2725f937343c734740a985d37fd" dependencies = [ "dunce", "is-wsl", @@ -4401,9 +4682,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "option-ext" @@ -4412,23 +4693,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] -name = "ordered-stream" -version = "0.2.0" +name = "ordered-float" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ - "futures-core", - "pin-project-lite", + "num-traits", ] [[package]] -name = "p256" -version = "0.13.2" +name = "ordered-stream" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" dependencies = [ - "elliptic-curve", - "primeorder", + "futures-core", + "pin-project-lite", ] [[package]] @@ -4456,6 +4736,16 @@ dependencies = [ "system-deps", ] +[[package]] +name = "papaya" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" +dependencies = [ + "equivalent", + "seize", +] + [[package]] name = "parking" version = "2.2.1" @@ -4464,9 +4754,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -4474,15 +4764,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -4497,21 +4787,11 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - [[package]] name = "pem-rfc7468" -version = "1.0.0-rc.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" dependencies = [ "base64ct", ] @@ -4522,6 +4802,49 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pest_meta" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" +dependencies = [ + "pest", + "sha2 0.10.9", +] + [[package]] name = "pharos" version = "0.5.3" @@ -4599,7 +4922,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared 0.10.0", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -4609,7 +4932,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared 0.11.3", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] @@ -4636,7 +4959,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4663,107 +4986,70 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 1.0.1", + "siphasher 1.0.2", ] [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", "futures-io", ] -[[package]] -name = "pkarr" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "792c1328860f6874e90e3b387b4929819cc7783a6bd5a4728e918706eb436a48" -dependencies = [ - "async-compat", - "base32", - "bytes", - "cfg_aliases", - "document-features", - "dyn-clone", - "ed25519-dalek", - "futures-buffered", - "futures-lite", - "getrandom 0.3.3", - "log", - "lru 0.13.0", - "ntimestamp", - "reqwest", - "self_cell", - "serde", - "sha1_smol", - "simple-dns", - "thiserror 2.0.16", - "tokio", - "tracing", - "url", - "wasm-bindgen-futures", -] - [[package]] name = "pkcs8" -version = "0.11.0-rc.7" +version = "0.11.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" +checksum = "b226d2cc389763951db8869584fd800cbbe2962bf454e2edeb5172b31ee99774" dependencies = [ - "der 0.8.0-rc.9", + "der", "spki", ] [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" -version = "1.7.4" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", - "indexmap 2.11.0", + "indexmap 2.14.0", "quick-xml", "serde", "time", @@ -4787,7 +5073,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4826,37 +5112,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.8", - "windows-sys 0.60.2", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash 0.5.1", -] - -[[package]] -name = "poly1305" -version = "0.9.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb78a635f75d76d856374961deecf61031c0b6f928c83dc9c0924ab6c019c298" -dependencies = [ - "cpufeatures", - "universal-hash 0.6.0-rc.2", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] @@ -4866,26 +5131,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", - "universal-hash 0.5.1", + "universal-hash", ] [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +dependencies = [ + "serde", +] [[package]] name = "portmapper" -version = "0.12.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b575f975dcf03e258b0c7ab3f81497d7124f508884c37da66a7314aa2a8d467" +checksum = "a145e62ddd9aecc9c7b1a3c84cea2a803386c7f4da7795bf9f0d50d90dc52549" dependencies = [ "base64 0.22.1", "bytes", - "derive_more 2.0.1", + "derive_more 2.1.1", "futures-lite", "futures-util", "hyper-util", @@ -4895,10 +5163,10 @@ dependencies = [ "n0-error", "netwatch", "num_enum", - "rand 0.9.2", + "rand 0.10.1", "serde", "smallvec", - "socket2 0.6.0", + "socket2", "time", "tokio", "tokio-util", @@ -4907,16 +5175,6 @@ dependencies = [ "url", ] -[[package]] -name = "positioned-io" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ec4b80060f033312b99b6874025d9503d2af87aef2dd4c516e253fbfcdada7" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "postcard" version = "1.1.3" @@ -4939,14 +5197,14 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -4973,12 +5231,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] -name = "primeorder" -version = "0.13.6" +name = "prefix-trie" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23370be78b7e5bcbb0cab4a02047eb040279a693c78daad04c2c5f1c24a83503" +dependencies = [ + "either", + "ipnet", + "num-traits", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "elliptic-curve", + "proc-macro2", + "syn 2.0.117", ] [[package]] @@ -4993,33 +5263,21 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ - "toml_edit 0.20.7", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", ] [[package]] name = "proc-macro-crate" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" -dependencies = [ - "toml_edit 0.22.27", -] - -[[package]] -name = "proc-macro-error" -version = "0.4.12" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "proc-macro-error-attr 0.4.12", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "toml_edit 0.25.11+spec-1.1.0", ] [[package]] @@ -5028,23 +5286,10 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "proc-macro-error-attr 1.0.4", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" -dependencies = [ + "proc-macro-error-attr", "proc-macro2", "quote", "syn 1.0.109", - "syn-mid", "version_check", ] @@ -5067,82 +5312,47 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] -name = "quick-xml" -version = "0.38.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" -dependencies = [ - "memchr", -] - -[[package]] -name = "quinn" -version = "0.11.9" +name = "ptr_meta" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2 0.6.0", - "thiserror 2.0.16", - "tokio", - "tracing", - "web-time", + "ptr_meta_derive", ] [[package]] -name = "quinn-proto" -version = "0.11.13" +name = "ptr_meta_derive" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ - "bytes", - "getrandom 0.3.3", - "lru-slab", - "rand 0.9.2", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "slab", - "thiserror 2.0.16", - "tinyvec", - "tracing", - "web-time", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "quinn-udp" -version = "0.5.14" +name = "quick-xml" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.6.0", - "tracing", - "windows-sys 0.60.2", + "memchr", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -5153,6 +5363,18 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -5169,9 +5391,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -5180,12 +5402,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -5215,7 +5448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -5233,18 +5466,24 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_hc" version = "0.2.0" @@ -5264,53 +5503,103 @@ dependencies = [ ] [[package]] -name = "range-collections" -version = "0.4.6" +name = "ratatui" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861706ea9c4aded7584c5cd1d241cec2ea7f5f50999f236c22b65409a1f1a0d0" +checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" dependencies = [ - "binary-merge", - "inplace-vec-builder", - "ref-cast", - "serde", - "smallvec", + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termwiz", + "ratatui-widgets", ] [[package]] -name = "raw-window-handle" -version = "0.6.2" +name = "ratatui-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" +dependencies = [ + "bitflags 2.11.1", + "compact_str", + "hashbrown 0.16.1", + "indoc", + "itertools", + "kasuari", + "lru 0.16.4", + "strum 0.27.2", + "thiserror 2.0.18", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] [[package]] -name = "rcgen" -version = "0.14.5" +name = "ratatui-crossterm" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fae430c6b28f1ad601274e78b7dffa0546de0b73b4cd32f46723c0c2a16f7a5" +checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" dependencies = [ - "pem", - "ring", - "rustls-pki-types", - "time", - "yasna", + "cfg-if", + "crossterm", + "instability", + "ratatui-core", ] [[package]] -name = "redb" -version = "2.6.3" +name = "ratatui-macros" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eca1e9d98d5a7e9002d0013e18d5a9b000aee942eb134883a82f06ebffb6c01" +checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" dependencies = [ - "libc", + "ratatui-core", + "ratatui-widgets", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" +dependencies = [ + "ratatui-core", + "termwiz", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.16.1", + "indoc", + "instability", + "itertools", + "line-clipping", + "ratatui-core", + "strum 0.27.2", + "time", + "unicode-segmentation", + "unicode-width", ] +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", ] [[package]] @@ -5319,48 +5608,36 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.16", + "thiserror 2.0.18", ] [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", -] - -[[package]] -name = "reflink-copy" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd34aed05de14a9001009dbffc2a6843095dcd8fe3d1207016192717a449d218" -dependencies = [ - "cfg-if", - "libc", - "rustix 1.0.8", - "windows 0.62.2", + "syn 2.0.117", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -5370,9 +5647,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -5381,15 +5658,24 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rend" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -5399,20 +5685,52 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", - "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", +] + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", "tokio-rustls", "tokio-util", "tower", @@ -5421,16 +5739,15 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", "web-sys", - "webpki-roots", ] [[package]] name = "resolv-conf" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "ring" @@ -5440,24 +5757,53 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "route_manager" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb012980f7bfadc330cc5b99e2a93bda641717554338b6ddb0e86de4188af65b" +checksum = "319bb478ff9aae1dc7a544fa599e9eb47e2521621dc3921fba6abcaaa312092c" dependencies = [ - "flume", + "flume 0.12.0", "libc", - "netlink-packet-core 0.7.0", - "netlink-packet-route 0.24.0", + "netlink-packet-core", + "netlink-packet-route 0.28.0", "netlink-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -5485,16 +5831,27 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.26" +name = "rust_decimal" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "2ce901f9a19d251159075a4c37af514c3b8ef99c22e02dd8c19161cf397ee94a" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.6", + "rkyv", + "serde", + "serde_json", + "wasm-bindgen", +] [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -5511,7 +5868,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -5520,22 +5877,22 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.12.1", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" dependencies = [ "log", "once_cell", @@ -5548,9 +5905,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -5560,9 +5917,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -5570,13 +5927,13 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", - "jni", + "jni 0.21.1", "log", "once_cell", "rustls", @@ -5585,8 +5942,8 @@ dependencies = [ "rustls-webpki", "security-framework", "security-framework-sys", - "webpki-root-certs 0.26.11", - "windows-sys 0.59.0", + "webpki-root-certs", + "windows-sys 0.61.2", ] [[package]] @@ -5597,9 +5954,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -5614,19 +5971,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "salsa20" -version = "0.11.0-rc.1" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ff3b81c8a6e381bc1673768141383f9328048a60edddcfc752a8291a138443" -dependencies = [ - "cfg-if", - "cipher 0.5.0-rc.1", -] +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -5639,11 +5986,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5675,9 +6022,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.0.4" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", @@ -5694,7 +6041,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5710,25 +6057,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "sec1" -version = "0.7.3" +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "secrecy" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" dependencies = [ - "base16ct 0.2.0", - "der 0.7.10", - "generic-array", - "subtle", "zeroize", ] [[package]] name = "security-framework" -version = "3.3.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -5737,14 +6086,24 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", ] +[[package]] +name = "seize" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "selectors" version = "0.24.0" @@ -5775,19 +6134,14 @@ dependencies = [ "winapi", ] -[[package]] -name = "self_cell" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" - [[package]] name = "semver" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -5806,23 +6160,15 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-error" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "342110fb7a5d801060c885da03bf91bfa7c7ca936deafcc64bb6706375605d47" -dependencies = [ - "serde", -] - [[package]] name = "serde-untagged" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34836a629bcbc6f1afdf0907a744870039b1e14c0561cb26094fa683b158eff3" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" dependencies = [ "erased-serde", "serde", + "serde_core", "typeid", ] @@ -5838,11 +6184,12 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.17" +version = "0.11.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -5862,7 +6209,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5873,19 +6220,21 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ + "indexmap 2.14.0", "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -5896,7 +6245,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5910,11 +6259,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -5931,19 +6280,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.0" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.0", + "indexmap 2.14.0", "schemars 0.9.0", - "schemars 1.0.4", - "serde", - "serde_derive", + "schemars 1.2.1", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -5951,24 +6299,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.0" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", - "syn 2.0.106", -] - -[[package]] -name = "serdect" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" -dependencies = [ - "base16ct 0.3.0", - "serde", + "syn 2.0.117", ] [[package]] @@ -5990,7 +6328,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6003,17 +6341,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "sha1" -version = "0.11.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e046edf639aa2e7afb285589e5405de2ef7e61d4b0ac1e30256e3eab911af9" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.3", -] - [[package]] name = "sha1_smol" version = "1.0.1" @@ -6027,19 +6354,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] [[package]] name = "sha2" -version = "0.11.0-rc.2" +version = "0.11.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" +checksum = "7c5f3b1e2dc8aad28310d8410bd4d7e180eca65fca176c52ab00d364475d0024" dependencies = [ "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.3", + "cpufeatures 0.2.17", + "digest 0.11.2", ] [[package]] @@ -6057,26 +6384,58 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "signature" -version = "3.0.0-rc.4" +version = "3.0.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" +checksum = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] name = "simdutf8" @@ -6090,7 +6449,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", ] [[package]] @@ -6101,15 +6460,15 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -6117,73 +6476,47 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ - "serde", -] - -[[package]] -name = "snafu" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" -dependencies = [ - "backtrace", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.106", -] - -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", + "serde", ] [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "softbuffer" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +checksum = "aac18da81ebbf05109ab275b157c22a653bb3c12cf884450179942f81bcbf6c3" dependencies = [ "bytemuck", - "cfg_aliases", - "core-graphics", - "foreign-types", "js-sys", - "log", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", + "ndk", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-quartz-core", "raw-window-handle", "redox_syscall", + "tracing", "wasm-bindgen", "web-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] +[[package]] +name = "sorted-index-buffer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea06cc588e43c632923a55450401b8f25e628131571d4e1baea1bdfdb2b5ed06" + [[package]] name = "soup3" version = "0.5.0" @@ -6210,6 +6543,18 @@ dependencies = [ "system-deps", ] +[[package]] +name = "spake2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5482afe85a0b6ce956c945401598dbc527593c77ba51d0a87a586938b1b893a" +dependencies = [ + "curve25519-dalek 4.1.3", + "hkdf", + "rand_core 0.6.4", + "sha2 0.10.9", +] + [[package]] name = "spez" version = "0.1.2" @@ -6218,7 +6563,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6243,14 +6588,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80" dependencies = [ "base64ct", - "der 0.8.0-rc.9", + "der", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -6291,45 +6636,44 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.3" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "strum_macros 0.26.4", + "strum_macros 0.27.2", ] [[package]] name = "strum" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ - "strum_macros 0.27.2", + "strum_macros 0.28.0", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "rustversion", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "strum_macros" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6362,26 +6706,15 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn-mid" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea305d57546cc8cd04feb14b62ec84bf17f50e3f7b12560d7bfa9265f39d9ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -6399,28 +6732,18 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "core-foundation 0.9.4", - "system-configuration-sys 0.6.0", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", + "system-configuration-sys", ] [[package]] @@ -6442,7 +6765,7 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml 0.8.23", + "toml 0.8.2", "version-compare", ] @@ -6454,35 +6777,33 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tao" -version = "0.34.3" +version = "0.34.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7" +checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" dependencies = [ - "bitflags 2.9.4", - "block2 0.6.1", + "bitflags 2.11.1", + "block2", "core-foundation 0.10.1", "core-graphics", "crossbeam-channel", - "dispatch", - "dlopen2 0.8.0", + "dispatch2", + "dlopen2", "dpi", "gdkwayland-sys", "gdkx11-sys", "gtk", - "jni", - "lazy_static", + "jni 0.21.1", "libc", "log", "ndk", "ndk-context", "ndk-sys", - "objc2 0.6.2", + "objc2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation", "once_cell", "parking_lot", "raw-window-handle", - "scopeguard", "tao-macros", "unicode-segmentation", "url", @@ -6500,9 +6821,15 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.12.16" @@ -6521,25 +6848,25 @@ dependencies = [ "dirs", "dunce", "embed_plist", - "getrandom 0.3.3", + "getrandom 0.3.4", "glob", "gtk", "heck 0.5.0", "http", - "jni", + "jni 0.21.1", "libc", "log", "mime", "muda", - "objc2 0.6.2", + "objc2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation", "objc2-ui-kit", "objc2-web-kit", "percent-encoding", "plist", "raw-window-handle", - "reqwest", + "reqwest 0.12.28", "serde", "serde_json", "serde_repr", @@ -6550,7 +6877,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tray-icon", "url", @@ -6563,9 +6890,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.4.1" +version = "2.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c432ccc9ff661803dab74c6cd78de11026a578a9307610bbc39d3c55be7943f" +checksum = "4bbc990d1dbf57a8e1c7fa2327f2a614d8b757805603c1b9ba5c81bade09fd4d" dependencies = [ "anyhow", "cargo_toml", @@ -6579,15 +6906,15 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.9.5", + "toml 0.9.12+spec-1.1.0", "walkdir", ] [[package]] name = "tauri-codegen" -version = "2.4.0" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a" +checksum = "d4a24476afd977c5d5d169f72425868613d82747916dd29e0a357c84c4bd6d29" dependencies = [ "base64 0.22.1", "brotli", @@ -6601,9 +6928,9 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", - "syn 2.0.106", + "syn 2.0.117", "tauri-utils", - "thiserror 2.0.16", + "thiserror 2.0.18", "time", "url", "uuid", @@ -6612,23 +6939,23 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "2.4.0" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e" +checksum = "d39b349a98dadaffebb73f0a40dcd1f23c999211e5a2e744403db384d0c33de7" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "tauri-codegen", "tauri-utils", ] [[package]] name = "tauri-plugin" -version = "2.4.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9946a3cede302eac0c6eb6c6070ac47b1768e326092d32efbb91f21ed58d978f" +checksum = "ddde7d51c907b940fb573006cdda9a642d6a7c8153657e88f8a5c3c9290cd4aa" dependencies = [ "anyhow", "glob", @@ -6637,27 +6964,49 @@ dependencies = [ "serde", "serde_json", "tauri-utils", - "toml 0.9.5", + "toml 0.9.12+spec-1.1.0", "walkdir", ] +[[package]] +name = "tauri-plugin-log" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5709c792b8630290b5d9811a1f8fe983dd925fc87c7fc7f4923616458cd00b6" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log", + "objc2", + "objc2-foundation", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.18", + "time", +] + [[package]] name = "tauri-plugin-opener" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786156aa8e89e03d271fbd3fe642207da8e65f3c961baa9e2930f332bf80a1f5" +checksum = "c26b72571d25dee25667940027114e60f569fc3974f8cefbe50c2cbc5fd65e3b" dependencies = [ "dunce", "glob", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation", "open", "schemars 0.8.22", "serde", "serde_json", "tauri", "tauri-plugin", - "thiserror 2.0.16", + "thiserror 2.0.18", "url", "windows 0.61.3", "zbus", @@ -6665,23 +7014,23 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.8.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846" +checksum = "2826d79a3297ed08cd6ea7f412644ef58e32969504bc4fbd8d7dbeabc4445ea2" dependencies = [ "cookie", "dpi", "gtk", "http", - "jni", - "objc2 0.6.2", + "jni 0.21.1", + "objc2", "objc2-ui-kit", "objc2-web-kit", "raw-window-handle", "serde", "serde_json", "tauri-utils", - "thiserror 2.0.16", + "thiserror 2.0.18", "url", "webkit2gtk", "webview2-com", @@ -6690,17 +7039,17 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.8.1" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807" +checksum = "187a3f26f681bdf028f796ccf57cf478c1ee422c50128e5a0a6ebeb3f5910065" dependencies = [ "gtk", "http", - "jni", + "jni 0.21.1", "log", - "objc2 0.6.2", + "objc2", "objc2-app-kit", - "objc2-foundation 0.3.1", + "objc2-foundation", "once_cell", "percent-encoding", "raw-window-handle", @@ -6717,9 +7066,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "2.7.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212" +checksum = "219a1f983a2af3653f75b5747f76733b0da7ff03069c7a41901a5eb3ace4557d" dependencies = [ "anyhow", "brotli", @@ -6745,8 +7094,8 @@ dependencies = [ "serde_json", "serde_with", "swift-rs", - "thiserror 2.0.16", - "toml 0.9.5", + "thiserror 2.0.18", + "toml 0.9.12+spec-1.1.0", "url", "urlpattern", "uuid", @@ -6755,25 +7104,26 @@ dependencies = [ [[package]] name = "tauri-winres" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd21509dd1fa9bd355dc29894a6ff10635880732396aa38c0066c1e6c1ab8074" +checksum = "1087b111fe2b005e42dbdc1990fc18593234238d47453b0c99b7de1c9ab2c1e0" dependencies = [ + "dunce", "embed-resource", - "toml 0.9.5", + "toml 0.9.12+spec-1.1.0", ] [[package]] name = "tempfile" -version = "3.21.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.2", "once_cell", - "rustix 1.0.8", - "windows-sys 0.60.2", + "rustix 1.1.4", + "windows-sys 0.61.2", ] [[package]] @@ -6788,12 +7138,66 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.4.1" +name = "terminfo" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" dependencies = [ - "winapi-util", + "fnv", + "nom", + "phf 0.11.3", + "phf_codegen 0.11.3", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bitflags 2.11.1", + "fancy-regex", + "filedescriptor", + "finl_unicode", + "fixedbitset 0.4.2", + "hex", + "lazy_static", + "libc", + "log", + "memmem", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "phf 0.11.3", + "sha2 0.10.9", + "signal-hook", + "siphasher 1.0.2", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", ] [[package]] @@ -6807,11 +7211,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.18", ] [[package]] @@ -6822,18 +7226,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6847,30 +7251,33 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "itoa", "js-sys", + "libc", "num-conv", + "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -6878,9 +7285,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -6888,9 +7295,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -6903,39 +7310,37 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", + "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -6943,9 +7348,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -6955,9 +7360,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -6969,20 +7374,21 @@ dependencies = [ [[package]] name = "tokio-websockets" -version = "0.12.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5190767f03b86528ab9f4f6a9158072a6d0ef240d9a9591772eb411f315920f4" +checksum = "dad543404f98bfc969aeb71994105c592acfc6c43323fddcd016bb208d1c65cb" dependencies = [ "base64 0.22.1", "bytes", "futures-core", "futures-sink", - "getrandom 0.3.3", + "getrandom 0.4.2", "http", "httparse", - "rand 0.9.2", + "rand 0.10.1", "ring", "rustls-pki-types", + "sha1_smol", "simdutf8", "tokio", "tokio-rustls", @@ -6991,47 +7397,56 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.23" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_edit 0.22.27", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", ] [[package]] name = "toml" -version = "0.9.5" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap 2.11.0", - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow 0.7.13", + "winnow 0.7.15", ] [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" dependencies = [ - "serde", + "serde_core", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", ] [[package]] @@ -7040,55 +7455,56 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.11.0", - "toml_datetime 0.6.11", + "indexmap 2.14.0", + "toml_datetime 0.6.3", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ - "indexmap 2.11.0", - "toml_datetime 0.6.11", + "indexmap 2.14.0", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.3", "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.25.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" dependencies = [ - "indexmap 2.11.0", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "winnow 0.7.13", + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.2", ] [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 0.7.13", + "winnow 1.0.2", ] [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -7101,11 +7517,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.11.1", "bytes", "futures-util", "http", @@ -7131,9 +7547,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -7143,35 +7559,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -7185,9 +7591,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -7203,24 +7609,24 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.21.1" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d92153331e7d02ec09137538996a7786fe679c629c279e82a6be762b7e6fe2" +checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" dependencies = [ "crossbeam-channel", "dirs", "libappindicator", "muda", - "objc2 0.6.2", + "objc2", "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.1", + "objc2-foundation", "once_cell", "png", "serde", - "thiserror 2.0.16", - "windows-sys 0.59.0", + "thiserror 2.0.18", + "windows-sys 0.60.2", ] [[package]] @@ -7231,9 +7637,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tun-rs" -version = "2.7.7" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1842070c95f1e34f5563748c1218448899ea5ed9b76d8ba20b9c24b100f16f" +checksum = "a88c6aea62111e48fb67b733d6bbdc2019272e6d6f7108c9b0f4cd25d715d38a" dependencies = [ "blocking", "byteorder", @@ -7243,17 +7649,16 @@ dependencies = [ "getifaddrs", "ipnet", "libc", - "libloading 0.8.8", + "libloading 0.9.0", "log", - "mac_address", "netconfig-rs", - "nix 0.30.1", + "nix 0.31.2", "route_manager", "scopeguard", "tokio", "widestring", "windows-sys 0.61.2", - "winreg 0.55.0", + "winreg", ] [[package]] @@ -7264,19 +7669,25 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "ucd-trie" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uds_windows" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -7322,15 +7733,32 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" + +[[package]] +name = "unicode-truncate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" +dependencies = [ + "itertools", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "unicode-width" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -7344,17 +7772,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ - "crypto-common 0.1.6", - "subtle", -] - -[[package]] -name = "universal-hash" -version = "0.6.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" -dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.1.7", "subtle", ] @@ -7366,14 +7784,15 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -7394,21 +7813,34 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" + [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.18.1" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.3.3", + "atomic", + "getrandom 0.4.2", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] @@ -7418,11 +7850,65 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + +[[package]] +name = "vergen" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "vergen-lib 9.1.0", +] + +[[package]] +name = "vergen-gitcl" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9dfc1de6eb2e08a4ddf152f1b179529638bedc0ea95e6d667c014506377aefe" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", + "time", + "vergen", + "vergen-lib 0.1.6", +] + +[[package]] +name = "vergen-lib" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b07e6010c0f3e59fcb164e0163834597da68d1f864e2b8ca49f74de01e9c166" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + +[[package]] +name = "vergen-lib" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + [[package]] name = "version-compare" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" [[package]] name = "version_check" @@ -7450,6 +7936,15 @@ dependencies = [ "libc", ] +[[package]] +name = "vtparse" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +dependencies = [ + "utf8parse", +] + [[package]] name = "walkdir" version = "2.5.0" @@ -7482,58 +7977,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.3+wasi-0.2.4" +name = "wasip2" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] -name = "wasm-bindgen" -version = "0.2.100" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", + "wit-bindgen 0.51.0", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" +name = "wasm-bindgen" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -7541,26 +8029,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -7574,11 +8084,36 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.1", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", +] + [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -7640,36 +8175,27 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" -dependencies = [ - "webpki-root-certs 1.0.2", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.2" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] [[package]] name = "webview2-com" -version = "0.38.0" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ba622a989277ef3886dd5afb3e280e3dd6d974b766118950a08f8f678ad6a4" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" dependencies = [ "webview2-com-macros", "webview2-com-sys", @@ -7681,26 +8207,98 @@ dependencies = [ [[package]] name = "webview2-com-macros" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "webview2-com-sys" -version = "0.38.0" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36695906a1b53a3bf5c4289621efedac12b73eeb0b89e7e1a89b517302d5d75c" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ - "thiserror 2.0.16", + "thiserror 2.0.18", "windows 0.61.3", "windows-core 0.61.2", ] +[[package]] +name = "wezterm-bidi" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" +dependencies = [ + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +dependencies = [ + "getrandom 0.3.4", + "mac_address", + "sha2 0.10.9", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +dependencies = [ + "csscolorparser", + "deltae", + "lazy_static", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +dependencies = [ + "log", + "ordered-float", + "strsim", + "thiserror 1.0.69", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "lazy_static", + "serde", + "wezterm-dynamic", +] + [[package]] name = "which" version = "4.4.2" @@ -7715,9 +8313,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "winapi" @@ -7737,11 +8335,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7756,10 +8354,10 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c" dependencies = [ - "objc2 0.6.2", + "objc2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation", "raw-window-handle", "windows-sys 0.59.0", "windows-version", @@ -7864,7 +8462,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7875,7 +8473,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7910,6 +8508,17 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.3.4" @@ -7988,7 +8597,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] @@ -8048,19 +8657,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -8083,11 +8692,11 @@ dependencies = [ [[package]] name = "windows-version" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] @@ -8110,9 +8719,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -8134,9 +8743,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -8158,9 +8767,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -8170,9 +8779,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -8194,9 +8803,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -8218,9 +8827,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -8242,9 +8851,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -8266,9 +8875,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" @@ -8281,21 +8890,20 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] [[package]] -name = "winreg" -version = "0.50.0" +name = "winnow" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "memchr", ] [[package]] @@ -8310,39 +8918,127 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.45.0" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "wmi" -version = "0.17.2" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3de777dce4cbcdc661d5d18e78ce4b46a37adc2bb7c0078a556c7f07bcce2f" +checksum = "7c81b85c57a57500e56669586496bf2abd5cf082b9d32995251185d105208b64" dependencies = [ "chrono", "futures", "log", "serde", - "thiserror 2.0.16", - "windows 0.61.3", - "windows-core 0.61.2", + "thiserror 2.0.18", + "windows 0.62.2", + "windows-core 0.62.2", ] [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "wry" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f0e9642a0d061f6236c54ccae64c2722a7879ad4ec7dff59bd376d446d8e90" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" dependencies = [ "base64 0.22.1", - "block2 0.6.1", + "block2", "cookie", "crossbeam-channel", "dirs", @@ -8353,14 +9049,14 @@ dependencies = [ "html5ever", "http", "javascriptcore-rs", - "jni", + "jni 0.21.1", "kuchikiki", "libc", "ndk", - "objc2 0.6.2", + "objc2", "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation", "objc2-ui-kit", "objc2-web-kit", "once_cell", @@ -8369,7 +9065,7 @@ dependencies = [ "sha2 0.10.9", "soup3", "tao-macros", - "thiserror 2.0.16", + "thiserror 2.0.18", "url", "webkit2gtk", "webkit2gtk-sys", @@ -8393,12 +9089,21 @@ dependencies = [ "pharos", "rustc_version", "send_wrapper", - "thiserror 2.0.16", + "thiserror 2.0.18", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11" version = "2.21.0" @@ -8420,23 +9125,11 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek 4.1.3", - "rand_core 0.6.4", - "serde", - "zeroize", -] - [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmltree" @@ -8447,22 +9140,12 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -8470,13 +9153,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "synstructure", ] @@ -8488,9 +9171,9 @@ checksum = "2164e798d9e3d84ee2c91139ace54638059a3b23e361f5c11781c2c6459bde0f" [[package]] name = "zbus" -version = "5.10.0" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a073be99ace1adc48af593701c8015cd9817df372e14a1a6b0ee8f8bf043be" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" dependencies = [ "async-broadcast", "async-executor", @@ -8506,14 +9189,16 @@ dependencies = [ "futures-core", "futures-lite", "hex", - "nix 0.30.1", + "libc", "ordered-stream", + "rustix 1.1.4", "serde", "serde_repr", "tracing", "uds_windows", - "windows-sys 0.60.2", - "winnow 0.7.13", + "uuid", + "windows-sys 0.61.2", + "winnow 0.7.15", "zbus_macros", "zbus_names", "zvariant", @@ -8521,14 +9206,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.10.0" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e80cd713a45a49859dcb648053f63265f4f2851b6420d47a958e5697c68b131" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" dependencies = [ - "proc-macro-crate 3.3.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "zbus_names", "zvariant", "zvariant_utils", @@ -8536,54 +9221,53 @@ dependencies = [ [[package]] name = "zbus_names" -version = "4.2.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" dependencies = [ "serde", - "static_assertions", - "winnow 0.7.13", + "winnow 0.7.15", "zvariant", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "synstructure", ] @@ -8598,20 +9282,20 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -8620,9 +9304,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -8631,51 +9315,57 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zvariant" -version = "5.7.0" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999dd3be73c52b1fccd109a4a81e4fcd20fab1d3599c8121b38d04e1419498db" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" dependencies = [ "endi", "enumflags2", "serde", - "winnow 0.7.13", + "winnow 0.7.15", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "5.7.0" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6643fd0b26a46d226bd90d3f07c1b5321fe9bb7f04673cb37ac6d6883885b68e" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" dependencies = [ - "proc-macro-crate 3.3.0", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.106", - "winnow 0.7.13", + "syn 2.0.117", + "winnow 0.7.15", ] diff --git a/ui/src-tauri/Cargo.toml b/ui/src-tauri/Cargo.toml index 0124c49..0f154a4 100644 --- a/ui/src-tauri/Cargo.toml +++ b/ui/src-tauri/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/rustonbsd/iroh-lan" readme = "README.md" keywords = ["networking"] categories = ["network-programming"] -version = "0.1.2" +version = "1.0.0-debug.9" edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -25,10 +25,11 @@ tauri-build = { version = "2", features = [] } [dependencies] tauri = { version = "~2.8", features = [] } tauri-plugin-opener = "2" +tauri-plugin-log = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" -iroh-lan = { path = "../../../iroh-lan" } +iroh-lan = { path = "../../" } once_cell = "1" tokio = { version = "1", features = ["sync", "rt", "macros"] } self-runas = "0.1.0" @@ -36,7 +37,6 @@ anyhow = "1" tracing = { version = "0.1", default-features = false, features = ["std"] } -tracing-subscriber = { version = "0.3", features = ["env-filter"] } [profile.release] opt-level = "z" diff --git a/ui/src-tauri/src/lib.rs b/ui/src-tauri/src/lib.rs index 0e19c45..d8e3905 100644 --- a/ui/src-tauri/src/lib.rs +++ b/ui/src-tauri/src/lib.rs @@ -1,21 +1,14 @@ -use iroh_lan::network::Network; +use iroh_lan::Network; use once_cell::sync::Lazy; use serde::Serialize; +use tauri_plugin_log::log; use tokio::sync::Mutex; -use tracing::{self, info}; +use tracing::info; // Re-export lib so main.rs can call run() // Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ -static NETWORK: Lazy>> = Lazy::new(|| { - #[cfg(debug_assertions)] - tracing_subscriber::fmt() - .with_max_level(tracing::Level::INFO) - .with_thread_ids(true) - .init(); - - Mutex::new(None) -}); +static NETWORK: Lazy>> = Lazy::new(|| Mutex::new(None)); #[derive(Debug, Serialize)] pub enum Status { @@ -53,6 +46,10 @@ impl MyInfo { Some(format!("acquiring {}...", ip_candidate.ip)) } iroh_lan::RouterIp::AssignedIp(ipv4_addr) => Some(format!("{ipv4_addr}")), + iroh_lan::RouterIp::VerifyingIp(ipv4_addr, instant) => Some(format!( + "verifying {ipv4_addr} ({}s)", + instant.elapsed().as_secs() + )), }, }) } @@ -96,12 +93,12 @@ async fn connection_state() -> Result { let guard = NETWORK.lock().await; if let Some(network) = guard.as_ref() { // peer count - let peers = network - .get_peers() + let peers = network.get_peers().await.map_err(|e| e.to_string())?; + + let router = network + .get_router_handle() .await .map_err(|e| e.to_string())?; - - let router = network.get_router_handle().await.map_err(|e| e.to_string())?; let ip_state = router.get_ip_state().await.map_err(|e| e.to_string())?; let (ip, raw_ip_state) = match ip_state { iroh_lan::RouterIp::NoIp => (None, "NoIp".to_string()), @@ -109,7 +106,16 @@ async fn connection_state() -> Result { Some(format!("acquiring {}...", candidate.ip)), "AquiringIp".to_string(), ), - iroh_lan::RouterIp::AssignedIp(addr) => (Some(addr.to_string()), "AssignedIp".to_string()), + iroh_lan::RouterIp::AssignedIp(addr) => { + (Some(addr.to_string()), "AssignedIp".to_string()) + } + iroh_lan::RouterIp::VerifyingIp(addr, instant) => ( + Some(format!( + "verifying {addr} ({}s)", + instant.elapsed().as_secs() + )), + "VerifyingIp".to_string(), + ), }; Ok(ConnectionState { @@ -138,11 +144,18 @@ async fn my_info() -> Result { async fn list_peers() -> Result, String> { let guard = NETWORK.lock().await; if let Some(network) = guard.as_ref() { - let direct_handle = network.get_direct_handle().await.map_err(|e| e.to_string())?; + let direct_handle = network + .get_direct_handle() + .await + .map_err(|e| e.to_string())?; let peers = network.get_peers().await.map_err(|e| e.to_string())?; let mut peer_infos = vec![]; for peer in peers { - let status = direct_handle.get_conn_state(peer.0).await.map_err(|e| e.to_string()).unwrap_or(iroh_lan::ConnState::Idle); + let status = direct_handle + .get_peer_state(peer.0) + .await + .map_err(|e| e.to_string()) + .unwrap_or(iroh_lan::InnerConnState::Closed); peer_infos.push(PeerInfo { node_id: peer.0.to_string(), ip: match peer.1 { @@ -150,11 +163,9 @@ async fn list_peers() -> Result, String> { None => "unknown".to_string(), }, status: match status { - iroh_lan::ConnState::Connecting => Status::Disconnected, - iroh_lan::ConnState::Idle => Status::Active, - iroh_lan::ConnState::Open => Status::Active, - iroh_lan::ConnState::Disconnected => Status::Disconnected, - iroh_lan::ConnState::Closed => Status::Disconnected, + iroh_lan::InnerConnState::Connecting => Status::Disconnected, + iroh_lan::InnerConnState::Open => Status::Active, + iroh_lan::InnerConnState::Closed => Status::Disconnected, }, }); } @@ -174,7 +185,7 @@ async fn close(window: tauri::Window) -> Result<(), String> { network.close().await.map_err(|e| e.to_string())?; } *guard = None; // drop - + window.close().map_err(|e| e.to_string())?; Ok(()) @@ -184,13 +195,22 @@ async fn close(window: tauri::Window) -> Result<(), String> { pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) + .plugin( + tauri_plugin_log::Builder::default() + .filter(|metadata| { + matches!( + metadata.target(), + "iroh_lan::connection" | "iroh_lan::direct_connect" | "iroh_lan::router" + ) && metadata.level() <= log::Level::Debug + }) + .build(), + ) .invoke_handler(tauri::generate_handler![ my_info, list_peers, connection_state, close, create_network, - ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/ui/src-tauri/src/main.rs b/ui/src-tauri/src/main.rs index d0de30c..7872e92 100644 --- a/ui/src-tauri/src/main.rs +++ b/ui/src-tauri/src/main.rs @@ -2,10 +2,16 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use std::process::exit; -fn main() { +#[tokio::main] +async fn main() { if !self_runas::is_elevated() { let _ = self_runas::admin(); exit(0); } + + if std::env::args_os().len() > 1 && iroh_lan::cli::run_cli().await.is_ok() { + return; + } + iroh_lan_lib::run() } diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 2a60df5..1913b75 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -89,13 +89,14 @@ export default function App() { if (state.peers === 0) { pushMessage("Looking for at least one peer to connect to…"); } else { - pushMessage(`Found ${state.peers} peer${state.peers === 1 ? "" : "s"}`); + pushMessage(`Found ${state.peers} peer record${state.peers === 1 ? "" : "s"}`); } } if (state.raw_ip_state !== lastRawState) { lastRawState = state.raw_ip_state; if (state.raw_ip_state === "NoIp") pushMessage("No IP yet"); if (state.raw_ip_state === "AquiringIp") pushMessage("Acquiring IP…"); + if (state.raw_ip_state === "VerifyingIp") pushMessage("Verifying IP…"); if (state.raw_ip_state === "AssignedIp") pushMessage("Acquired IP"); } if (state.ip && state.raw_ip_state === "AssignedIp") {