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..3c6595b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ target # Added by cargo /target -.DS_Store \ No newline at end of file +.DS_Store + +docker_test/results_* \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e55b5ee..d3870e1 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" @@ -107,14 +75,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" @@ -139,19 +154,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 +168,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -180,6 +182,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" @@ -215,9 +226,9 @@ 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", @@ -225,92 +236,56 @@ dependencies = [ ] [[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" +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.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[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 +299,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.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", ] [[package]] @@ -346,16 +329,16 @@ 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 = "bytemuck" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -365,9 +348,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", ] @@ -389,15 +372,25 @@ checksum = "3b457277798202ccd365b9c112ebee08ddd57f1033916c8b8ea52f222e5b715d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", +] + +[[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.33" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ + "find-msvc-tools", "shlex", ] @@ -409,9 +402,9 @@ 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" @@ -421,97 +414,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", + "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.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 +518,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" @@ -534,21 +543,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 +607,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" @@ -641,77 +662,77 @@ 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", + "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.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" 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 +742,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", @@ -755,87 +776,206 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] -name = "data-encoding" -version = "2.9.0" +name = "darling" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] [[package]] -name = "der" -version = "0.7.10" +name = "darling" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "const-oid 0.9.6", - "zeroize", + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] -name = "der" -version = "0.8.0-rc.9" +name = "darling_core" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ - "const-oid 0.10.1", - "pem-rfc7468", - "zeroize", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", ] [[package]] -name = "deranged" -version = "0.4.0" +name = "darling_core" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" dependencies = [ - "powerfmt", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", ] [[package]] -name = "derive_more" -version = "1.0.0" +name = "darling_macro" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "derive_more-impl 1.0.0", + "darling_core 0.20.11", + "quote", + "syn 2.0.117", ] [[package]] -name = "derive_more" -version = "2.0.1" +name = "darling_macro" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "derive_more-impl 2.0.1", + "darling_core 0.23.0", + "quote", + "syn 2.0.117", ] [[package]] -name = "derive_more-impl" -version = "1.0.0" +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + +[[package]] +name = "data-encoding-macro" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" +dependencies = [ + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.106", - "unicode-xid", + "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 = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version", + "syn 2.0.117", "unicode-xid", ] +[[package]] +name = "dht" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf85ef918f33294d98b8833ab7bd095700480b095295b275d36c8fdd86daafdd" +dependencies = [ + "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]] name = "diatomic-waker" version = "0.2.3" @@ -849,61 +989,49 @@ 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]] -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.11.1", + "block2", + "libc", + "objc2", ] [[package]] -name = "distributed-topic-tracker" +name = "displaydoc" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c1ed9a2484b742d78d0a1e1cc93cbc1a5de784e1138a2e69414851a9fe39bc" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 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.117", ] [[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 +1040,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,9 +1055,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", @@ -938,57 +1066,26 @@ 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 = "embedded-io" version = "0.4.0" @@ -1011,15 +1108,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.117", ] [[package]] @@ -1030,12 +1126,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 +1165,34 @@ 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 = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] [[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 0.2.0", + "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 +1207,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,7 +1250,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", ] @@ -1111,6 +1271,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" @@ -1119,18 +1285,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,9 +1309,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", @@ -1156,9 +1322,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", @@ -1166,30 +1332,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 +1362,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 +1381,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", @@ -1252,53 +1416,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.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" dependencies = [ "cc", "cfg-if", "libc", "log", "rustversion", - "windows 0.61.3", + "windows-link 0.2.1", + "windows-result 0.4.1", ] [[package]] @@ -1309,44 +1442,59 @@ 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", + "bitflags 2.11.1", "libc", "windows-sys 0.59.0", ] [[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.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.2+wasi-0.2.4", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", "wasm-bindgen", ] @@ -1360,12 +1508,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 +1526,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.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -1428,16 +1559,30 @@ 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]] @@ -1467,28 +1612,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.15", + "thiserror 2.0.18", "tinyvec", "tokio", "tokio-rustls", @@ -1496,24 +1640,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.15", + "system-configuration", + "thiserror 2.0.18", "tokio", "tokio-rustls", "tracing", @@ -1539,42 +1708,20 @@ 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]] 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", ] @@ -1615,23 +1762,23 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hybrid-array" -version = "0.4.5" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +checksum = "08d46837a0ed51fe95bd3b05de33cd64a1ee88fc797477ca48446872504507c5" dependencies = [ "typenum", - "zeroize", ] [[package]] name = "hyper" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -1646,31 +1793,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 +1823,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2", "tokio", "tower-service", "tracing", @@ -1687,9 +1831,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 +1841,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -1711,12 +1855,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 +1869,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 +1882,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 +1896,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 +1935,29 @@ 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.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", "smallvec", @@ -1818,11 +1976,10 @@ dependencies = [ [[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", @@ -1831,7 +1988,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.9.2", + "rand 0.10.1", "tokio", "url", "xmltree", @@ -1839,87 +1996,74 @@ 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.0", + "serde", + "serde_core", ] [[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.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", @@ -1927,48 +2071,49 @@ dependencies = [ [[package]] name = "iroh" -version = "0.95.1" +version = "0.98.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2374ba3cdaac152dc6ada92d971f7328e6408286faab3b7350842b2ebbed4789" +checksum = "9382a37668c84823e94b52eee462b3133ca7252a28de5f619a989d48b69cb30b" 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.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", + "rand 0.10.1", "reqwest", + "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", @@ -1977,120 +2122,74 @@ 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=70c7bca92bae179212fe6088105ca3025490fff4#70c7bca92bae179212fe6088105ca3025490fff4" +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", + "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", "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", - "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", "ed25519-dalek", "futures-concurrency", "futures-lite", @@ -2104,43 +2203,37 @@ 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", "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", @@ -2149,18 +2242,20 @@ dependencies = [ "tracing", "tracing-subscriber", "tun-rs", + "url", "z32", ] [[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", @@ -2169,149 +2264,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", "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.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", + "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", + "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", + "rand 0.10.1", "reqwest", "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=58320f1d3e6c46cc0e6bfce9e1c8f0f79a92a94a#58320f1d3e6c46cc0e6bfce9e1c8f0f79a92a94a" dependencies = [ - "data-encoding", - "derive_more 2.0.1", - "iroh-base", - "n0-error", - "postcard", - "serde", -] - -[[package]] -name = "irpc" -version = "0.11.0" + "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.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", @@ -2319,20 +2363,35 @@ 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]] +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,49 +2402,141 @@ 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 = "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 = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +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", ] +[[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" 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 = "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.11.1", ] [[package]] @@ -2396,37 +2547,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.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "loom" @@ -2449,11 +2599,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]] @@ -2462,6 +2621,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" @@ -2474,40 +2639,46 @@ 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.15", + "thiserror 2.0.18", "tracing", ] [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[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" @@ -2519,49 +2690,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.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" 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 = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d5969a2f40e9d9ed121a789c415f4114ac2b28e5731c080bdefee217d3b3fb" +checksum = "af4782b4baf92d686d161c15460c83d16ebcfd215918763903e9619842665cae" dependencies = [ "anyhow", "n0-error-macros", @@ -2570,23 +2737,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", "futures-buffered", "futures-lite", "futures-util", @@ -2601,145 +2768,133 @@ 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", "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 = "nested_enum_utils" -version = "0.2.2" +name = "ndk-context" +version = "0.1.1" 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.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ab878b4c90faf36dab10ea51d48c69ae9019bcca47c048a7c9b273d5d7a823" +checksum = "e30af1a5073b82356d9317c18226826370b4288eba2f71c7e84e18bae51b3847" dependencies = [ + "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", - "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", + "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]] @@ -2751,19 +2906,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 +2926,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", "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", @@ -2809,7 +2966,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags", + "bitflags 2.11.1", "cfg-if", "cfg_aliases", "libc", @@ -2822,7 +2979,20 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags", + "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", @@ -2836,35 +3006,104 @@ 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 = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b969bd157c3bd3bab239a1a8b14f67f2033fa012770367fcbd5b42d71ae3548" +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 = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdec6f5039d98ee5377b2f532d495a555eb664c53161b1b5780dcaeac678b60e" +dependencies = [ + "aes-gcm", + "bytes", + "derive_more", + "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.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.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" @@ -2877,9 +3116,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 +3126,94 @@ 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.117", ] [[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.11.1", + "block2", + "dispatch2", + "libc", + "objc2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-security" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a" +dependencies = [ + "bitflags 2.11.1", + "objc2", + "objc2-core-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.11.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 +3222,27 @@ 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 = "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,105 +3253,184 @@ 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 = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link 0.2.1", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem-rfc7468" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" +dependencies = [ + "base64ct", +] + +[[package]] +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.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 = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ - "lock_api", - "parking_lot_core", + "pest", + "sha2 0.10.9", ] [[package]] -name = "parking_lot_core" -version = "0.9.11" +name = "pharos" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", + "futures", + "rustc_version", ] [[package]] -name = "paste" -version = "1.0.15" +name = "phf" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] [[package]] -name = "pem" -version = "3.0.5" +name = "phf_codegen" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "base64", - "serde", + "phf_generator", + "phf_shared", ] [[package]] -name = "pem-rfc7468" -version = "1.0.0-rc.3" +name = "phf_generator" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "base64ct", + "phf_shared", + "rand 0.8.6", ] [[package]] -name = "percent-encoding" -version = "2.3.1" +name = "phf_macros" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "pharos" -version = "0.5.3" +name = "phf_shared" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "futures", - "rustc_version", + "siphasher", ] [[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", @@ -3058,44 +3438,26 @@ dependencies = [ ] [[package]] -name = "pkarr" -version = "5.0.0" +name = "pkcs8" +version = "0.11.0-rc.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "792c1328860f6874e90e3b387b4929819cc7783a6bd5a4728e918706eb436a48" +checksum = "12922b6296c06eb741b02d7b5161e3aaa22864af38dfa025a1a3ba3f68c84577" 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.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ - "der 0.8.0-rc.9", - "spki", + "base64", + "indexmap", + "quick-xml", + "serde", + "time", ] [[package]] @@ -3116,7 +3478,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3140,27 +3502,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,26 +3509,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", "bytes", - "derive_more 2.0.1", + "derive_more", "futures-lite", "futures-util", "hyper-util", @@ -3197,10 +3541,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", @@ -3209,16 +3553,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 +3575,14 @@ checksum = "e0232bd009a197ceec9cc881ba46f727fcd8060a2d8d6a9dde7a69030a6fe2bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[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 +3603,58 @@ dependencies = [ ] [[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "proc-macro-crate" -version = "3.3.0" +name = "prefix-trie" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "23370be78b7e5bcbb0cab4a02047eb040279a693c78daad04c2c5f1c24a83503" dependencies = [ - "toml_edit", + "either", + "ipnet", + "num-traits", ] [[package]] -name = "proc-macro-error" -version = "0.4.12" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "proc-macro-error-attr", "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "syn 2.0.117", ] [[package]] -name = "proc-macro-error-attr" -version = "0.4.12" +name = "proc-macro-crate" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "syn-mid", - "version_check", + "toml_edit", ] -[[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.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" 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.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3397,35 +3665,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.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ - "libc", - "rand_chacha 0.3.1", "rand_core 0.6.4", ] [[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_chacha", + "rand_core 0.9.5", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "rand" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -3435,7 +3708,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 +3717,152 @@ 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 = "range-collections" -version = "0.4.6" +name = "rand_core" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861706ea9c4aded7584c5cd1d241cec2ea7f5f50999f236c22b65409a1f1a0d0" -dependencies = [ - "binary-merge", - "inplace-vec-builder", - "ref-cast", - "serde", - "smallvec", -] +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] -name = "rcgen" -version = "0.14.5" +name = "ratatui" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fae430c6b28f1ad601274e78b7dffa0546de0b73b4cd32f46723c0c2a16f7a5" +checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" dependencies = [ - "pem", - "ring", - "rustls-pki-types", - "time", - "yasna", + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termwiz", + "ratatui-widgets", ] [[package]] -name = "redb" -version = "2.6.3" +name = "ratatui-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eca1e9d98d5a7e9002d0013e18d5a9b000aee942eb134883a82f06ebffb6c01" +checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ - "libc", + "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 = "redox_syscall" -version = "0.5.17" +name = "ratatui-crossterm" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" dependencies = [ - "bitflags", + "cfg-if", + "crossterm", + "instability", + "ratatui-core", ] [[package]] -name = "ref-cast" -version = "1.0.24" +name = "ratatui-macros" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" dependencies = [ - "ref-cast-impl", + "ratatui-core", + "ratatui-widgets", ] [[package]] -name = "ref-cast-impl" -version = "1.0.24" +name = "ratatui-termwiz" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "ratatui-core", + "termwiz", ] [[package]] -name = "reflink-copy" -version = "0.1.27" +name = "ratatui-widgets" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd34aed05de14a9001009dbffc2a6843095dcd8fe3d1207016192717a449d218" +checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" dependencies = [ - "cfg-if", - "libc", - "rustix 1.0.8", - "windows 0.62.2", + "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 = "regex" -version = "1.11.1" +name = "redox_syscall" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "bitflags 2.11.1", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "regex" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ - "regex-syntax 0.6.29", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" 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.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.12.23" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" dependencies = [ "base64", "bytes", @@ -3596,12 +3878,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 +3893,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 +3909,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -3639,16 +3917,16 @@ dependencies = [ [[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]] @@ -3675,17 +3953,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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -3702,7 +3974,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3711,22 +3983,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.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", @@ -3739,9 +4011,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", @@ -3751,9 +4023,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -3761,13 +4033,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", @@ -3776,8 +4048,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 +4060,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", @@ -3805,19 +4077,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" @@ -3830,11 +4092,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 +4112,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.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3877,14 +4135,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" @@ -3895,19 +4163,13 @@ dependencies = [ "nix 0.30.1", "runas-with-inherited-cmd", "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 +4187,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 +4199,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 +4224,43 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 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", "itoa", "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] -name = "serdect" -version = "0.4.1" +name = "serde_with" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f" dependencies = [ - "base16ct 0.3.0", - "serde", + "serde_core", + "serde_with_macros", ] [[package]] -name = "sha1" -version = "0.11.0-rc.2" +name = "serde_with_macros" +version = "3.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e046edf639aa2e7afb285589e5405de2ef7e61d4b0ac1e30256e3eab911af9" +checksum = "d3db8978e608f1fe7357e211969fd9abdcae80bac1ba7a3369bb7eb6b404eb65" dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-rc.3", + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -4031,19 +4276,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]] @@ -4061,20 +4306,52 @@ 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 = "7f1880df446116126965eeec169136b2e0251dba37c6223bcc819569550edea3" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] name = "simdutf8" @@ -4088,14 +4365,20 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ - "bitflags", + "bitflags 2.11.1", ] +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +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" @@ -4107,45 +4390,31 @@ dependencies = [ ] [[package]] -name = "snafu" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320b01e011bf8d5d7a4a4a4be966d9160968935849c83b918827f6a435e7f627" -dependencies = [ - "backtrace", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.6" +name = "socket2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" 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", + "rand_core 0.6.4", + "sha2 0.10.9", ] [[package]] @@ -4156,7 +4425,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4176,28 +4445,31 @@ checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" [[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 = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" @@ -4208,29 +4480,37 @@ dependencies = [ "strum_macros 0.27.2", ] +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "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", "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", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4252,26 +4532,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" @@ -4289,28 +4558,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", + "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]] @@ -4330,25 +4589,66 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] -name = "tempfile" -version = "3.21.0" +name = "terminfo" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" dependencies = [ - "fastrand", - "getrandom 0.3.3", - "once_cell", - "rustix 1.0.8", - "windows-sys 0.60.2", + "fnv", + "nom", + "phf", + "phf_codegen", ] [[package]] -name = "termcolor" -version = "1.4.1" +name = "termios" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" dependencies = [ - "winapi-util", + "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.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", + "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 +4662,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,18 +4677,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[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.117", ] [[package]] @@ -4402,29 +4702,43 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +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.4" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +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 +4746,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -4447,39 +4761,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", @@ -4487,9 +4799,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 +4811,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 +4825,21 @@ dependencies = [ [[package]] name = "tokio-websockets" -version = "0.12.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f29ba084eb43becc9864ba514b4a64f5f65b82f9a6ffbafa5436c1c80605f03" +checksum = "dad543404f98bfc969aeb71994105c592acfc6c43323fddcd016bb208d1c65cb" dependencies = [ "base64", "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", @@ -4535,26 +4848,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 = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] [[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", "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ "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,11 +4893,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", + "bitflags 2.11.1", "bytes", "futures-util", "http", @@ -4597,9 +4923,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 +4935,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" @@ -4651,14 +4967,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,9 +4991,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", @@ -4689,52 +5005,70 @@ dependencies = [ "libc", "libloading", "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]] 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 = "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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[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 +5080,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 +5097,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.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ - "getrandom 0.3.3", + "atomic", + "getrandom 0.4.2", "js-sys", "wasm-bindgen", ] @@ -4777,7 +5119,55 @@ dependencies = [ name = "valuable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +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 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_check" @@ -4785,6 +5175,15 @@ 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 +5210,51 @@ 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.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen-rt", + "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", @@ -4870,31 +5262,53 @@ 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", + "wasm-encoder", + "wasmparser", +] + [[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", @@ -4903,11 +5317,23 @@ dependencies = [ "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", + "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", @@ -4925,29 +5351,92 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "0.26.11" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" 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.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ffd8df1c57e87c325000a3d6ef93db75279dc3a231125aac571650f22b12a" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" 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 +5453,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 +5475,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 +5587,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5109,7 +5598,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5144,6 +5633,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 +5716,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 +5764,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 +5807,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 +5825,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 +5843,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 +5867,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 +5885,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 +5903,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 +5921,139 @@ 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.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.50.0" +version = "0.55.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] -name = "winreg" -version = "0.55.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5a765337c50e9ec252c2069be9bf91c7df47afb103b642ba3a53bf8101be97" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ - "cfg-if", - "windows-sys 0.59.0", + "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", + "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", + "indexmap", + "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", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ - "bitflags", + "anyhow", + "id-arena", + "indexmap", + "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.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 +6068,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 +6089,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", @@ -5623,13 +6102,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", ] @@ -5641,42 +6120,42 @@ checksum = "2164e798d9e3d84ee2c91139ace54638059a3b23e361f5c11781c2c6459bde0f" [[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", ] @@ -5691,20 +6170,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", @@ -5713,9 +6192,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 +6203,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.117", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index 98717c3..1e2827f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,25 +7,23 @@ 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 = { git = "https://github.com/rustonbsd/iroh-topic-tracker", rev="58320f1d3e6c46cc0e6bfce9e1c8f0f79a92a94a" } +ed25519-dalek = "3.0.0-pre.6" +iroh = { version="0.98.1", features=["address-lookup-pkarr-dht", "qlog", "tls-ring"] } +iroh-gossip = "0.98.0" runas = "1" tokio = "1" -nix = { version = "0.30", features = ["process"] } +nix = { version = "0.31", 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" postcard = { version = "1", features = ["use-std"] } @@ -33,21 +31,32 @@ 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 = "0.6" -actor-helper = "0.2" - +iroh-auth = { git="https://github.com/rustonbsd/iroh-auth", rev="70c7bca92bae179212fe6088105ca3025490fff4" } +actor-helper = { version="0.3.0", features=["anyhow", "tokio"]} #{ git = "https://github.com/rustonbsd/actor-helper", rev="9af542cc2d26354dcc4d87d270408326aa319397", features=["anyhow", "tokio"] } +clap = { version = "4.6", features = ["derive"] } +ratatui = "0.30.0" +crossterm = "0.29.0" +noq = { version = "0.18" } +url = "2" +iroh-relay = "0.98" [lib] path = "src/lib.rs" crate-type = ["lib"] bench = false +[[bin]] +name = "iroh-lan" +path = "src/bin/cli.rs" + [[example]] name = "participant" path = "examples/participant.rs" crate-type = ["bin"] -[[example]] -name = "creator" -path = "examples/creator.rs" -crate-type = ["bin"] + +[patch.crates-io] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3fd3d5f --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +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 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..7ed235d --- /dev/null +++ b/docker_test/entrypoint_reliability.sh @@ -0,0 +1,524 @@ +#!/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}" +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" + /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 "AssignedIp(" "$logfile" 2>/dev/null | tail -n1 | sed -n 's/.*AssignedIp(\([0-9.]*\)).*/\1/p' || true) + if [ -n "$ip" ]; then + MY_IP="$ip" + echo "[node${NODE_INDEX}] AssignedIp=$MY_IP" + return 0 + fi + sleep 1 + done + + echo "[node${NODE_INDEX}] timeout waiting AssignedIp" + 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" + +NETEM_DELAY_MS=200 +NETEM_JITTER_MS=150 +NETEM_LOSS="gemodel 3% 20% 100% 0%" +NETEM_RATE=512kbit +NETEM_REORDER_PCT=5 +NETEM_DUP_PCT=2 +NETEM_CORRUPT_PCT=0.3 +NETEM_SLOT="" + +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 + jitter (normal distribution) + if [[ -n "$NETEM_DELAY_MS" ]]; then + cmd+=" delay ${NETEM_DELAY_MS}ms" + [[ -n "$NETEM_JITTER_MS" ]] && \ + cmd+=" ${NETEM_JITTER_MS}ms distribution normal" + fi + + # Loss — supports both "gemodel p h k ..." and plain "%" + # Use NETEM_LOSS for gemodel, NETEM_LOSS_PCT for simple + if [[ -n "$NETEM_LOSS" ]]; then + cmd+=" loss ${NETEM_LOSS}" + elif [[ -n "$NETEM_LOSS_PCT" ]]; then + cmd+=" loss ${NETEM_LOSS_PCT}%" + fi + + # Reorder + if [[ -n "$NETEM_REORDER_PCT" ]]; then + cmd+=" reorder ${NETEM_REORDER_PCT}%" + [[ -n "$NETEM_REORDER_CORR" ]] && \ + cmd+=" ${NETEM_REORDER_CORR}%" + fi + + # Duplicate + [[ -n "$NETEM_DUP_PCT" ]] && \ + cmd+=" duplicate ${NETEM_DUP_PCT}%" + + # Corrupt + [[ -n "$NETEM_CORRUPT_PCT" ]] && \ + cmd+=" corrupt ${NETEM_CORRUPT_PCT}%" + + # Rate limiting + [[ -n "$NETEM_RATE" ]] && \ + cmd+=" rate ${NETEM_RATE}" + + # Slot (periodic outage windows) + [[ -n "$NETEM_SLOT" ]] && \ + cmd+=" slot ${NETEM_SLOT}" + + 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..2baaa34 --- /dev/null +++ b/examples/mesh_check.rs @@ -0,0 +1,224 @@ +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}; + +#[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), + } + } +} + +#[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 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); + } + } 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; + } + 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); + } + } + } + } + _ = 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/src/bin/cli.rs b/src/bin/cli.rs new file mode 100644 index 0000000..17e83ae --- /dev/null +++ b/src/bin/cli.rs @@ -0,0 +1,141 @@ +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 + + /* + let last_tokio_tick = Arc::new(AtomicU64::new(0)); + let tick_for_watchdog = last_tokio_tick.clone(); + + std::thread::Builder::new() + .name("watchdog".to_string()) + .spawn(move || { + loop { + std::thread::sleep(std::time::Duration::from_secs(3)); + let tokio_tick = tick_for_watchdog.load(Ordering::Relaxed); + let now = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(); + let ago = if tokio_tick > 0 { + now.saturating_sub(tokio_tick) + } else { + 0 + }; + eprintln!( + "[WATCHDOG] {} | tokio_tick={}s_ago", + std::fs::read_to_string("/proc/self/status") + .unwrap_or_default() + .lines() + .find(|l| l.starts_with("Threads:")) + .unwrap_or("Threads: ?"), + ago, + ); + + // When freeze detected, capture full backtraces via GDB + if ago > 10 { + eprintln!("\n[FREEZE DETECTED] tokio_tick={}s_ago\n", ago); + let pid = std::process::id(); + + // GDB output goes to a FILE (not pipe) to avoid deadlock: + // GDB ptrace-stops ALL threads including this watchdog. + // With pipe: GDB fills 64KB buffer, blocks on write, watchdog + // can't read (stopped) → deadlock. Files have no such limit. + let bt_path = "/app/results/gdb_bt.txt"; + eprintln!("[FREEZE] Running GDB (output → {bt_path})..."); + + let gdb_result = std::fs::File::create(bt_path).and_then(|outfile| { + let errfile = outfile.try_clone()?; + std::process::Command::new("gdb") + .args([ + "-batch", + "-ex", "thread apply all bt", + "-p", &pid.to_string(), + ]) + .stdout(outfile) + .stderr(errfile) + .spawn() + }); + + match gdb_result { + Ok(mut child) => { + // GDB will ptrace-stop us, generate backtraces, + // write to file, detach, then we resume here. + match child.wait() { + Ok(s) => eprintln!("[FREEZE] GDB exited: {s}"), + Err(e) => eprintln!("[FREEZE] GDB wait err: {e}"), + } + // Print the captured backtraces + if let Ok(bt) = std::fs::read_to_string(bt_path) { + eprintln!("{bt}"); + } + } + Err(e) => { + eprintln!("[FREEZE] GDB failed ({e}), falling back to /proc"); + if let Ok(entries) = std::fs::read_dir(format!("/proc/{pid}/task")) { + for entry in entries.flatten() { + let tid = entry.file_name(); + let tid = tid.to_string_lossy(); + let comm = std::fs::read_to_string( + format!("/proc/{pid}/task/{tid}/comm") + ).unwrap_or_default(); + let wchan = std::fs::read_to_string( + format!("/proc/{pid}/task/{tid}/wchan") + ).unwrap_or_default(); + let syscall = std::fs::read_to_string( + format!("/proc/{pid}/task/{tid}/syscall") + ).unwrap_or_default(); + eprintln!( + "=== tid={tid} name={} wchan={} syscall={} ===", + comm.trim(), wchan.trim(), syscall.trim() + ); + } + } + } + } + + eprintln!("\n[FREEZE DUMP COMPLETE]"); + std::process::exit(99); + } + } + }) + .ok(); + + std::panic::set_hook(Box::new(|info| { + eprintln!("[PANIC] {}", info); + eprintln!("[PANIC] {:?}", std::backtrace::Backtrace::force_capture()); + })); + + let tick_for_tokio = last_tokio_tick.clone(); + + tokio::runtime::Builder::new_multi_thread() + .worker_threads(WORKERS) + .thread_name("iroh-worker") + .enable_all() + .build() + .unwrap() + .block_on(async { + let tick = tick_for_tokio; + tokio::spawn(async move { + loop { + tick.store( + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_secs(), + Ordering::Relaxed, + ); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + } + }); + iroh_lan::cli::run_cli().await + }) + */ +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..62bcb4e --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,384 @@ +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::{Network, RouterIp}; + +#[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, +} + +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::connection=debug,iroh_lan::direct_connect=debug,iroh_lan::router=debug,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).await?; + } else { + run_tui(args.name, args.password).await?; + } + + Ok(()) +} + +async fn run_headless(name: String, password: String, qlog_dir: 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).await?; + println!("Waiting for IP assignment..."); + + loop { + if let Ok(RouterIp::AssignedIp(ip)) = network.get_router_state().await { + println!("My IP is {}", ip); + break; + } + sleep(std::time::Duration::from_millis(500)).await; + } + + let mut known_peers: HashSet = HashSet::new(); + let mut lost_peers: HashSet = 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 new_peers: Vec<_> = peers + .iter() + .filter(|(id, ip)| ip.is_some() && !known_peers.contains(id)) + .collect(); + for (id, ip) in new_peers { + known_peers.insert(*id); + if lost_peers.contains(id) { + lost_peers.remove(id); + } + println!("Peer connected: {} ({})", ip.unwrap_or(Ipv4Addr::UNSPECIFIED), id); + } + let newly_lost_peers: Vec<_> = known_peers + .iter() + .filter(|id| !peers.iter().any(|(pid, _)| pid == *id)) + .cloned() + .collect(); + for id in newly_lost_peers { + lost_peers.insert(id); + if known_peers.contains(&id) { + known_peers.remove(&id); + } + 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) -> 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).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, state: &mut AppState) -> Result<()> { + // Node ID + if state.node_id.is_none() + && let Ok(id) = network.get_node_id().await + { + state.node_id = Some(id); + } + + // Router State (IP and Status) + match network.get_router_state().await { + Ok(RouterIp::NoIp) => { + state.status = "No IP".to_string(); + state.my_ip = "None".to_string(); + } + Ok(RouterIp::AquiringIp(_, _)) => { + state.status = "Acquiring IP...".to_string(); + state.my_ip = "Acquiring...".to_string(); + } + Ok(RouterIp::VerifyingIp(_, _)) => { + state.status = "Verifying IP...".to_string(); + state.my_ip = "Verifying...".to_string(); + } + Ok(RouterIp::AssignedIp(ip)) => { + state.status = "Connected".to_string(); + state.my_ip = ip.to_string(); + } + Err(e) => { + state.status = format!("Router update error: {}", e); + } + } + + // Peers + match network.get_peers().await { + Ok(peers) => { + 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..2b525bc 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,25 +1,29 @@ -use std::{ - collections::VecDeque, - sync::atomic::AtomicUsize, - time::{Duration, SystemTime}, -}; +use std::fmt::Display; +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 iroh::endpoint::{Connection, VarInt}; -use iroh::{ - Endpoint, EndpointId, - endpoint::{RecvStream, SendStream}, -}; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tracing::{debug, warn}; +use iroh::{Endpoint, EndpointId}; +use n0_watcher::Watchable; +use tokio::time::{self}; +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); - -#[derive(Debug, Clone)] +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_secs(2); +const CONNECTING_TIMEOUT: Duration = Duration::from_secs(20); +const DATAGRAM_PREFIX: u8 = 0x43; + +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Conn { api: Handle, } @@ -27,17 +31,16 @@ pub struct Conn { #[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 + ClosedAndStopped, // connection closed and actor stopped, no recovery possible } #[derive(Debug)] struct ConnActor { - rx: Receiver>, - self_handle: Handle, - state: ConnState, + self_handle: Option>, + state: Watchable, // 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 +48,666 @@ struct ConnActor { // route_packet failed conn: Option, conn_endpoint_id: EndpointId, - send_stream: Option, - recv_stream: Option, - endpoint: Endpoint, - last_reconnect: tokio::time::Instant, - reconnect_backoff: Duration, - reconnect_count: AtomicUsize, + external_sender: tokio::sync::mpsc::Sender, + + write_task: Option>, + write_tx: Option>, - external_sender: tokio::sync::broadcast::Sender, + read_task: Option>, - receiver_queue: VecDeque, - receiver_notify: tokio::sync::Notify, + 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, } impl Conn { - pub async fn new( - endpoint: Endpoint, + pub async fn accept_connection( conn: iroh::endpoint::Connection, - send_stream: SendStream, - recv_stream: RecvStream, - external_sender: tokio::sync::broadcast::Sender, + external_sender: tokio::sync::mpsc::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 }) + let (api, _) = Handle::spawn_with( + ConnActor::new(external_sender, conn.remote_id()), + |mut actor, rx| async move { actor.run(rx).await }, + ); + let s = Self { api }; + let self_handle = s.api.clone(); + s.api + .call(act_ok!(actor => async move { + actor.state.set(ConnState::Connecting).ok(); + actor.self_handle = Some(self_handle); + })) + .await?; + + /* + if let Err(err) = handshake(conn.clone(), CONNECTING_TIMEOUT).await { + warn!("Handshake failed for {}: {}", conn.remote_id(), err); + s.drop().await; + anyhow::bail!("Handshake failed: {}", err); + } + */ + + 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); + } + + Ok(s) } - pub async fn connect( + pub async fn open_connection( 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, - ) - .await; - - tokio::spawn(async move { - actor.set_state(ConnState::Connecting); - actor.run().await - }); + remote_endpoint_id: EndpointId, + external_sender: tokio::sync::mpsc::Sender, + ) -> Result { + let (api, _) = Handle::spawn_with( + ConnActor::new(external_sender, remote_endpoint_id), + |mut actor, rx| async move { actor.run(rx).await }, + ); let s = Self { api }; + let self_handle = s.api.clone(); + s.api + .call(act_ok!(actor => async move { + actor.state.set(ConnState::Connecting).ok(); + actor.self_handle = Some(self_handle); + })) + .await?; - 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; - } + let conn = match tokio::time::timeout( + CONNECTING_TIMEOUT, + endpoint.connect(remote_endpoint_id, crate::Direct::ALPN), + ) + .await + { + 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"); + } + }; - s + /* + if let Err(err) = handshake(conn.clone(), CONNECTING_TIMEOUT).await { + warn!("Handshake failed for {}: {:?}", conn.remote_id(), err); + s.drop().await; + anyhow::bail!("Handshake failed: {}", err); + } + */ + + 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); + } + + Ok(s) } - pub async fn get_state(&self) -> ConnState { + pub async fn get_state(&self) -> Watchable { if let Ok(state) = self .api .call(act_ok!(actor => async move { - actor.state + actor.state.clone() })) .await { state } else { - ConnState::Closed + Watchable::new(ConnState::ClosedAndStopped) } } - pub async fn close(&self) -> Result<()> { - self.api.call(act_ok!(actor => actor.close())).await - } + /* + pub async fn get_conn(&self) -> Option { + self.api + .call(act_ok!(actor => async { + actor.conn.clone() + })) + .await + .unwrap_or_default() + } */ 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; + actor.state.set(ConnState::ClosedAndStopped).ok(); + })) + .await + .ok(); + } +} + +#[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(()) + }; + + tokio::time::timeout(handshake_timeout, handshake_task).await? } -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)); +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); - reconnect_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); - notification_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 { + if self.state.get() == ConnState::ClosedAndStopped { + debug!( + "ConnActor for {} is in ClosedAndStopped 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 => { + /*_ = 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(); + let need_reconnect = !matches!(self.state, ConnState::Open | ConnState::Connecting) && + (self.write_task.as_ref().map(|t| t.is_finished()).unwrap_or(false) + || self.read_task.as_ref().map(|t| t.is_finished()).unwrap_or(false) + || self.conn.as_ref().and_then(|c| c.close_reason()).is_some() + || self.closed_task.as_ref().map(|t| t.is_finished()).unwrap_or(false) + ); 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"); + if self.reconnect_count.load(Ordering::SeqCst) < MAX_RECONNECTS { + warn!("Write task finished or connection issues detected. Attempting reconnect."); 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(); - } - 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; + }*/ + _ = keepalive_ticker.tick(), if self.state.get() == ConnState::Open => { + if let Some(tx) = &self.write_tx { + match tx.try_send(DirectMessage::IDontLikeWarnings) { + Ok(_) => { + 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={} state={:?} rx_count={} tx_count={} queue_len={} write_timeouts={} write_errors={} dropped_packets={}", + self.conn_endpoint_id, + self.state.get(), + 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( + external_sender: tokio::sync::mpsc::Sender, conn_endpoint_id: EndpointId, - conn: Option, - send_stream: Option, - recv_stream: Option, ) -> Self { Self { - rx, - state: if conn.is_some() && send_stream.is_some() && recv_stream.is_some() { - ConnState::Open - } else { - ConnState::Disconnected - }, + state: Watchable::new(ConnState::Connecting), external_sender, - receiver_queue: VecDeque::with_capacity(QUEUE_SIZE), + read_task: None, + write_task: None, + write_tx: 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)), } } - pub fn set_state(&mut self, state: ConnState) { - self.state = state; - } - pub async fn close(&mut self) { - self.state = ConnState::Closed; + if matches!( + self.state.get(), + ConnState::Disconnected | ConnState::ClosedAndStopped | ConnState::Closed + ) { + return; + } + + 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; + self.state.set(ConnState::ClosedAndStopped).ok(); + + if let Some(task) = self.read_task.take() { + task.abort(); + } + if let Some(task) = self.write_task.take() { + task.abort(); + } } pub async fn write(&mut self, pkg: DirectMessage) { - self.sender_queue.push_front(pkg); - self.sender_notify.notify_one(); + 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(); + } + if self.state.get() == ConnState::Open { + self.state.set(ConnState::Disconnected).ok(); + } + } + } + } 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.state.set(ConnState::Disconnected).ok(); return Err(anyhow::anyhow!("connection closed")); } + /* + let mut ack_iter = 0u8; + match conn.side() { + iroh::endpoint::Side::Client => { + iroh_auth::send_and_ack( + &conn, + &mut ack_iter, + Bytes::copy_from_slice(&[42]), + Duration::from_secs(5), + ) + .await?; + info!( + "Performing connection handshake for #2: {}", + conn.remote_id() + ); + let recv = + iroh_auth::read_and_ack(&conn, &mut ack_iter, Duration::from_secs(10)).await?; + info!( + "Performing connection handshake for #3: {}", + conn.remote_id() + ); + if recv.len() != 1 || recv[0] != 42 { + warn!("Handshake failed: invalid ack from client"); + return Err(anyhow::anyhow!("handshake failed")); + } + } + iroh::endpoint::Side::Server => { + let recv = + iroh_auth::read_and_ack(&conn, &mut ack_iter, Duration::from_secs(10)).await?; + info!( + "Performing connection handshake for #2: {}", + conn.remote_id() + ); + if recv.len() != 1 || recv[0] != 42 { + warn!("Handshake failed: invalid ack from server"); + return Err(anyhow::anyhow!("handshake failed")); + } + iroh_auth::send_and_ack( + &conn, + &mut ack_iter, + Bytes::copy_from_slice(&[42]), + Duration::from_secs(5), + ) + .await?; + info!( + "Performing connection handshake for #3: {}", + conn.remote_id() + ); + } + } */ + + 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(), + rx_count, + ))); + + 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.queue_len.clone(), + "main", + tx_count, + write_timeouts, + ))); + self.write_tx = Some(tx.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; + self.consecutive_write_errors.store(0, Ordering::Relaxed); + self.rx_count.store(0, Ordering::Relaxed); + self.tx_count.store(0, Ordering::Relaxed); + + 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); + } + Err(tokio::sync::mpsc::error::TrySendError::Closed(_)) => { + self.dropped_packets.fetch_add(1, Ordering::Relaxed); + } + } + } - // SHOULD NOT CHANGE but just for sanity - //self.conn_node_id = self.conn.clone().expect("new_conn").remote_node_id()?; + self.state.set(ConnState::Open).ok(); Ok(()) } +} - async fn try_reconnect(&mut self) -> Result<()> { - if self.state == ConnState::Closed { - return Err(anyhow::anyhow!("actor closed for good")); +async fn write_loop_bounded( + conn: Connection, + mut rx: tokio::sync::mpsc::Receiver, + api: Handle, + queue_len: Arc, + label: &'static str, + tx_count: Arc, + write_timeout: 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 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 mut retries = 0; + while retries < 1 { + match time::timeout( + KEEPALIVE_INTERVAL * 5, + conn.send_datagram_wait(Bytes::from(buf.clone())), + ) + .await + { + Ok(Ok(())) => break, + Ok(Err(err)) => { + warn!("Write error (frame): {}, {:?}, retrying...", err, err); + retries += 1; + time::sleep(Duration::from_millis(100)).await; + } + Err(_) => { + warn!("Write error timeout (frame)"); + write_timeout.fetch_add(1, Ordering::SeqCst); + time::sleep(Duration::from_millis(100)).await; + break; + } + } } - self.state = ConnState::Connecting; - self.reconnect_backoff *= 3; - self.last_reconnect = tokio::time::Instant::now(); - - self.send_stream = None; - self.recv_stream = None; - self.conn = None; - - 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 { + warn!( + "Write failed after 3 retries, 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 { - let _ = api.call(act_ok!(actor => async move { actor.reconnect_count.fetch_add(1, std::sync::atomic::Ordering::SeqCst) })).await; + "unknown".to_string() } - } - }); - Ok(()) + ); + info!("Write task stopped ({})", label); + let _ = api.call(act_ok!(actor => actor.close())).await; + break; + } + + 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, + rx_count: Arc, +) { + info!("Read task started"); + let mut retries = 0; + while retries < 1 { + match tokio::time::timeout(KEEPALIVE_INTERVAL * 5, read_next_msg(&conn)).await { + Ok(Ok(msg)) => { + retries = 0; + rx_count.fetch_add(1, Ordering::SeqCst); + trace!("Read message from stream, forwarding to network actor"); + let start = std::time::Instant::now(); + if let Err(e) = sender.send(msg).await { + warn!("Failed to forward message to network actor: {}", e); break; } + if start.elapsed().as_millis() > BACKPRESSURE_WARN_MS { + warn!( + "Direct->Network backpressure: send blocked {} ms", + start.elapsed().as_millis() + ); + } + } + Ok(Err(ReadError::Multiplex(_))) => { + continue; + } + Ok(Err(e)) => { + warn!("Stream read error: {:?}", e); + retries += 1; + } + Err(e) => { + warn!("Stream read error: timeout after {}", e); + retries += 1; } - } else { - return Err(anyhow::anyhow!("no send stream")); - } - - if !self.sender_queue.is_empty() { - self.sender_notify.notify_one(); } - - let end = SystemTime::now(); - let duration = end.duration_since(start).unwrap(); - debug!("write_remote: {wrote}; elapsed: {}", duration.as_millis()); - Ok(()) } - 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")), - } + info!("Read task stopped"); + if retries >= 1 { + warn!( + "Read failed after 3 retries, 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 { - Err(anyhow::anyhow!("failed to deserialize message")) + "unknown".to_string() } - } else { - Err(anyhow::anyhow!("no recv stream")) + ); + let _ = api.call(act_ok!(actor => actor.close())).await; + } +} + +#[derive(Debug)] +enum ReadError { + Datagram(String), + Multiplex(String), + Deserialize(String), +} + +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), } } } + +impl std::error::Error for ReadError {} + +async fn read_next_msg(conn: &Connection) -> Result { + let buf = conn + .read_datagram() + .await + .map_err(|e| ReadError::Datagram(format!("failed to read datagram: {}", e)))?; + if buf.len() > 1 && buf[0] == DATAGRAM_PREFIX { + let msg: DirectMessage = postcard::from_bytes(&buf[1..]) + .map_err(|e| ReadError::Deserialize(format!("failed to deserialize message: {}", e)))?; + Ok(msg) + } else { + Err(ReadError::Multiplex(format!( + "not meant for us: prefix={:X}", + buf[0] + ))) + } +} diff --git a/src/direct_connect.rs b/src/direct_connect.rs index cabad4e..f6f8a30 100644 --- a/src/direct_connect.rs +++ b/src/direct_connect.rs @@ -1,23 +1,56 @@ -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, protocol::ProtocolHandler}; +use n0_watcher::Watchable; +use noq::VarInt; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, hash_map::Entry}; -use tracing::{debug, info}; +use tokio::time::Instant; +use tracing::{debug, error, info, trace}; -use crate::{connection::Conn, local_networking::Ipv4Pkg}; +use crate::{ConnState, Router, RouterIp, connection::Conn, local_networking::Ipv4Pkg}; + +const MAX_RECONNECT_ATTEMPTS: usize = 50; #[derive(Debug, Clone)] pub struct Direct { api: Handle, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum PeerState { + NoConnection, + Connecting, + Connected(Conn), +} + +#[derive(Debug, Clone)] +pub struct ConnGen { + conn: Watchable>, + promoted: Watchable>, + accept_conn: Watchable, + open_conn: Watchable, + attempts: Watchable, +} + +impl Default for ConnGen { + fn default() -> Self { + Self { + conn: Watchable::new(None), + promoted: Watchable::new(None), + accept_conn: Watchable::new(PeerState::NoConnection), + open_conn: Watchable::new(PeerState::NoConnection), + 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, + direct_connect_tx: tokio::sync::mpsc::Sender, + router: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -27,19 +60,19 @@ pub enum DirectMessage { } impl Direct { - pub const ALPN: &[u8] = b"/iroh/lan-direct/1"; + pub const ALPN: &[u8] = b"/iroh/lan-direct/1.0.2"; pub fn new( endpoint: iroh::endpoint::Endpoint, - direct_connect_tx: tokio::sync::broadcast::Sender, + direct_connect_tx: tokio::sync::mpsc::Sender, ) -> Self { - let (api, rx) = Handle::channel(); - let mut actor = DirectActor { + let (api, _) = Handle::spawn_with(DirectActor { peers: HashMap::new(), endpoint, - rx, direct_connect_tx, - }; - tokio::spawn(async move { actor.run().await }); + router: None, + }, |mut actor, rx| async move { + actor.run(rx).await + }); Self { api } } @@ -55,6 +88,18 @@ impl Direct { .await } + pub async fn ensure_connection(&self, to: EndpointId) -> Result<()> { + self.api + .call(act!(actor => actor.ensure_connection(to))) + .await + } + + pub async fn set_router(&self, router: Router) -> Result<()> { + self.api + .call(act_ok!(actor => async move { actor.set_router(router) })) + .await + } + pub async fn get_endpoint(&self) -> iroh::endpoint::Endpoint { self.api .call(act!(actor => actor.get_endpoint())) @@ -62,12 +107,9 @@ impl Direct { .unwrap() } - pub async fn get_conn_state( - &self, - endpoint_id: EndpointId, - ) -> Result { + pub async fn get_peer_state(&self, endpoint_id: EndpointId) -> Result { self.api - .call(act!(actor => actor.get_conn_state(endpoint_id))) + .call(act!(actor => actor.get_peer_state(endpoint_id))) .await } @@ -77,88 +119,384 @@ impl Direct { } impl DirectActor { - async fn run(&mut self) { + async fn run(&mut self, rx: Receiver>) -> Result<(), anyhow::Error> { + let mut cleanup_interval = tokio::time::interval(std::time::Duration::from_secs(10)); + cleanup_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + 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; } + _ = cleanup_interval.tick() => { + //self.prune_closed_connections().await; + } + _ = reconnect_interval.tick() => { + self.connection_driver().await; + } _ = tokio::signal::ctrl_c() => { + info!("Ctrl-C received, shutting down DirectActor"); 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 prune_closed_connections(&mut self) { + let mut to_remove = Vec::new(); + for (id, conn) in &self.peers { + if conn.get_state().await == crate::connection::ConnState::Closed { + to_remove.push(*id); + } + } + for id in to_remove { + debug!("Removing closed connection to {}", id); + self.peers.remove(&id); + } + } */ - match self.peers.entry(remote_id) { - Entry::Occupied(mut entry) => { - entry.get_mut().incoming_connection(conn, true).await?; + async fn connection_driver(&mut self) { + for (id, peer) in self.peers.clone() { + if peer.attempts.get() > MAX_RECONNECT_ATTEMPTS { + if let Some(stale_conn) = peer.conn.get() + && peer.attempts.get() > MAX_RECONNECT_ATTEMPTS + { + debug!( + "Dropping stale connection to {} after {} failed attempts", + id, + peer.attempts.get() + ); + stale_conn.drop().await; + peer.conn.set(None).ok(); + } + + continue; } - Entry::Vacant(entry) => { - let (send_stream, recv_stream) = conn.accept_bi().await?; - entry.insert( - Conn::new( - self.endpoint.clone(), - conn, - send_stream, - recv_stream, - self.direct_connect_tx.clone(), - ) - .await?, - ); + + match (peer.open_conn.get(), peer.accept_conn.get()) { + (PeerState::Connected(_), PeerState::Connected(_)) + | (PeerState::Connected(_), PeerState::NoConnection | PeerState::Connecting) + | (PeerState::NoConnection | PeerState::Connecting, PeerState::Connected(_)) => { + self.promote_new_conn(peer, id).await; + } + (PeerState::NoConnection, PeerState::NoConnection) => { + let open_new = if let Some(conn) = peer.conn.get() + && matches!( + conn.get_state().await.get(), + crate::connection::ConnState::Disconnected + | crate::connection::ConnState::Closed + | crate::connection::ConnState::ClosedAndStopped + ) { + true + } else { + peer.conn.get().is_none() + }; + + if open_new { + let attempts = peer.attempts.clone(); + attempts.set(attempts.get() + 1).ok(); + Self::open_new_connection( + id, + peer.clone(), + self.endpoint.clone(), + self.direct_connect_tx.clone(), + ) + .await; + } + } + _ => { + /*debug!( + "Peer {} is in intermediate state (open={:?}, accept={:?}), skipping", + id, + peer.open_conn.get(), + peer.accept_conn.get() + );*/ + continue; + } + } + } + } + + async fn open_new_connection( + peer_id: EndpointId, + peer: ConnGen, + endpoint: Endpoint, + direct_connect_tx: tokio::sync::mpsc::Sender, + ) { + peer.open_conn.set(PeerState::Connecting).ok(); + + // Try open new connection + tokio::spawn(async move { + info!("Attempting to open new connection to {}", peer_id); + match Conn::open_connection(endpoint.clone(), peer_id, direct_connect_tx).await { + Ok(new_conn) => { + debug!("Successfully established connection to {}", peer_id); + if peer.open_conn.get() != PeerState::Connecting { + debug!( + "Connection to {} is no longer in Connecting state, dropping new connection", + peer_id + ); + new_conn.drop().await; + return; + } + peer.open_conn + .set(PeerState::Connected(new_conn.clone())) + .ok(); + } + Err(err) => { + error!( + "Failed to establish connection to {}: {}: {:?}", + peer_id, err, err + ); + peer.open_conn.set(PeerState::NoConnection).ok(); + } + } + }); + } + + async fn promote_new_conn(&mut self, peer: ConnGen, peer_id: EndpointId) { + debug!("Promoting new connection to {}", peer_id); + + match (peer.open_conn.get(), peer.accept_conn.get()) { + (PeerState::Connected(open), PeerState::Connected(accept)) => { + if let Some(old_conn) = peer.conn.get() { + debug!("Dropping old connection to {} during promotion", peer_id); + old_conn.drop().await; + } + if peer_id < self.endpoint.id() { + debug!("Promoting accept connection for {}", peer_id); + peer.conn.set(Some(accept)).ok(); + open.drop().await; + peer.open_conn.set(PeerState::NoConnection).ok(); + } else { + debug!("Promoting open connection for {}", peer_id); + peer.conn.set(Some(open)).ok(); + accept.drop().await; + peer.accept_conn.set(PeerState::NoConnection).ok(); + } + peer.open_conn.set(PeerState::NoConnection).ok(); + peer.accept_conn.set(PeerState::NoConnection).ok(); + peer.attempts.set(0).ok(); + peer.promoted.set(Some(Instant::now())).ok(); + } + (PeerState::Connected(open), PeerState::NoConnection | PeerState::Connecting) => { + /*if let Some(promoted) = peer.promoted.get() + && promoted.elapsed() < Duration::from_secs(3) + { + println!("RACE Accept"); + } + if let Some(promoted) = peer.promoted.get() + && promoted.elapsed() < Duration::from_secs(3) + && peer_id < self.endpoint.id() + { + info!("Probably a race, not promoting, lost peer_id comparison (open)"); + peer.open_conn.set(PeerState::NoConnection).ok(); + open.drop().await; + return; + }*/ + debug!("Promoting open connection for {}", peer_id); + if let Some(old_conn) = peer.conn.get() { + debug!("Dropping old connection to {} during promotion", peer_id); + old_conn.drop().await; + } + peer.conn.set(Some(open)).ok(); + peer.open_conn.set(PeerState::NoConnection).ok(); + peer.attempts.set(0).ok(); + peer.promoted.set(Some(Instant::now())).ok(); + } + (PeerState::NoConnection | PeerState::Connecting, PeerState::Connected(accept)) => { + /*if let Some(promoted) = peer.promoted.get() + && promoted.elapsed() < Duration::from_secs(3) + { + println!("RACE Accept"); + } + if let Some(promoted) = peer.promoted.get() + && promoted.elapsed() < Duration::from_secs(3) + && peer_id >= self.endpoint.id() + { + info!("Probably a race, not promoting, lost peer_id comparison (accept)"); + peer.accept_conn.set(PeerState::NoConnection).ok(); + accept.drop().await; + return; + }*/ + debug!("Promoting accept connection for {}", peer_id); + if let Some(old_conn) = peer.conn.get() { + debug!("Dropping old connection to {} during promotion", peer_id); + old_conn.drop().await; + } + peer.conn.set(Some(accept)).ok(); + peer.accept_conn.set(PeerState::NoConnection).ok(); + peer.attempts.set(0).ok(); + peer.promoted.set(Some(Instant::now())).ok(); + } + _ => { + unreachable!("Invalid state during promotion for {}", peer_id); } } + } + + async fn handle_connection(&mut self, conn: iroh::endpoint::Connection) -> Result<()> { + info!("Handling new connection from {}", conn.remote_id()); + let router = self.router.clone(); + let peer = self.peers.entry(conn.remote_id()).or_default().clone(); + let direct_connect_tx = self.direct_connect_tx.clone(); + if peer.accept_conn.get() != PeerState::NoConnection { + error!( + "Already have an active or pending connection with {}, rejecting new connection", + conn.remote_id() + ); + return Err(anyhow::anyhow!( + "Already have an active or pending connection with {}", + conn.remote_id() + )); + } + peer.accept_conn.set(PeerState::Connecting).ok(); + + tokio::spawn(async move { + info!("New direct connection from {:?}", conn.remote_id()); + let remote_id = conn.remote_id(); + if let Some(router) = &router { + if !matches!(router.get_ip_state().await, Ok(RouterIp::AssignedIp(_))) { + info!( + "Accepting connection from {} before local IP assignment", + remote_id + ); + } + + if router.get_ip_from_endpoint_id(remote_id).await.is_err() { + info!( + "Accepting connection from {} before remote IP assignment", + remote_id + ); + } + } else { + info!( + "Accepting connection from {} before router ready", + remote_id + ); + } + + let remote_id = conn.remote_id(); + + match Conn::accept_connection(conn.clone(), direct_connect_tx.clone()).await { + Ok(remote_conn) => { + debug!("Successfully accepted connection from {}", remote_id); + if peer.accept_conn.get() != PeerState::Connecting { + debug!( + "Connection to {} is no longer in Connecting state, dropping accepted connection", + remote_id + ); + remote_conn.drop().await; + return Ok(()); + } + peer.accept_conn + .set(PeerState::Connected(remote_conn.clone())) + .ok(); + Ok(()) + } + Err(err) => { + error!("Failed to accept connection from {}: {}", remote_id, err); + peer.accept_conn.set(PeerState::NoConnection).ok(); + conn.close(VarInt::from_u32(411), b"Failed to accept connection"); + Err(anyhow::anyhow!( + "Failed to accept connection from {}: {}", + remote_id, + err + )) + } + } + }); Ok(()) } 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 local_conn = if let Some(conn) = peer.conn.get() { + conn + } else { + return Err(anyhow::anyhow!( + "Connection to {} is not currently open", + to + )); + }; + if local_conn.get_state().await.get() != ConnState::Open { + return Err(anyhow::anyhow!( + "Connection to {} is not currently open", + to + )); + } + if let Err(e) = local_conn.write(pkg).await { + error!("Failed to write packet to peer {}: {}", to, e); + return Err(e); } - - entry.get().write(pkg).await?; } 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()); + return Err(anyhow::anyhow!( + "No active connection to {}, initiating new connection", + to + )); } } Ok(()) } - pub async fn get_conn_state( - &self, - endpoint_id: EndpointId, - ) -> Result { - Ok(self + async fn ensure_connection(&mut self, to: EndpointId) -> Result<()> { + if self.peers.contains_key(&to) { + return Ok(()); + } + + info!( + "No active connection to {}, initiating new connection (ensure_connection)", + to + ); + self.peers.insert(to, Default::default()); + Ok(()) + } + + pub async fn get_peer_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"))?; + if let Some(conn) = peer.conn.get() { + return Ok(conn.get_state().await.get()); + } + if peer.open_conn.get() != PeerState::NoConnection + || peer.accept_conn.get() != PeerState::NoConnection + { + return Ok(ConnState::Connecting); + } + Ok(ConnState::Closed) } pub async fn get_endpoint(&self) -> Result { Ok(self.endpoint.clone()) } + fn set_router(&mut self, router: Router) { + self.router = Some(router); + } + pub async fn close(&mut self) -> Result<()> { for (_, conn) in self.peers.drain() { - let _ = conn.close().await; + if let Some(conn) = conn.conn.get() { + conn.drop().await; + } } Ok(()) } @@ -169,6 +507,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/kv.rs b/src/kv.rs new file mode 100644 index 0000000..5da71f1 --- /dev/null +++ b/src/kv.rs @@ -0,0 +1,495 @@ +use std::{collections::BTreeMap, pin::Pin, sync::Arc, time::Duration}; + +use bytes::Bytes; +use futures::StreamExt; +use iroh::{EndpointId, PublicKey}; +use iroh_gossip::api::{GossipReceiver, GossipSender}; +use n0_watcher::Watchable; +use rand::Rng; +use serde::{Deserialize, Serialize}; +use tokio::{ + sync::{Mutex, broadcast}, + time::Instant, +}; +use tracing::{debug, info, trace, warn}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +enum Message { + /// A single key was inserted locally, propagate immediately. + Insert { key: String, timestamp: u64 }, + /// Full state dump. `nonce` ensures gossip never deduplicates the message. + State { + entries: Vec<(String, u64)>, + nonce: u64, + }, +} + +#[derive(Debug, Clone)] +pub struct KvEvent { + pub key: String, + pub timestamp: u64, + /// `true` when the key came from a remote peer. + pub remote: bool, +} + +/// Gossip-backed key store. +/// +/// * **Keys are the data**, every key is a plain `String` that encodes +/// whatever information you need (paths, ids, …). +/// * **Values are timestamps**, on conflict the highest timestamp wins +/// (simple last-writer-wins). +/// * Offers `query_all` / `query_prefix` à la iroh-docs. +/// * Fully clonable, backed by `Arc>`. +/// +/// # Synchronisation strategy +/// +/// | trigger | action | +/// |----------------------|-------------------------------------------------| +/// | local `insert()` | broadcast an `Insert` message immediately | +/// | `NeighborUp` | schedule a full `State` broadcast (with jitter) | +/// | periodic timer | schedule a full `State` broadcast (with jitter) | +/// | received `Insert` | apply if newer, notify subscribers | +/// | received `State` | merge all entries (latest-ts wins), notify | +#[derive(Debug, Clone)] +pub struct Kv { + inner: Arc, +} + +#[derive(Debug)] +struct KvInner { + endpoint_id: EndpointId, + store: Mutex>, + sender: GossipSender, + updates: broadcast::Sender, +} +impl Kv { + /// Spawn the background gossip worker and return a clonable handle. + /// + /// `receiver` is consumed, the worker exclusively owns the gossip + /// receive side. + pub fn spawn(endpoint_id: EndpointId, sender: GossipSender, receiver: GossipReceiver) -> Self { + let (updates_tx, _) = broadcast::channel(512); + + let inner = Arc::new(KvInner { + endpoint_id, + store: Mutex::new(BTreeMap::new()), + sender, + updates: updates_tx, + }); + + let kv = Kv { + inner: inner.clone(), + }; + + let kv_worker = kv.clone(); + tokio::spawn(async move { + worker(kv_worker, receiver).await; + }); + + kv + } +} + +impl Kv { + pub async fn query_all_entries(&self) -> Vec<(String, u64)> { + self.inner + .store + .lock() + .await + .iter() + .map(|(k, &v)| (k.clone(), v)) + .collect() + } + + /// Insert (or update) a key. Returns the timestamp that was written. + /// + /// The key is immediately broadcast to all gossip peers. + pub async fn insert(&self, key: impl Into) -> u64 { + let key = key.into(); + let ts = now_millis(); + + { + let mut store = self.inner.store.lock().await; + store.insert(key.clone(), ts); + } + + // Best-effort broadcast, don't block the caller on gossip errors. + self.send(Message::Insert { + key: key.clone(), + timestamp: ts, + }) + .await; + + let _ = self.inner.updates.send(KvEvent { + key, + timestamp: ts, + remote: false, + }); + + ts + } + + /// All keys, sorted lexicographically. + pub async fn query_all(&self) -> Vec { + self.query_all_entries() + .await + .into_iter() + .map(|(k, _)| k) + .collect() + } + + /// All keys that start with `prefix`, sorted lexicographically. + pub async fn query_prefix(&self, prefix: &str) -> Vec { + self.inner + .store + .lock() + .await + .range(prefix.to_string()..) + .take_while(|(k, _)| k.starts_with(prefix)) + .map(|(k, _)| k.clone()) + .collect() + } + + /// Number of keys matching `prefix`. + pub async fn count_prefix(&self, prefix: &str) -> usize { + self.inner + .store + .lock() + .await + .range(prefix.to_string()..) + .take_while(|(k, _)| k.starts_with(prefix)) + .count() + } + + /// Check whether `key` exists. + pub async fn contains(&self, key: &str) -> bool { + self.inner.store.lock().await.contains_key(key) + } + + /// Total number of keys. + pub async fn len(&self) -> usize { + self.inner.store.lock().await.len() + } + + /// Check whether the store is empty. + pub async fn is_empty(&self) -> bool { + self.inner.store.lock().await.is_empty() + } + + /// Subscribe to live insert notifications (local + remote). + pub fn subscribe(&self) -> broadcast::Receiver { + self.inner.updates.subscribe() + } +} + +impl Kv { + fn canonical_state_key(key: &str) -> String { + if let Some(rest) = key.strip_prefix("/assigned/ip/") { + let parts: Vec<&str> = rest.split('/').collect(); + if parts.len() >= 2 { + return format!("/assigned/ip/{}/{}", parts[0], parts[1]); + } + } + if let Some(rest) = key.strip_prefix("/candidates/ip/") { + let parts: Vec<&str> = rest.split('/').collect(); + if parts.len() >= 2 { + return format!("/candidates/ip/{}/{}", parts[0], parts[1]); + } + } + key.to_string() + } + + /// Apply a remote key. Returns `true` if the store was actually updated + /// (i.e. the incoming timestamp was strictly newer). + async fn apply(&self, key: &str, timestamp: u64) -> bool { + let mut store = self.inner.store.lock().await; + match store.get(key) { + Some(&existing) if existing >= timestamp => false, + _ => { + store.insert(key.to_string(), timestamp); + true + } + } + } + + /// Snapshot the entire store for a `State` broadcast. + async fn snapshot(&self) -> Vec<(String, u64)> { + let store = self.inner.store.lock().await; + let mut latest = BTreeMap::::new(); + for (key, ×tamp) in store.iter() { + let canonical = Self::canonical_state_key(key); + match latest.get(&canonical) { + Some(&existing) if existing >= timestamp => {} + _ => { + latest.insert(canonical, timestamp); + } + } + } + latest.into_iter().collect() + } + + /// Broadcast a full state dump. + async fn broadcast_state(&self) { + let entries = self.snapshot().await; + if entries.is_empty() { + return; + } + debug!("[Kv] Broadcasting state ({} keys)", entries.len()); + self.send(Message::State { + entries, + nonce: now_millis(), + }) + .await; + } + + /// Serialize + send via gossip. Errors are logged, never propagated. + async fn send(&self, msg: Message) { + let inner = self.inner.clone(); + tokio::spawn(async move { + match postcard::to_allocvec(&msg) { + Ok(bytes) => { + debug!("[Kv] Sending gossip message: {:?}", msg); + if let Err(e) = inner.sender.broadcast(Bytes::from(bytes)).await { + warn!("[Kv] gossip broadcast failed: {}", e); + } else { + debug!("[Kv] gossip broadcast succeeded"); + } + } + Err(e) => warn!("[Kv] serialize failed: {}", e), + } + }); + } +} + +const JITTER_MIN_MS: u64 = 200; +const JITTER_MAX_MS: u64 = 2_000; +const PERIODIC_SYNC_SECS: u64 = 30; +const DIAGNOSTIC_LOG_SECS: u64 = 10; +const PEER_DISCONNECT_BACKOFF_INIT_SECS: u64 = 2; +const PEER_DISCONNECT_BACKOFF_INC_SECS: u64 = 2; +const PEER_DISCONNECT_MAX_BACKOFF_SECS: u64 = 30; +const PEER_DISCONNECT_MAX_RETRY_SECS: u64 = 120; + +async fn worker(kv: Kv, mut receiver: GossipReceiver) { + use iroh_gossip::api::Event; + + let mut state_timer: Pin> = + Box::pin(tokio::time::sleep(Duration::from_secs(86400))); + let mut state_pending = false; + let mut received_count: u64 = 0; + let mut neighbor_up_count: u64 = 0; + let mut neighbor_down_count: u64 = 0; + let mut lagged_count: u64 = 0; + let mut stream_error_count: u64 = 0; + let mut decode_error_count: u64 = 0; + + let mut periodic = tokio::time::interval(Duration::from_secs(PERIODIC_SYNC_SECS)); + periodic.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + let mut diagnostics = tokio::time::interval(Duration::from_secs(DIAGNOSTIC_LOG_SECS)); + diagnostics.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + let init_peers = receiver + .neighbors() + .map(|peer| (peer, None)) + .collect::>(); + let peer_disconnect_timings = Watchable::new(init_peers); + + // On startup, schedule an initial state broadcast so any existing peers + // learn about keys we may have inserted before the worker started. + schedule_state(&mut state_timer, &mut state_pending); + loop { + tokio::select! { + event = receiver.next() => { + match event { + Some(Ok(Event::Received(msg))) => { + received_count += 1; + info!("[Kv] Received gossip message from {}: {:?}", msg.delivered_from, msg.content); + if !handle_received(&kv, &msg.content, &mut state_pending).await { + decode_error_count += 1; + } + } + Some(Ok(Event::NeighborUp(peer))) => { + neighbor_up_count += 1; + let mut peers = peer_disconnect_timings.get(); + peers.insert(peer, None); + peer_disconnect_timings.set(peers).ok(); + + info!("[Kv] NeighborUp: {}, scheduling state broadcast", peer); + schedule_state(&mut state_timer, &mut state_pending); + } + Some(Ok(Event::NeighborDown(peer))) => { + neighbor_down_count += 1; + let mut peers = peer_disconnect_timings.get(); + peers.insert(peer, Some(Instant::now())); + peer_disconnect_timings.set(peers).ok(); + reconnect_peer(&peer_disconnect_timings, &kv, &peer); + debug!("[Kv] NeighborDown: {}", peer); + } + Some(Ok(Event::Lagged)) => { + lagged_count += 1; + warn!("[Kv] Gossip lagged, scheduling state broadcast"); + schedule_state(&mut state_timer, &mut state_pending); + } + Some(Err(e)) => { + stream_error_count += 1; + warn!("[Kv] gossip stream error: {}", e); + } + None => { + warn!("[Kv] gossip stream ended, exiting worker"); + } + } + } + _ = &mut state_timer, if state_pending => { + state_pending = false; + kv.broadcast_state().await; + } + _ = periodic.tick() => { + schedule_state(&mut state_timer, &mut state_pending); + } + _ = diagnostics.tick() => { + let neighbors = receiver.neighbors().count(); + let store_len = kv.inner.store.lock().await.len(); + info!( + "[KvDiag] endpoint={} neighbors={} store={} recv={} up={} down={} lagged={} stream_err={} decode_err={} state_pending={}", + kv.inner.endpoint_id, + neighbors, + store_len, + received_count, + neighbor_up_count, + neighbor_down_count, + lagged_count, + stream_error_count, + decode_error_count, + state_pending, + ); + } + } + } +} + +fn reconnect_peer( + peer_disconnect_timings: &Watchable>>, + kv: &Kv, + peer: &PublicKey, +) { + tokio::spawn({ + let kv = kv.clone(); + let peer_disconnect_timings = peer_disconnect_timings.clone(); + let peer = *peer; + async move { + let mut backoff = PEER_DISCONNECT_BACKOFF_INIT_SECS; + while let Some(Some(disconnected_since)) = peer_disconnect_timings.get().get(&peer) + && disconnected_since.elapsed() + < Duration::from_secs(PEER_DISCONNECT_MAX_RETRY_SECS) + { + kv.inner.sender.join_peers(vec![peer]).await.ok(); + debug!( + "[Kv] Attempting to rejoin peer {} (disconnected for {}s, backoff {}s)", + peer, + disconnected_since.elapsed().as_secs(), + backoff, + ); + tokio::time::sleep(Duration::from_secs(backoff)).await; + backoff = (backoff + PEER_DISCONNECT_BACKOFF_INC_SECS) + .min(PEER_DISCONNECT_MAX_BACKOFF_SECS); + } + } + }); +} + +/// Reset the state-broadcast timer to fire after a random jitter. +/// +/// If the timer was already pending it gets **replaced**, this combines +/// multiple rapid triggers (e.g. several `NeighborUp` events in a burst) +/// into one broadcast. +fn schedule_state(timer: &mut Pin>, pending: &mut bool) { + let jitter = rand::rng().random_range(JITTER_MIN_MS..=JITTER_MAX_MS); + timer + .as_mut() + .reset(tokio::time::Instant::now() + Duration::from_millis(jitter)); + *pending = true; + trace!("[Kv] State broadcast scheduled in {}ms", jitter); +} + +/// Parse and apply one incoming gossip message. +/// +/// When a `State` message is received from another peer we only cancel our +/// pending local broadcast if the remote state already covers everything we +/// have (same keys, same or newer timestamps). If we have keys or newer +/// timestamps that the remote is missing, we keep the pending broadcast so +/// the remote learns about our state. +async fn handle_received(kv: &Kv, raw: &[u8], state_pending: &mut bool) -> bool { + let msg: Message = match postcard::from_bytes(raw) { + Ok(m) => m, + Err(e) => { + warn!( + "[Kv] ignoring unparseable gossip message (len={}): {}", + raw.len(), + e + ); + return false; + } + }; + + match msg { + Message::Insert { key, timestamp } => { + if kv.apply(&key, timestamp).await { + debug!("[Kv] remote insert: {}", key); + let _ = kv.inner.updates.send(KvEvent { + key, + timestamp, + remote: true, + }); + } + } + Message::State { entries, .. } => { + let remote_map: std::collections::HashMap<&str, u64> = + entries.iter().map(|(k, ts)| (k.as_str(), *ts)).collect(); + + let mut applied = 0usize; + for (key, timestamp) in &entries { + if kv.apply(key, *timestamp).await { + let _ = kv.inner.updates.send(KvEvent { + key: key.clone(), + timestamp: *timestamp, + remote: true, + }); + applied += 1; + } + } + if applied > 0 { + debug!("[Kv] state merge: {} keys applied", applied); + } + + if *state_pending { + let store = kv.inner.store.lock().await; + let we_have_extra = store + .iter() + .any(|(k, &ts)| match remote_map.get(k.as_str()) { + None => true, + Some(&remote_ts) => ts > remote_ts, + }); + if we_have_extra { + debug!( + "[Kv] received remote state but we have keys they don't, keeping pending broadcast" + ); + } else { + debug!( + "[Kv] received remote state that covers ours, cancelling pending broadcast" + ); + *state_pending = false; + } + } + } + } + + true +} + +fn now_millis() -> u64 { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_millis() as u64 +} diff --git a/src/lib.rs b/src/lib.rs index a595c20..31173a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,13 @@ -//mod direct_connect; -//mod local_networking; mod connection; mod direct_connect; +pub mod kv; mod local_networking; -pub mod network; +mod network; mod router; +pub mod cli; +pub use kv::Kv; +pub use network::Network; pub use connection::ConnState; pub use direct_connect::{Direct, DirectMessage}; pub use local_networking::Tun; diff --git a/src/local_networking.rs b/src/local_networking.rs index d9d1731..effa267 100644 --- a/src/local_networking.rs +++ b/src/local_networking.rs @@ -1,11 +1,22 @@ use anyhow::Result; -use pnet_packet::{Packet, ip::IpNextHeaderProtocols, ipv4::Ipv4Packet}; +use pnet_packet::{ + MutablePacket, Packet, + icmp::{MutableIcmpPacket, checksum as icmp_checksum}, + ip::IpNextHeaderProtocols, + ipv4::{Ipv4Flags, Ipv4Packet, MutableIpv4Packet, checksum}, + tcp::{MutableTcpPacket, ipv4_checksum as tcp_ipv4_checksum}, + udp::{MutableUdpPacket, ipv4_checksum as udp_ipv4_checksum}, +}; use serde::{Deserialize, Serialize}; -use std::{fmt::Debug, net::Ipv4Addr}; -use tracing::debug; +use std::{ + fmt::Debug, + net::Ipv4Addr, + time::{Duration, Instant}, +}; +use tracing::{info, trace, warn}; use tun_rs::{AsyncDevice, DeviceBuilder, Layer}; -use actor_helper::{Action, Handle, act}; +use actor_helper::{Action, Handle, Receiver, act}; #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Ipv4Pkg(Vec); @@ -39,14 +50,14 @@ impl Ipv4Pkg { #[derive(Debug, Clone)] pub struct Tun { api: Handle, + tun_tx: tokio::sync::mpsc::Sender, } 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, + tun_rx: tokio::sync::mpsc::Receiver, + to_remote_writer: tokio::sync::mpsc::Sender, } impl Debug for TunActor { @@ -61,9 +72,9 @@ impl Debug for TunActor { impl Tun { pub async fn new( free_ip_ending: (u8, u8), - to_remote_writer: tokio::sync::broadcast::Sender, + to_remote_writer: tokio::sync::mpsc::Sender, ) -> Result { - let ip = Ipv4Addr::new(172, 22, free_ip_ending.0, free_ip_ending.1); + let ip = Ipv4Addr::new(172, 30, free_ip_ending.0, free_ip_ending.1); #[cfg(target_os = "windows")] dll_export().await?; @@ -71,31 +82,32 @@ impl Tun { let dev = DeviceBuilder::new() .ipv4(ip, 24, None) .layer(Layer::L3) - .mtu(1280) + .mtu(1400) .build_async()?; - let (api, rx) = Handle::channel(); - - tokio::spawn(async move { - let mut actor = TunActor { + let (tun_tx, tun_rx) = tokio::sync::mpsc::channel(1024 * 16); + let (api, _) = Handle::spawn_with(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 }) + tun_rx, + }, |mut actor, rx| async move {actor.run(rx).await} ); + Ok(Self { api, tun_tx }) } pub async fn write(&self, pkg: Ipv4Pkg) -> Result<()> { - self.api.call(act!(actor => actor.write_to_tun(pkg))).await - } + let cap = self.tun_tx.capacity(); + if cap < 1000 { + warn!( + "TunActor write channel saturated ({} free). Packet flow stalled.", + cap + ); + } - pub async fn subscribe(&self) -> Result> { - self.api.call(act!(actor => actor.subscribe())).await + match self.tun_tx.send(pkg).await { + Ok(_) => Ok(()), + Err(e) => Err(anyhow::anyhow!("Tun actor closed: {}", e)), + } } pub async fn close(&self) -> Result<()> { @@ -108,65 +120,124 @@ impl Tun { } impl TunActor { - async fn run(&mut self) -> Result<()> { + async fn run(&mut self, rx: Receiver>) -> Result<()> { let mut dev_buf = [0u8; 1024 * 128]; + info!("TunActor started for IP: {}", self.ip); loop { tokio::select! { - - // Handle API actions - Ok(action) = self.rx.recv_async() => { + Ok(action) = rx.recv_async() => { action(self).await; } + + // Write path: Network -> TUN + Some(pkg) = self.tun_rx.recv() => { + if let Ok(packet) = pkg.to_ipv4_packet() { + let data = packet.packet(); + match self.dev.send(data).await { + Ok(_) => {} + Err(e) => warn!("Failed to write to TUN: {}", e), + } + } + } + + // Read path: TUN -> Network 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(), + if let Some(mut ipv4_packet) = MutableIpv4Packet::new(&mut dev_buf[..len]) { + let source = ipv4_packet.get_source(); + let destination = ipv4_packet.get_destination(); + + // drop broadcast packets to prevent loops (broadcast storms) + if destination.octets()[3] == 255 { + trace!( + "Dropping broadcast packet to prevent loop: src={} dst={}", + source, + destination + ); + continue; + } + + if !matches!( + ipv4_packet.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(), - ); + trace!("Ignored packet protocol: {:?}", ipv4_packet.get_next_level_protocol()); + continue; + } + + // re-calculate and set checksum for the IP header + ipv4_packet.set_checksum(checksum(&ipv4_packet.to_immutable())); - 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()); + // 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 = (ipv4_packet.get_flags() & Ipv4Flags::MoreFragments) != 0 + || ipv4_packet.get_fragment_offset() > 0; - debug!("forwarding_to_remote_writer {}", _res.is_ok()); + if !is_fragment { + // ONLY calculate L4 checksums for whole packets + match ipv4_packet.get_next_level_protocol() { + IpNextHeaderProtocols::Tcp => { + if let Some(mut tcp_packet) = + MutableTcpPacket::new(ipv4_packet.payload_mut()) + { + tcp_packet.set_checksum(tcp_ipv4_checksum( + &tcp_packet.to_immutable(), + &source, + &destination, + )); + } + } + IpNextHeaderProtocols::Udp => { + if let Some(mut udp_packet) = + MutableUdpPacket::new(ipv4_packet.payload_mut()) + { + udp_packet.set_checksum(udp_ipv4_checksum( + &udp_packet.to_immutable(), + &source, + &destination, + )); + } + } + IpNextHeaderProtocols::Icmp => { + if let Some(mut icmp_packet) = + MutableIcmpPacket::new(ipv4_packet.payload_mut()) + { + icmp_packet.set_checksum(icmp_checksum( + &icmp_packet.to_immutable(), + )); + } + } + _ => {} } + } + if let Ok(pkg) = Ipv4Pkg::new(ipv4_packet.packet()) { + let start = Instant::now(); + if let Err(e) = self.to_remote_writer.send(pkg).await { + warn!("Failed to forward packet from TUN to network: {}", e); + } else if start.elapsed() > Duration::from_millis(5) { + warn!("TUN->network backpressure: send blocked {} ms", start.elapsed().as_millis()); + } } + } else { + warn!("Failed to parse packet from TUN"); } } + _ = tokio::signal::ctrl_c() => { + info!("Ctrl-C received, shutting down TunActor"); break } } } + self.close().await?; 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()) - } - +impl TunActor { pub async fn close(&mut self) -> Result<()> { + info!("Closing TunActor"); let _ = &self.dev; Ok(()) } diff --git a/src/network.rs b/src/network.rs index 5243ce0..5fb21e9 100644 --- a/src/network.rs +++ b/src/network.rs @@ -1,14 +1,27 @@ -use std::time::Duration; +use std::{ + collections::{HashMap, HashSet, VecDeque}, + path::PathBuf, + time::{Duration, Instant}, +}; -use actor_helper::{Action, Actor, Handle, act, act_ok}; +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 iroh::{ + Endpoint, EndpointId, SecretKey, endpoint::{Connection, IdleTimeout, QuicTransportConfig, VarInt}, protocol::ProtocolHandler +}; +use iroh_auth::Authenticator; + use iroh_gossip::{net::Gossip, proto::HyparviewConfig}; -use tracing::warn; +use iroh_topic_tracker::TopicDiscoveryHook; +use sha2::Digest; +use tracing::{debug, error, info, trace, warn}; + +use crate::{ + ConnState, Direct, DirectMessage, Router, Tun, local_networking::Ipv4Pkg, router::RouterIp, +}; -use crate::{Direct, DirectMessage, Router, Tun, local_networking::Ipv4Pkg, router::RouterIp}; +const PENDING_TTL: Duration = Duration::from_secs(60); +const PENDING_MAX_PER_IP: usize = 1024 * 16; #[derive(Debug, Clone)] pub struct Network { @@ -17,89 +30,181 @@ pub struct Network { #[derive(Debug)] struct NetworkActor { - rx: actor_helper::Receiver>, - router: Router, direct: Direct, + _auth: Authenticator, - _router: iroh::protocol::Router, - _endpoint: iroh::endpoint::Endpoint, + _iroh_router: iroh::protocol::Router, + //_docs_router: iroh::protocol::Router, + iroh_endpoint: iroh::endpoint::Endpoint, tun: Option, - _local_to_direct_tx: tokio::sync::broadcast::Sender, - local_to_direct_rx: tokio::sync::broadcast::Receiver, + tun_ip_debug: Option, + + _local_to_direct_tx: tokio::sync::mpsc::Sender, + local_to_direct_rx: tokio::sync::mpsc::Receiver, - _direct_to_local_tx: tokio::sync::broadcast::Sender, - direct_to_local_rx: tokio::sync::broadcast::Receiver, + _direct_to_local_tx: tokio::sync::mpsc::Sender, + direct_to_local_rx: tokio::sync::mpsc::Receiver, + + ip_cache: HashMap, + peer_ids: HashSet, + pending_packets: HashMap>, } +/*fn transport_config() -> QuicTransportConfig { + QuicTransportConfig::builder() + .max_idle_timeout(Some(IdleTimeout::from(VarInt::from_u32(10_000)))) + .keep_alive_interval(Duration::from_millis(20_000)) + .build() +}*/ + +fn transport_config(log_path: Option) -> QuicTransportConfig { + const EXPECTED_RTT: u32 = 100; + //const MAX_STREAM_BANDWIDTH: u32 = 512_000; + const STREAM_RWND: u32 = 102_400;//MAX_STREAM_BANDWIDTH / 1000 * EXPECTED_RTT * 2; + + let mut transport = QuicTransportConfig::builder() + //.congestion_controller_factory(Arc::new(BbrConfig::default())) + .enable_segmentation_offload(false) + .packet_threshold(3) + .time_threshold(1.125) + .max_idle_timeout(Some(IdleTimeout::from(VarInt::from_u32(45_000)))) + .keep_alive_interval(Duration::from_millis(3_000)) + .stream_receive_window(STREAM_RWND.into()) + .send_window((4 * STREAM_RWND).into()) + .initial_rtt(Duration::from_millis(EXPECTED_RTT as u64)) + .initial_mtu(1660) + .min_mtu(1660) + .datagram_receive_buffer_size(Some(65_536)) + .datagram_send_buffer_size(65_536); + + 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_from_path(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()), + } +} */ + +#[derive(Debug, Clone)] +#[allow(dead_code)] +struct DummyProtocol; +impl ProtocolHandler for DummyProtocol { + async fn accept(&self, _conn: Connection) -> Result<(), iroh::protocol::AcceptError> { + Ok(()) + } +} impl Network { pub async fn new(name: &str, password: &str) -> Result { - let secret_key = SecretKey::generate(&mut rand::rng()); - - let endpoint = Endpoint::builder() + Self::new_logs_dir(name, password, None).await + } + pub async fn new_logs_dir( + name: &str, + password: &str, + log_dir: Option, + ) -> 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 topic_discovery_hook = TopicDiscoveryHook::new(); + //let relay_map = RelayMap::from_iter([rustonbsd_relay()]); + //relay_map.extend(&iroh::defaults::prod::default_relay_map()); + + let endpoint = Endpoint::builder(iroh::endpoint::presets::N0) + //.relay_mode(iroh::RelayMode::Custom(relay_map)) + .hooks(auth.clone()) + .hooks(topic_discovery_hook.clone()) .secret_key(secret_key.clone()) + .transport_config(transport_config(log_dir)) .bind() .await?; + auth.set_endpoint(&endpoint).await; + endpoint.online().await; + + let gossip_hyparview_config = HyparviewConfig { + neighbor_request_timeout: Duration::from_millis(3000), + shuffle_interval: Duration::from_secs(120), + ..Default::default() + }; - let gossip_config = HyparviewConfig { - neighbor_request_timeout: Duration::from_millis(2000), + 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), + graft_timeout_1: Duration::from_secs(2), + graft_timeout_2: Duration::from_secs(1), ..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?; - - let (direct_connect_tx, direct_connect_rx) = tokio::sync::broadcast::channel(1024 * 16); + let (direct_connect_tx, direct_connect_rx) = tokio::sync::mpsc::channel(1024 * 16); let direct = Direct::new(endpoint.clone(), direct_connect_tx.clone()); - 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() + let router = crate::Router::builder(topic_discovery_hook) .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, - direct, - - _router, - _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; - }); + direct.set_router(router.clone()).await?; + + let (to_remote_writer, to_remote_reader) = tokio::sync::mpsc::channel(1024 * 16); + let (api, _) = Handle::spawn_with(NetworkActor { + router, + direct, + _auth: auth, + + _iroh_router, + //_docs_router, + iroh_endpoint: endpoint, + + tun: None, + tun_ip_debug: 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, + + ip_cache: HashMap::new(), + peer_ids: HashSet::new(), + pending_packets: HashMap::new(), + }, |mut actor, rx| async move { actor.run(rx).await }); Ok(Self { api }) } @@ -137,7 +242,7 @@ impl Network { 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,44 +250,224 @@ impl Network { } } -impl Actor for NetworkActor { - async fn run(&mut self) -> Result<()> { +impl NetworkActor { + async fn run(&mut self, rx: Receiver>) -> Result<()> { let mut ip_tick = tokio::time::interval(Duration::from_millis(500)); ip_tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + let mut cache_tick = tokio::time::interval(Duration::from_secs(1)); + cache_tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + + 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() => { + info!("Received Ctrl-C, shutting down NetworkActor"); 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); + _ = ip_tick.tick() => { + if let Some(tun_ip) = self.tun_ip_debug + && let Ok(RouterIp::AssignedIp(router_ip)) = self.router.get_ip_state().await + && tun_ip != router_ip { + error!("IP Configuration Mismatch: TUN={}, Router={}. Connectivity compromised.", tun_ip, router_ip); + } + if self.tun.is_none() { + match self.router.get_ip_state().await { + Ok(RouterIp::AssignedIp(ip)) => { + info!("Initializing TUN for IP: {}", ip); + match tokio::time::timeout( + Duration::from_secs(10), + Tun::new((ip.octets()[2],ip.octets()[3]), self._local_to_direct_tx.clone()) + ).await { + Ok(Ok(tun)) => { + info!("TUN initialized successfully"); + self.tun_ip_debug = Some(ip); + self.tun = Some(tun); + if let Ok(peers) = self.router.get_peers().await { + for (id, remote_ip) in peers { + if remote_ip.is_some() { + info!("Ensuring direct connection after IP assignment: {}", id); + let direct = self.direct.clone(); + tokio::spawn(async move { + if let Err(e) = direct.ensure_connection(id).await { + warn!("Failed to ensure connection to {}: {}", id, e); + } + }); + } + + } + } + } + Ok(Err(e)) => { + error!("Failed to initialize TUN: {}", e); + } + Err(_) => { + error!("Timed out initializing TUN"); + } + } + } + Ok(_) => {} + Err(e) => { + warn!("Failed to get router state while waiting for TUN: {}", e); + } + } + } + } + + _ = cache_tick.tick() => { + if let Ok(peers) = self.router.get_peers().await { + let mut next_peer_ids = HashSet::new(); + let mut router_peers: HashMap = HashMap::new(); + + for (id, maybe_ip) in peers { + next_peer_ids.insert(id); + if let Some(ip) = maybe_ip { + router_peers.insert(ip, id); + } } + + let cached_ips: Vec<_> = self.ip_cache.keys().copied().collect(); + for ip in cached_ips { + if let std::collections::hash_map::Entry::Vacant(e) = router_peers.entry(ip) + && let Some(owner_id) = self.ip_cache.get(&ip) + && matches!(self.direct.get_peer_state(*owner_id).await, Ok(ConnState::Open) | Ok(ConnState::Connecting)) { + debug!("[Data-Plane Liveness] Preserving route to {} (owned by {}) despite Router/Doc miss. Connection is OPEN.", ip, owner_id); + e.insert(*owner_id); + next_peer_ids.insert(*owner_id); + } + } + + self.ip_cache = router_peers; + if !self.pending_packets.is_empty() { + let now = Instant::now(); + let pending_keys: Vec<_> = self.pending_packets.keys().copied().collect(); + for ip in pending_keys { + if let Some(queue) = self.pending_packets.get_mut(&ip) { + queue.retain(|(ts, _)| now.duration_since(*ts) <= PENDING_TTL); + if queue.is_empty() { + self.pending_packets.remove(&ip); + continue; + } + } + if let Some(id) = self.ip_cache.get(&ip).copied() { + let peer_state = self.direct.get_peer_state(id).await; + if !matches!(peer_state, Ok(ConnState::Open)) { + continue; + } + + if let Some(mut queue) = self.pending_packets.remove(&ip) { + let replay_count = queue.len(); + info!( + "Replaying {} buffered packets for {} via {}", + replay_count, + ip, + id + ); + + let mut failed_queue = VecDeque::new(); + while let Some((ts, pkt)) = queue.pop_front() { + if let Err(e) = self + .direct + .route_packet(id, DirectMessage::IpPacket(pkt.clone())) + .await + { + warn!( + "Failed to route buffered packet to {} for ip {} state={:?}: {}", + id, + ip, + peer_state, + e + ); + failed_queue.push_back((ts, pkt)); + failed_queue.append(&mut queue); + break; + } + } + + if !failed_queue.is_empty() { + self.pending_packets.insert(ip, failed_queue); + } + } + } + } + } + for id in next_peer_ids.difference(&self.peer_ids).copied() { + info!("New peer discovered: {}. Ensuring direct connection", id); + let direct = self.direct.clone(); + tokio::spawn(async move { + if let Err(e) = direct.ensure_connection(id).await { + warn!("Failed to ensure connection to {}: {}", id, e); + } + }); + } + self.peer_ids = next_peer_ids; } } - 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() { - 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; + res = self.local_to_direct_rx.recv(), if self.tun.is_some() => { + match res { + Some(tun_recv) => { + // Tun initialized, route packets + if let Ok(ip_pkg) = tun_recv.to_ipv4_packet() { + let dest = ip_pkg.get_destination(); + let to = if let Some(id) = self.ip_cache.get(&dest) { + Ok(*id) + } else { + self.router.get_endpoint_id_from_ip(dest).await + }; + match to { + Ok(to) => { + if to == self.iroh_endpoint.id() { + trace!("Loopback packet detected (dest to self)"); + if let Some(tun) = &self.tun + && let Err(e) = tun.write(tun_recv.clone()).await { + warn!("Failed to loopback packet to TUN: {}", e); + self.queue_packet(dest, tun_recv); + } + } else { + trace!("Routing packet from TUN to {}", to); + if let Err(e) = self.direct.route_packet(to, DirectMessage::IpPacket(tun_recv.clone())).await { + self.queue_packet(dest, tun_recv); + trace!("Failed to route packet to {}: {}", to, e); + } + } + } + Err(e) => { + trace!("Could not resolve endpoint for IP {}: {}", dest, e); + self.queue_packet(dest, tun_recv); + } + } + } + } + None => { + error!("TUN channel closed, breaking loop"); + break; } } } - 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; + res = self.direct_to_local_rx.recv(), if self.tun.is_some() => { + match res { + Some(direct_msg) => { + // Route remote packet to tun if our ip + if let Some(tun) = &self.tun + && let DirectMessage::IpPacket(ip_pkg) = direct_msg { + trace!("Routing remote packet to TUN"); + if let Err(e) = tun.write(ip_pkg).await { + warn!("Failed to write to TUN: {}", e); + } + } + } + None => { + warn!("NetworkActor direct channel closed"); + break; } } } @@ -192,3 +477,24 @@ impl Actor for NetworkActor { Ok(()) } } + +impl NetworkActor { + fn queue_packet(&mut self, ip: std::net::Ipv4Addr, pkt: Ipv4Pkg) { + let queue = self.pending_packets.entry(ip).or_default(); + if queue.len() >= PENDING_MAX_PER_IP { + queue.pop_front(); + warn!( + "Buffered packet queue at cap for {}. Dropping oldest packet before enqueue", + ip + ); + } + queue.push_back((Instant::now(), pkt.clone())); + if queue.len() == 1 || queue.len().is_multiple_of(256) { + info!( + "Buffered packet queue for {} now has {} packets", + ip, + queue.len() + ); + } + } +} diff --git a/src/router.rs b/src/router.rs index 4a7384f..77c463b 100644 --- a/src/router.rs +++ b/src/router.rs @@ -1,42 +1,49 @@ -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 std::{ + collections::{BTreeMap, BTreeSet}, + net::Ipv4Addr, + time::Duration, }; -use anyhow::{Context, Result, bail}; -use iroh::{Endpoint, EndpointAddr, EndpointId, SecretKey}; +use ed25519_dalek::SigningKey; use iroh_gossip::net::Gossip; +use iroh_topic_tracker::{ + TopicDiscoveryConfig, TopicDiscoveryExt, TopicDiscoveryHandle, TopicDiscoveryHook, +}; +use rand::Rng; use serde::{Deserialize, Serialize}; use sha2::Digest; -use tracing::{debug, info}; +use tracing::{debug, info, trace, warn}; + +use anyhow::{Result, bail}; +use iroh::{Endpoint, EndpointId, SecretKey}; + +use actor_helper::{Action, Handle, Receiver, act, act_ok}; + +use crate::kv::{Kv, KvEvent}; -use actor_helper::{Action, Actor, Handle, act, act_ok}; +const CANDIDATE_PHASE_DURATION: Duration = Duration::from_secs(10); +const VERIFY_IP_DURATION: Duration = Duration::from_secs(5); #[derive(Debug, Clone)] pub struct Builder { + topic_discovery_hook: TopicDiscoveryHook, 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 new(topic_discovery_hook: TopicDiscoveryHook) -> Builder { + Builder { + topic_discovery_hook, + entry_name: String::default(), + secret_key: SecretKey::generate(), + password: String::default(), + endpoint: None, + gossip: None, + } } pub fn entry_name(mut self, entry_name: &str) -> Self { @@ -49,11 +56,6 @@ impl Builder { 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 @@ -69,16 +71,6 @@ impl Builder { 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() @@ -90,12 +82,6 @@ impl Builder { } 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) @@ -108,86 +94,51 @@ impl Builder { 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 topic_discovery_config = + TopicDiscoveryConfig::builder(signing_key, self.topic_discovery_hook.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)) = 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; + } }; - 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); + info!("Joined topic with hash: {:x?}", topic_hash); - 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 kv = Kv::spawn(endpoint.id(), gossip_sender, gossip_receiver); - 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, + let (api, _) = Handle::spawn_with( + RouterActor { + kv, + _endpoint: endpoint.clone(), endpoint_id: endpoint.id(), - _topic: Some(topic), - rx, - blobs, + topic: topic_handle, my_ip: RouterIp::NoIp, - }; - router_actor.run().await - }); - + assignments: BTreeMap::new(), + candidates: BTreeMap::new(), + startup_entries: BTreeSet::new(), + }, + |mut actor, rx| async move { actor.run(rx).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, @@ -197,36 +148,34 @@ pub struct Router { pub enum RouterIp { NoIp, AquiringIp(IpCandidate, tokio::time::Instant), + VerifyingIp(Ipv4Addr, 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 kv: Kv, + pub(crate) _endpoint: Endpoint, pub endpoint_id: EndpointId, - pub(crate) _topic: Option, + pub(crate) topic: Option, pub my_ip: RouterIp, + + assignments: BTreeMap, + candidates: BTreeMap>, + startup_entries: BTreeSet, } impl Router { - pub fn builder() -> Builder { - Builder::new() + pub fn builder(topic_discovery_hook: TopicDiscoveryHook) -> Builder { + Builder::new(topic_discovery_hook) } pub async fn get_ip_state(&self) -> Result { self.api .call(act_ok!(actor => async move { - actor.my_ip.clone() + actor.my_ip.clone() })) .await } @@ -234,7 +183,7 @@ impl Router { pub async fn get_node_id(&self) -> Result { self.api .call(act_ok!(actor => async move { - actor.endpoint_id + actor.endpoint_id })) .await } @@ -256,16 +205,14 @@ impl Router { .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)); - } + let assignments = actor.read_all_ip_assignments(true)?; + 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); - } + let cands = actor.read_all_ip_candidates(true)?; + for c in cands { + map.entry(c.endpoint_id).or_insert(None); } map.remove(&actor.endpoint_id); @@ -274,212 +221,397 @@ impl Router { })) .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)); +impl RouterActor { + async fn run(&mut self, rx: Receiver>) -> Result<()> { + let mut ip_tick = tokio::time::interval(Duration::from_millis(1000)); ip_tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip); + debug!("RouterActor started. EndpointId: {}", self.endpoint_id); + + let mut last_ip_state = self.my_ip.clone(); + + let mut kv_sub = self.kv.subscribe(); + self.populate_from_kv().await; + loop { tokio::select! { - Ok(action) = self.rx.recv_async() => { + Ok(action) = rx.recv_async() => { action(self).await; } _ = tokio::signal::ctrl_c() => { + info!("Received Ctrl-C, stopping RouterActor"); break } + result = kv_sub.recv() => { + match result { + Ok(event) => { + self.handle_kv_event(&event); + } + Err(tokio::sync::broadcast::error::RecvError::Lagged(n)) => { + warn!("[ROUTER_LOOP] kv_sub lagged by {} messages!", n); + } + Err(tokio::sync::broadcast::error::RecvError::Closed) => { + warn!("[ROUTER_LOOP] kv_sub channel closed!"); + 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); + _ = ip_tick.tick() => { + if self.startup_entries.len() < 2 { + + // Write our startup entry (immediately broadcast via gossip). + let startup_key = format!("{}{}", key_startup_prefix(), self.endpoint_id); + trace!("[ROUTER_LOOP] Calling kv.insert for startup"); + self.kv.insert(&startup_key).await; + trace!("[ROUTER_LOOP] kv.insert completed"); + trace!("Not advancing IP state, waiting for startup entries. Current count: {}", self.startup_entries.len()); + continue; + } + match self.advance_ip_state().await { + Ok(_) => { + if self.my_ip != last_ip_state { + info!("Router IP state changed: {:?} -> {:?}", last_ip_state, self.my_ip); + last_ip_state = self.my_ip.clone(); + } + }, + Err(e) => { + warn!("Error advancing IP state: {}", e); + } } } } } - + warn!("RouterActor stopped."); Ok(()) } } +impl RouterActor { + async fn populate_from_kv(&mut self) { + let all_entries = self.kv.query_all_entries().await; + for (key, timestamp) in all_entries { + self.apply_key(&key, timestamp); + } + debug!( + "Populated from Kv: {} startup, {} assignments, {} candidate IPs", + self.startup_entries.len(), + self.assignments.len(), + self.candidates.len(), + ); + } + + fn handle_kv_event(&mut self, event: &KvEvent) { + self.apply_key(&event.key, event.timestamp); + } + + fn apply_key(&mut self, key: &str, timestamp: u64) { + let startup_prefix = key_startup_prefix(); + let assigned_prefix = key_assigned_ip(); + let candidate_prefix = key_candidate_ip_prefix(); + + if key.starts_with(&startup_prefix) { + if let Ok(endpoint_id) = decode_endpoint_id_from_startup(key) + && self.startup_entries.insert(endpoint_id) + { + info!( + "Startup entry added for {}. Total: {}", + endpoint_id, + self.startup_entries.len() + ); + } + } else if key.starts_with(&assigned_prefix) { + if let Ok(ip_assignment) = decode_ip_assignment(key, timestamp) { + self.assignments.insert(ip_assignment.ip, ip_assignment); + } + } else if key.starts_with(&candidate_prefix) + && let Ok(ip_candidate) = decode_ip_candidate(key, timestamp) + { + self.candidates + .entry(ip_candidate.ip) + .or_default() + .insert(ip_candidate.endpoint_id, ip_candidate); + } + } +} + +fn current_time() -> u64 { + chrono::Utc::now().timestamp() as u64 +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct IpAssignment { pub ip: Ipv4Addr, pub endpoint_id: EndpointId, + pub last_updated: u64, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct IpCandidate { pub ip: Ipv4Addr, pub endpoint_id: EndpointId, + pub last_updated: u64, +} + +impl IpAssignment { + pub fn is_stale(&self) -> bool { + is_stale(self.last_updated, RouterActor::ASSIGNMENT_STALE_SECS) + } } -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") +impl IpCandidate { + pub fn is_stale(&self) -> bool { + is_stale(self.last_updated, RouterActor::CANDIDATE_STALE_SECS) + } } -fn query(q: impl Into) -> impl Into { - QueryBuilder::::default() - .key_exact(q.into()) - .build() +fn is_stale(last_updated: u64, stale_secs: u64) -> bool { + current_time().saturating_sub(last_updated) > stale_secs } -fn query_prefix(q: impl Into) -> impl Into { - QueryBuilder::::default() - .key_prefix(q.into()) - .build() +fn decode_ip_assignment(key: &str, timestamp: u64) -> Result { + let parts: Vec<&str> = key.split('/').collect(); + if parts.len() != 5 { + warn!( + "Invalid key format for IpAssignment (invalid length): {}", + key + ); + anyhow::bail!("Invalid key format for IpAssignment"); + } + if let (Ok(ip), Ok(endpoint_id)) = + (parts[3].parse::(), parts[4].parse::()) + { + Ok(IpAssignment { + ip, + endpoint_id, + last_updated: timestamp, + }) + } else { + warn!( + "Failed to parse IpAssignment from key (parse failed): {}", + key + ); + anyhow::bail!("Invalid key format for IpAssignment"); + } } -fn key_ip_assigned(ip: Ipv4Addr) -> String { - format!("/assigned/ip/{ip}") +fn encode_ip_assignment(assignment: &IpAssignment) -> String { + format!("/assigned/ip/{}/{}", assignment.ip, assignment.endpoint_id) } -fn key_ip_assigned_prefix() -> String { +fn key_assigned_ip() -> String { "/assigned/ip/".to_string() } -fn key_ip_candidate(ip: Ipv4Addr, endpoint_id: EndpointId) -> String { - format!("/candidates/ip/{ip}/{endpoint_id}") +fn decode_ip_candidate(key: &str, timestamp: u64) -> Result { + let parts: Vec<&str> = key.split('/').collect(); + if parts.len() != 5 { + warn!( + "Invalid key format for IpCandidate (invalid length): {}", + key + ); + anyhow::bail!("Invalid key format for IpCandidate"); + } + if let (Ok(ip), Ok(endpoint_id)) = + (parts[3].parse::(), parts[4].parse::()) + { + Ok(IpCandidate { + ip, + endpoint_id, + last_updated: timestamp, + }) + } else { + warn!( + "Failed to parse IpCandidate from key (parse failed): {}", + key + ); + anyhow::bail!("Invalid key format for IpCandidate"); + } +} + +fn encode_ip_candidate(candidate: &IpCandidate) -> String { + format!("/candidates/ip/{}/{}", candidate.ip, candidate.endpoint_id) +} + +fn decode_endpoint_id_from_startup(key: &str) -> Result { + let parts: Vec<&str> = key.split('/').collect(); + if parts.len() != 3 { + warn!( + "Invalid key format for startup entry (invalid length): {}", + key + ); + anyhow::bail!("Invalid key format for startup entry"); + } + if let Ok(endpoint_id) = parts[2].parse::() { + Ok(endpoint_id) + } else { + warn!( + "Failed to parse EndpointId from startup key (parse failed): {}", + key + ); + anyhow::bail!("Invalid key format for startup entry"); + } } -fn key_ip_candidate_prefix() -> String { +fn key_candidate_ip_prefix() -> String { "/candidates/ip/".to_string() } -fn key_prefix_ip_candidates(ip: Ipv4Addr) -> String { - format!("/candidates/ip/{ip}/") +fn key_startup_prefix() -> String { + "/startup/".to_string() } 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); - } + const ASSIGNMENT_STALE_SECS: u64 = 300; + const CANDIDATE_STALE_SECS: u64 = 60; + const IP_RANGES: [(usize, Ipv4Addr); u16::MAX as usize - 2] = { + let mut data = [(0, Ipv4Addr::UNSPECIFIED); u16::MAX as usize - 2]; + let mut order = 2usize; + while order < u16::MAX as usize { + let octet3 = (order >> 8) as u8; + let octet4 = (order & 0xFF) as u8; + data[order - 2] = (order, Ipv4Addr::new(172, 30, octet3, octet4)); + order += 1; } + data + }; - Ok(assignments) + fn is_initialized(&self) -> bool { + self.startup_entries.len() >= 2 } - 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()) + fn read_all_ip_assignments(&self, filter_stale: bool) -> Result> { + if !self.is_initialized() { + warn!( + "[Kv] read_all_ip_assignments called before initialized. Startup entries count: {}", + self.startup_entries.len() + ); + bail!("[Kv] not initialized yet"); + } + Ok(self + .assignments + .values() + .filter(|assignment| !filter_stale || !assignment.is_stale()) .cloned() - .collect::>(); + .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); - } + fn read_all_ip_candidates(&self, filter_stale: bool) -> Result> { + if !self.is_initialized() { + warn!( + "[Kv] read_all_ip_candidates called before initialized. Startup entries count: {}", + self.startup_entries.len() + ); + bail!("[Kv] not initialized yet"); } - - Ok(candidates) + Ok(self + .candidates + .values() + .flatten() + .filter(|(_, candidate)| !filter_stale || !candidate.is_stale()) + .map(|(_, candidate)| candidate.clone()) + .collect::>()) } // 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") + fn read_ip_assignment(&self, ip: Ipv4Addr, filter_stale: bool) -> Result> { + if !self.is_initialized() { + warn!( + "[Kv] read_ip_assignment called before initialized. Startup entries count: {}", + self.startup_entries.len() + ); + bail!("[Kv] not initialized yet"); + } + let mut assignments = self + .assignments + .iter() + .filter(|(_, assignment)| !filter_stale || !assignment.is_stale()) + .map(|(_, assignment)| assignment) + .collect::>(); + assignments.sort_by_key(|a| a.last_updated); + Ok(assignments.into_iter().rev().find(|a| a.ip == ip).cloned()) } // 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); - } - } + fn read_ip_candidates(&self, ip: Ipv4Addr, filter_stale: bool) -> Result> { + if !self.is_initialized() { + warn!( + "[Kv] read_ip_candidates called before initialized. Startup entries count: {}", + self.startup_entries.len() + ); + bail!("[Kv] not initialized yet"); } - - Ok(candidates) + let mut ip_candidates = match self.candidates.get(&ip) { + Some(candidates) => candidates + .values() + .filter(|candidate| !filter_stale || !candidate.is_stale()) + .cloned() + .collect::>(), + None => vec![], + }; + ip_candidates.sort_by_key(|candidate| candidate.last_updated); + debug!("candidates for {ip}: {}", ip_candidates.len()); + Ok(ip_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"); + async fn write_ip_assignment( + &mut self, + ip: Ipv4Addr, + endpoint_id: EndpointId, + force_override: bool, + ) -> Result<()> { + if !self.is_initialized() { + warn!( + "[Kv] write_ip_assignment called before initialized. Startup entries count: {}", + self.startup_entries.len() + ); + bail!("[Kv] not initialized yet"); } + info!("Attempting to assign IP {} to {}", ip, endpoint_id); - 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() - }); + let existing_assignment = self.read_ip_assignment(ip, true)?; - if candidates[0].endpoint_id != endpoint_id { - bail!("not the chosen candidate"); + if let Some(existing) = &existing_assignment { + if existing.endpoint_id != endpoint_id && !force_override { + anyhow::bail!("ip already assigned to another node"); + } + } else { + // New assignment. check for multiple candidates + let candidates = self.read_ip_candidates(ip, true)?; + if candidates + .iter() + .filter(|c| if c.endpoint_id != self.endpoint_id && self.endpoint_id < c.endpoint_id { + debug!( + "Existing candidate {} has higher priority than us for IP {}. Not writing new candidate.", + c.endpoint_id, ip + ); + true + } else { + false + }) + .count() + > 0 + || !candidates.iter().any(|c| c.endpoint_id == self.endpoint_id) + { + bail!("no candidates for this ip"); + } } // 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; + debug!("Winning candidate for IP {}. Writing assignment.", ip); + let now = current_time(); + let ip_assignment = IpAssignment { + ip, + endpoint_id, + last_updated: now, + }; + self.kv.insert(encode_ip_assignment(&ip_assignment)).await; + debug!("Wrote IP assignment {} for {}.", ip, endpoint_id); Ok(()) } @@ -490,40 +622,60 @@ impl RouterActor { ip: Ipv4Addr, endpoint_id: EndpointId, ) -> Result { + if !self.is_initialized() { + warn!( + "[Kv] write_ip_candidate called before initialized. Startup entries count: {}", + self.startup_entries.len() + ); + bail!("[Kv] not initialized yet"); + } // already assigned? don't write - if self.read_ip_assignment(ip).await.is_ok() { - anyhow::bail!("ip already assigned"); + if let Some(assignment) = self.read_ip_assignment(ip, true)? + && assignment.endpoint_id != endpoint_id + && self.endpoint_id < assignment.endpoint_id + { + anyhow::bail!("ip assignment 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) { + if let Ok(candidates) = self.read_ip_candidates(ip, true) + && candidates + .iter() + .filter(|c| if c.endpoint_id != self.endpoint_id && self.endpoint_id < c.endpoint_id { + debug!( + "Existing candidate {} has higher priority than us for IP {}. Not writing new candidate.", + c.endpoint_id, ip + ); + true + } else { + false + }) + .count() + > 0 + { 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?; + let now = current_time(); + let candidate = IpCandidate { + ip, + endpoint_id, + last_updated: now, + }; + self.kv.insert(encode_ip_candidate(&candidate)).await; + debug!("Wrote IP candidate {} for {}.", ip, endpoint_id); + 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) + self.read_ip_assignment(ip, true)? .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? + self.read_all_ip_assignments(true)? .iter() .find(|assignment| assignment.endpoint_id == endpoint_id) .map(|a| a.ip) @@ -533,9 +685,19 @@ impl RouterActor { impl RouterActor { async fn advance_ip_state(&mut self) -> Result { + trace!("Advancing IP state. Current: {:?}", self.my_ip); match self.my_ip.clone() { RouterIp::NoIp => { let next_ip = self.get_next_ip().await?; + info!("Trying to acquire IP candidate: {}", next_ip); + + if self.read_ip_assignment(next_ip, true)?.is_some() { + debug!( + "IP {} already assigned to another node. Skipping candidate write.", + next_ip + ); + return Ok(false); + } self.my_ip = RouterIp::AquiringIp( self.write_ip_candidate(next_ip, self.endpoint_id).await?, @@ -544,57 +706,214 @@ impl RouterActor { 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; + let elapsed = start_time.elapsed(); + + debug!( + "RouterIp::AquiringIp: {:?}", + self.read_ip_candidates(ip_candidate.ip, true)? + ); + if let Ok(candidates) = self.read_ip_candidates(ip_candidate.ip, true) + && candidates.iter().any(|c| { + c.endpoint_id != self.endpoint_id + && (self.endpoint_id < c.endpoint_id + || (self.endpoint_id >= c.endpoint_id + && current_time().saturating_sub(c.last_updated) + > CANDIDATE_PHASE_DURATION.as_secs())) + }) + { + warn!( + "Conflict detected for {:?} during acquisition wait. Aborting.", + ip_candidate.ip + ); + self.my_ip = RouterIp::NoIp; + return Ok(false); + } + + if let Ok(Some(assignment)) = self.read_ip_assignment(ip_candidate.ip, true) + && assignment.endpoint_id != self.endpoint_id + && (self.endpoint_id < assignment.endpoint_id + || (self.endpoint_id >= assignment.endpoint_id + && current_time().saturating_sub(assignment.last_updated) + > VERIFY_IP_DURATION.as_secs())) + { + warn!( + "IP {} got assigned to {} during acquisition wait. Aborting.", + ip_candidate.ip, assignment.endpoint_id + ); + self.my_ip = RouterIp::NoIp; + return Ok(false); + } + + self.write_ip_candidate(ip_candidate.ip, self.endpoint_id) + .await?; + + // Wait at least 5 seconds + if elapsed > CANDIDATE_PHASE_DURATION { + // Jitter: 20% chance to proceed per tick (approx 500ms) + if rand::rng().random_bool(0.2) { + // if we are connected to peers that we don't yet see in any of the candidate records, + // that leaves the risk of a potential collision, so we wait until we see all currently connected peers in at least one of the candidates + if let Some(peers) = + self.topic.as_ref().map(|topic| topic.get_connected_peers()) + { + let all_candidates = self.read_all_ip_candidates(true)?; + if peers + .iter() + .all(|p| all_candidates.iter().any(|c| c.endpoint_id == *p)) + { + debug!( + "All connected peers are visible in candidates for IP {}. Proceeding with acquisition.", + ip_candidate.ip + ); + } else { + warn!( + "Not all connected peers are visible in candidates for IP {}. Waiting longer to avoid potential collision.", + ip_candidate.ip + ); + return Ok(false); + } + } else { + return Ok(false); + } + + info!( + "Attempting to finalize IP assignment for {}", + ip_candidate.ip + ); + if self + .write_ip_assignment(ip_candidate.ip, ip_candidate.endpoint_id, false) + .await + .is_ok() + { + info!( + "Written assignment for IP: {}. Verifying...", + ip_candidate.ip + ); + self.my_ip = + RouterIp::VerifyingIp(ip_candidate.ip, tokio::time::Instant::now()); + } else { + warn!( + "Failed to write assignment for {}. Restarting negotiation.", + ip_candidate.ip + ); + self.my_ip = RouterIp::NoIp; + } } } Ok(false) } - _ => Ok(true), + RouterIp::VerifyingIp(ip, start_time) => { + // Wait 2 seconds to ensure propagation + if start_time.elapsed() > VERIFY_IP_DURATION { + trace!("Verifying IP assignment logic for {}", ip); + let assignment = self.read_ip_assignment(ip, true)?; + match assignment { + Some(a) if a.endpoint_id == self.endpoint_id => { + info!("Verified ownership of IP: {}", ip); + self.my_ip = RouterIp::AssignedIp(ip); + } + _ => { + warn!( + "Verification failed for IP: {}. Lost to another node or ghost.", + ip + ); + self.my_ip = RouterIp::NoIp; + } + } + } + Ok(false) + } + RouterIp::AssignedIp(my_ip) => { + match self.read_ip_assignment(my_ip, true)? { + Some(ip_assignment) => { + if ip_assignment.endpoint_id != self.endpoint_id { + if ip_assignment.endpoint_id < self.endpoint_id { + if current_time().saturating_sub(ip_assignment.last_updated) > 30 { + info!("Refreshing IP assignment for {}", my_ip); + if let Err(e) = self + .write_ip_assignment(my_ip, self.endpoint_id, true) + .await + { + warn!("Failed to refresh IP assignment: {}", e); + // Don't lose IP immediately, retry next tick + } + } + Ok(true) + } else { + self.my_ip = RouterIp::NoIp; + warn!( + "Lost IP assignment for {}. Expected owner: {}, Found: {}. Restarting negotiation.", + my_ip, self.endpoint_id, ip_assignment.endpoint_id + ); + Ok(false) + } + } else { + // Refresh if needed (every 30s) + if current_time().saturating_sub(ip_assignment.last_updated) > 30 { + info!("Refreshing IP assignment for {}", my_ip); + if let Err(e) = self + .write_ip_assignment(my_ip, self.endpoint_id, false) + .await + { + warn!("Failed to refresh IP assignment: {}", e); + // Don't lose IP immediately, retry next tick + } + } + Ok(true) + } + } + None => { + self.my_ip = RouterIp::NoIp; + warn!("Assignment lost/deleted for {}. Restarting.", my_ip); + Ok(false) + } + } + } } } 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 mut next_ip_range = Self::IP_RANGES.to_vec(); - let all_ips = all_assigned - .iter() - .map(|assigned| assigned.ip) - .chain(all_candidates.iter().map(|candidate| candidate.ip)) - .collect::>(); + for assignment in self.read_all_ip_assignments(false)? { + let index = ((u16::from(assignment.ip.octets()[2]) << 8) + | u16::from(assignment.ip.octets()[3])) as usize + - 2; + next_ip_range[index].0 += u16::MAX as usize; // push used IPs to the end of the list + } - 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") - }; + for candidate in self.read_all_ip_candidates(false)? { + let index = ((u16::from(candidate.ip.octets()[2]) << 8) + | u16::from(candidate.ip.octets()[3])) as usize + - 2; + next_ip_range[index].0 += u16::MAX as usize; // push used IPs to the end of the list + } - 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 - }, - ); + for assignment in self.read_all_ip_assignments(true)? { + let index = ((u16::from(assignment.ip.octets()[2]) << 8) + | u16::from(assignment.ip.octets()[3])) as usize + - 2; + next_ip_range[index].0 = 0; // order == 0 => taken + } - // 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"); + for candidate in self.read_all_ip_candidates(true)? { + let index = ((u16::from(candidate.ip.octets()[2]) << 8) + | u16::from(candidate.ip.octets()[3])) as usize + - 2; + next_ip_range[index].0 = 0; // order == 0 => taken } - Ok(next_ip) + + next_ip_range.sort_by_key(|(order, _)| *order); + info!("Next IP range order: {:?}", &next_ip_range[..10]); + next_ip_range + .iter() + .find_map(|(order, ip)| { + if *order == 0 || ip.octets()[3] == 255 { + None + } else { + Some(*ip) + } + }) + .ok_or_else(|| anyhow::anyhow!("No available IPs")) } } diff --git a/ui/src-tauri/Cargo.lock b/ui/src-tauri/Cargo.lock index dd3692a..2a635e1 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" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" +checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b" 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" +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" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "hpke" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65d16b699dd1a1fa2d851c970b0c971b388eeeb40f744252b8de48860980c8f" -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" @@ -2770,11 +2954,10 @@ dependencies = [ [[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 +2966,7 @@ dependencies = [ "hyper", "hyper-util", "log", - "rand 0.9.2", + "rand 0.10.1", "tokio", "url", "xmltree", @@ -2802,13 +2985,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 +3023,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 +3069,49 @@ dependencies = [ [[package]] name = "iroh" -version = "0.95.1" +version = "0.98.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2374ba3cdaac152dc6ada92d971f7328e6408286faab3b7350842b2ebbed4789" +checksum = "9382a37668c84823e94b52eee462b3133ca7252a28de5f619a989d48b69cb30b" dependencies = [ - "aead 0.6.0-rc.2", "backon", + "blake3", "bytes", "cfg_aliases", - "crypto_box", + "ctutils", "data-encoding", - "derive_more 2.0.1", + "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 +3120,80 @@ dependencies = [ "url", "wasm-bindgen-futures", "webpki-roots", - "z32", ] [[package]] -name = "iroh-base" -version = "0.95.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a8c5fb1cc65589f0d7ab44269a76f615a8c4458356952c9b0ef1c93ea45ff8" +name = "iroh-auth" +version = "0.2.0-pre.1" +source = "git+https://github.com/rustonbsd/iroh-auth?rev=70c7bca92bae179212fe6088105ca3025490fff4#70c7bca92bae179212fe6088105ca3025490fff4" dependencies = [ - "curve25519-dalek 5.0.0-pre.1", - "data-encoding", - "derive_more 2.0.1", - "ed25519-dalek", - "n0-error", - "rand_core 0.9.3", - "serde", - "url", - "zeroize", - "zeroize_derive", + "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-blobs" -version = "0.97.0" +name = "iroh-base" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c901304c1c28f257fcf9aae8c9149e54e0baf62f5eb2788cecde3bf1206a04e6" +checksum = "738865784637830fb14204ebd3047922db83bc1816a59027af29579b9c27bd99" dependencies = [ - "anyhow", - "arrayvec", - "bao-tree", - "bytes", - "cfg_aliases", - "chrono", + "curve25519-dalek 5.0.0-pre.6", "data-encoding", - "derive_more 2.0.1", - "futures-lite", - "genawaiter", - "hex", - "iroh", - "iroh-base", - "iroh-io", - "iroh-metrics", - "iroh-quinn", - "iroh-tickets", - "irpc", + "data-encoding-macro", + "derive_more 2.1.1", + "digest 0.11.2", + "ed25519-dalek", + "getrandom 0.4.2", "n0-error", - "n0-future", - "n0-snafu", - "nested_enum_utils", - "postcard", - "rand 0.9.2", - "range-collections", - "redb", - "ref-cast", - "reflink-copy", - "self_cell", + "rand 0.10.1", "serde", - "smallvec", - "snafu", - "tokio", - "tracing", + "sha2 0.11.0-rc.5", + "url", + "zeroize", + "zeroize_derive", ] [[package]] -name = "iroh-docs" -version = "0.95.0" +name = "iroh-dns" +version = "0.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fe6dc5524c65b401ebb5de204af8921c8cb329316eb972538622d708b4636c" +checksum = "ca474630d1e62ddef83149db6babe6a1055d901df9054349d31b22df99811b92" 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", + "derive_more 2.1.1", + "iroh-base", "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 +3201,37 @@ 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" dependencies = [ "actor-helper", "anyhow", - "distributed-topic-tracker", + "bytes", + "chrono", + "clap", + "crossterm", "ed25519-dalek", "futures", "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 +3240,13 @@ dependencies = [ "tracing", "tracing-subscriber", "tun-rs", + "url", "z32", ] [[package]] name = "iroh-lan-ui" -version = "0.1.1" +version = "1.0.0" dependencies = [ "anyhow", "iroh-lan", @@ -3137,21 +3256,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 +3280,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=58320f1d3e6c46cc0e6bfce9e1c8f0f79a92a94a#58320f1d3e6c46cc0e6bfce9e1c8f0f79a92a94a" 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 +3379,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 +3407,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 +3460,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 = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +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 = "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 +3559,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 +3589,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 +3637,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 +3653,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 +3693,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 +3748,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 +3776,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 +3794,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 +3836,7 @@ checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3664,9 +3856,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 +3881,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 +3899,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 +3960,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 +3991,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 +4041,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 +4153,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 +4173,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 +4219,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 +4232,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 +4265,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 +4375,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 +4385,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 +4416,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]] @@ -4243,144 +4535,119 @@ dependencies = [ [[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", -] - -[[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" +[[package]] +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 +4656,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 +4668,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 +4679,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 +4722,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 +4740,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 +4750,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 +4773,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 +4788,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 +4908,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 +4918,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 +4945,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4663,107 +4972,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.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" +checksum = "12922b6296c06eb741b02d7b5161e3aaa22864af38dfa025a1a3ba3f68c84577" 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 +5059,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4826,37 +5098,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 +5117,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 +5149,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 +5161,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 +5183,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,53 +5217,53 @@ 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 = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +checksum = "23370be78b7e5bcbb0cab4a02047eb040279a693c78daad04c2c5f1c24a83503" dependencies = [ - "elliptic-curve", + "either", + "ipnet", + "num-traits", ] [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "prettyplease" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ - "once_cell", - "toml_edit 0.19.15", + "proc-macro2", + "syn 2.0.117", ] [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ - "toml_edit 0.20.7", + "once_cell", + "toml_edit 0.19.15", ] [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" dependencies = [ - "toml_edit 0.22.27", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", ] [[package]] -name = "proc-macro-error" -version = "0.4.12" +name = "proc-macro-crate" +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 +5272,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 +5298,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 +5349,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 +5377,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 +5388,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 +5434,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,84 +5452,140 @@ 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.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", ] [[package]] -name = "rand_core" -version = "0.9.3" +name = "ratatui" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" dependencies = [ - "getrandom 0.3.3", + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termwiz", + "ratatui-widgets", ] [[package]] -name = "rand_hc" -version = "0.2.0" +name = "ratatui-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ - "rand_core 0.5.1", + "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 = "rand_pcg" -version = "0.2.1" +name = "ratatui-crossterm" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" dependencies = [ - "rand_core 0.5.1", + "cfg-if", + "crossterm", + "instability", + "ratatui-core", ] [[package]] -name = "range-collections" -version = "0.4.6" +name = "ratatui-macros" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861706ea9c4aded7584c5cd1d241cec2ea7f5f50999f236c22b65409a1f1a0d0" +checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" dependencies = [ - "binary-merge", - "inplace-vec-builder", - "ref-cast", - "serde", - "smallvec", + "ratatui-core", + "ratatui-widgets", ] [[package]] -name = "raw-window-handle" -version = "0.6.2" +name = "ratatui-termwiz" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" +dependencies = [ + "ratatui-core", + "termwiz", +] [[package]] -name = "rcgen" -version = "0.14.5" +name = "ratatui-widgets" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fae430c6b28f1ad601274e78b7dffa0546de0b73b4cd32f46723c0c2a16f7a5" +checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" dependencies = [ - "pem", - "ring", - "rustls-pki-types", + "bitflags 2.11.1", + "hashbrown 0.16.1", + "indoc", + "instability", + "itertools", + "line-clipping", + "ratatui-core", + "strum 0.27.2", "time", - "yasna", + "unicode-segmentation", + "unicode-width", ] [[package]] -name = "redb" -version = "2.6.3" +name = "raw-window-handle" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eca1e9d98d5a7e9002d0013e18d5a9b000aee942eb134883a82f06ebffb6c01" -dependencies = [ - "libc", -] +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 +5594,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 +5633,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 +5644,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 = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +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 +5671,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 +5725,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 +5743,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 +5817,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 +5854,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 +5863,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 +5891,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 +5903,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 +5913,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 +5928,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 +5940,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 +5957,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 +5972,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 +6008,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 +6027,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5710,25 +6043,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 +6072,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 +6120,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 +6146,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 +6170,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 +6195,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5873,19 +6206,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 +6231,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5910,11 +6245,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 +6266,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 +6285,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 +6314,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6003,17 +6327,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 +6340,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 +6370,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 +6435,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,89 +6446,63 @@ 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" 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", +dependencies = [ + "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 +6529,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 +6549,7 @@ checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6238,19 +6569,19 @@ checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" [[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 = "static_assertions" @@ -6291,45 +6622,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 +6692,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 +6718,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 +6751,7 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml 0.8.23", + "toml 0.8.2", "version-compare", ] @@ -6454,35 +6763,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 +6807,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 +6834,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 +6863,7 @@ dependencies = [ "tauri-runtime", "tauri-runtime-wry", "tauri-utils", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tray-icon", "url", @@ -6563,9 +6876,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 +6892,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 +6914,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 +6925,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 +6950,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 +7000,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 +7025,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 +7052,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 +7080,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 +7090,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 +7124,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 +7197,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 +7212,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 +7237,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 +7271,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 +7281,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 +7296,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 +7334,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 +7346,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 +7360,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 +7383,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 +7441,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 +7503,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 +7533,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 +7545,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 +7577,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 +7595,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 +7623,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 +7635,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 +7655,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 +7719,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 +7758,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 +7770,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 +7799,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 +7836,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 +7922,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 +7963,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 +8015,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 +8070,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 +8161,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 +8193,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 +8299,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 +8321,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 +8340,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 +8448,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7875,7 +8459,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7910,6 +8494,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 +8583,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 +8643,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 +8678,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 +8705,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 +8729,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 +8753,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 +8765,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 +8789,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 +8813,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 +8837,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 +8861,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 +8876,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 +8904,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 +9035,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 +9051,7 @@ dependencies = [ "sha2 0.10.9", "soup3", "tao-macros", - "thiserror 2.0.16", + "thiserror 2.0.18", "url", "webkit2gtk", "webkit2gtk-sys", @@ -8393,12 +9075,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 +9111,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 +9126,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 +9139,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 +9157,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 +9175,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 +9192,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 +9207,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 +9268,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 +9290,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 +9301,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..3296ad5 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,6 +25,7 @@ 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" @@ -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..d01bb2a 100644 --- a/ui/src-tauri/src/lib.rs +++ b/ui/src-tauri/src/lib.rs @@ -1,19 +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) }); @@ -53,6 +48,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 +95,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 +108,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 +146,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::ConnState::Disconnected); peer_infos.push(PeerInfo { node_id: peer.0.to_string(), ip: match peer.1 { @@ -151,10 +166,10 @@ async fn list_peers() -> Result, 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::ConnState::ClosedAndStopped => Status::Disconnected, }, }); } @@ -174,7 +189,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 +199,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") {