diff --git a/Cargo.lock b/Cargo.lock index 75a44e1e50..b2fcd97bf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,6 +86,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "bytes", + "crypto-common", + "generic-array", +] + [[package]] name = "ahash" version = "0.8.7" @@ -160,6 +171,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_log-sys" version = "0.3.1" @@ -257,12 +274,18 @@ dependencies = [ "objc", "objc-foundation", "objc_id", - "parking_lot 0.12.1", + "parking_lot", "thiserror", "winapi", "x11rb", ] +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + [[package]] name = "arrayvec" version = "0.7.4" @@ -278,6 +301,84 @@ dependencies = [ "libloading 0.7.4", ] +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive 0.4.0", + "asn1-rs-impl 0.1.0", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" +dependencies = [ + "asn1-rs-derive 0.5.0", + "asn1-rs-impl 0.2.0", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "synstructure 0.13.0", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -303,25 +404,6 @@ dependencies = [ "slab", ] -[[package]] -name = "async-io" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite 2.3.0", - "parking", - "polling 3.5.0", - "rustix", - "slab", - "tracing", - "windows-sys 0.52.0", -] - [[package]] name = "async-lock" version = "3.3.0" @@ -339,6 +421,17 @@ version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "atomic-arena" version = "0.1.1" @@ -360,12 +453,34 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf53d6c43ea3fa42a5d18d6060081bcfddeca7c63faa64e65a59c4372bbe173b" +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http 0.2.12", + "log", + "url", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom", + "instant", + "rand", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -381,12 +496,47 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "bao-tree" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f7a89a8ee5889d2593ae422ce6e1bb03e48a0e8a16e4fa0882dfcbe7e182ef" +dependencies = [ + "bytes", + "futures-lite 2.3.0", + "genawaiter", + "iroh-blake3", + "iroh-io", + "positioned-io", + "range-collections", + "self_cell 1.0.3", + "smallvec", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bevy" version = "0.11.3" @@ -444,7 +594,7 @@ dependencies = [ "downcast-rs", "fastrand 1.9.0", "js-sys", - "parking_lot 0.12.1", + "parking_lot", "serde", "thiserror", "wasm-bindgen", @@ -822,7 +972,7 @@ dependencies = [ "erased-serde 0.3.31", "glam 0.24.2", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "serde", "smallvec", "smol_str", @@ -907,7 +1057,7 @@ dependencies = [ "js-sys", "naga", "naga_oil", - "parking_lot 0.12.1", + "parking_lot", "regex", "serde", "smallvec", @@ -1130,6 +1280,12 @@ dependencies = [ "winit", ] +[[package]] +name = "binary-merge" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" + [[package]] name = "bincode" version = "1.3.3" @@ -1205,6 +1361,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f421f1bcb30aa9d851a03c2920ab5d96ca920d5786645a597b5fc37922f8b89e" +[[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 = "block" version = "0.1.6" @@ -1344,13 +1512,14 @@ dependencies = [ "either", "fluent", "fluent-langneg", - "futures-lite 2.3.0", "ggrs", "glam 0.24.2", "hex", "image", "instant", "intl-memoizer", + "iroh-net", + "iroh-quinn", "kira", "mdns-sd", "noise", @@ -1358,15 +1527,14 @@ dependencies = [ "once_cell", "ping-rs", "postcard", - "quinn", - "quinn_runtime_bevy", - "rcgen", + "rcgen 0.12.1", "rustls", "serde", "serde_yaml", "smallvec", "sys-locale", "thiserror", + "tokio", "tracing", "ttf-parser", "unic-langid", @@ -1385,23 +1553,20 @@ name = "bones_matchmaker" version = "0.2.0" dependencies = [ "anyhow", - "async-io", - "bevy_tasks 0.11.3", "bones_matchmaker_proto", "bytes", "clap", "either", "futures", - "futures-lite 2.3.0", + "iroh-net", + "iroh-quinn", "once_cell", "postcard", - "quinn", - "quinn_runtime_bevy", "rand", - "rcgen", - "rustls", + "rcgen 0.12.1", "scc", "serde", + "tokio", "tracing", "tracing-subscriber", ] @@ -1410,6 +1575,7 @@ dependencies = [ name = "bones_matchmaker_proto" version = "0.2.0" dependencies = [ + "iroh-net", "serde", ] @@ -1468,7 +1634,7 @@ dependencies = [ "hashbrown 0.14.3", "instant", "maybe-owned", - "parking_lot 0.12.1", + "parking_lot", "serde", "smallvec", "turborand", @@ -1484,6 +1650,12 @@ dependencies = [ "venial", ] +[[package]] +name = "bounded-integer" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a6932c88f1d2c29533a3b8a5f5a2f84cc19c3339b431677c3160c5c2e6ca85" + [[package]] name = "branches" version = "0.1.3" @@ -1574,6 +1746,41 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.5", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clang-sys" version = "1.7.0" @@ -1699,6 +1906,32 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + [[package]] name = "const_panic" version = "0.2.8" @@ -1711,6 +1944,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + [[package]] name = "constgebra" version = "0.1.3" @@ -1798,7 +2037,7 @@ dependencies = [ "ndk-context", "oboe", "once_cell", - "parking_lot 0.12.1", + "parking_lot", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1814,6 +2053,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.3.2" @@ -1844,6 +2098,18 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1851,9 +2117,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "crypto_box" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009" +dependencies = [ + "aead", + "chacha20", + "crypto_secretbox", + "curve25519-dalek", + "salsa20", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "chacha20", + "cipher", + "generic-array", + "poly1305", + "salsa20", + "subtle", + "zeroize", +] + [[package]] name = "csscolorparser" version = "0.6.2" @@ -1863,6 +2162,34 @@ dependencies = [ "phf", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "d3d12" version = "0.6.0" @@ -1884,7 +2211,7 @@ dependencies = [ "hashbrown 0.14.3", "lock_api", "once_cell", - "parking_lot_core 0.9.9", + "parking_lot_core", ] [[package]] @@ -1932,19 +2259,91 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.3.11" +name = "der" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ - "powerfmt", + "const-oid", + "der_derive", + "zeroize", ] [[package]] -name = "diff" -version = "0.1.13" +name = "der-parser" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs 0.5.2", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der-parser" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs 0.6.1", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_more" +version = "1.0.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7abbfc297053be59290e3152f8cbcd52c8642e0728b69ee187d991d4c1af08d" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0-beta.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "unicode-xid", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -1953,7 +2352,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", ] [[package]] @@ -1994,6 +2395,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "libc", + "once_cell", + "winapi", +] + [[package]] name = "document-features" version = "0.2.8" @@ -2009,6 +2421,38 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "ecolor" version = "0.23.0" @@ -2018,6 +2462,32 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "serde", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "egui" version = "0.23.0" @@ -2058,6 +2528,25 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "elsa" version = "1.10.0" @@ -2123,6 +2612,38 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "enumflags2" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "epaint" version = "0.23.0" @@ -2135,7 +2656,7 @@ dependencies = [ "ecolor", "emath", "nohash-hasher", - "parking_lot 0.12.1", + "parking_lot", ] [[package]] @@ -2163,14 +2684,10 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.8" +name = "erased_set" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] +checksum = "76a5aa24577083f8190ad401e376b55887c7cd9083ae95d83ceec5d28ea78125" [[package]] name = "error-code" @@ -2218,6 +2735,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "fastrand" version = "1.9.0" @@ -2242,6 +2765,22 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "filetime" version = "0.2.23" @@ -2326,6 +2865,9 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ + "futures-core", + "futures-sink", + "nanorand", "spin 0.9.8", ] @@ -2368,6 +2910,12 @@ dependencies = [ "libc", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.30" @@ -2383,6 +2931,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-buffered" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de8419e65098e54c06f5ae8a130a79e8ba2e391ff995d260ca5d77ea72ab2fe3" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -2393,6 +2952,20 @@ dependencies = [ "futures-sink", ] +[[package]] +name = "futures-concurrency" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ee14e256b9143bfafbf2fddeede6f396650bacf95d06fc1b3f2b503df129a0" +dependencies = [ + "bitvec", + "futures-core", + "futures-lite 1.13.0", + "pin-project", + "slab", + "smallvec", +] + [[package]] name = "futures-core" version = "0.3.30" @@ -2467,6 +3040,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.30" @@ -2515,7 +3094,38 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.48", - "synstructure", + "synstructure 0.13.0", +] + +[[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]] @@ -2526,6 +3136,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -2561,7 +3172,7 @@ dependencies = [ "bytemuck", "instant", "js-sys", - "parking_lot 0.12.1", + "parking_lot", "rand", "serde", ] @@ -2653,6 +3264,26 @@ dependencies = [ "web-sys", ] +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand", + "smallvec", + "spinning_top", +] + [[package]] name = "gpu-alloc" version = "0.5.4" @@ -2705,6 +3336,17 @@ dependencies = [ "bitflags 2.4.1", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + [[package]] name = "guillotiere" version = "0.6.2" @@ -2715,6 +3357,25 @@ dependencies = [ "svg_fmt", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hash32" version = "0.2.1" @@ -2776,6 +3437,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" @@ -2799,40 +3466,321 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] -name = "home" -version = "0.5.9" +name = "hickory-proto" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" dependencies = [ - "windows-sys 0.52.0", + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", ] [[package]] -name = "humantime" -version = "2.1.0" +name = "hickory-resolver" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] [[package]] -name = "idna" -version = "0.5.0" +name = "hmac" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "digest", ] [[package]] -name = "if-addrs" -version = "0.10.2" +name = "hmac-sha1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" +checksum = "6b05da5b9e5d4720bfb691eebb2b9d42da3570745da71eac8a1f5bb7e59aab88" +dependencies = [ + "hmac", + "sha1", +] + +[[package]] +name = "hmac-sha256" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3688e69b38018fec1557254f64c8dc2cc8ec502890182f395dbb0aa997aa5735" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "hostname-validator" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.28", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "socket2 0.5.7", + "tokio", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "if-addrs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" dependencies = [ "libc", "windows-sys 0.48.0", ] +[[package]] +name = "igd-next" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" +dependencies = [ + "async-trait", + "attohttpc", + "bytes", + "futures", + "http 0.2.12", + "hyper 0.14.28", + "log", + "rand", + "tokio", + "url", + "xmltree", +] + [[package]] name = "image" version = "0.24.7" @@ -2901,6 +3849,24 @@ dependencies = [ "libc", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-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.12" @@ -2942,6 +3908,219 @@ dependencies = [ "mach2", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.7", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "iroh-base" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a1a5323b25a181b1434a44f9f59ebc478d21156cf9bf91aa850ad0d626f833" +dependencies = [ + "aead", + "anyhow", + "bao-tree", + "crypto_box", + "data-encoding", + "derive_more", + "ed25519-dalek", + "hex", + "once_cell", + "postcard", + "rand", + "rand_core", + "serde", + "serde-error", + "ssh-key", + "thiserror", + "ttl_cache", + "url", + "zeroize", +] + +[[package]] +name = "iroh-blake3" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbba31f40a650f58fa28dd585a8ca76d8ae3ba63aacab4c8269004a0c803930" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "iroh-io" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d1047ad5ca29ab4ff316b6830d86e7ea52cea54325e4d4a849692e1274b498" +dependencies = [ + "bytes", + "futures-lite 2.3.0", + "pin-project", +] + +[[package]] +name = "iroh-metrics" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b4f668653628979461eabe56853a694b1eb4713e87ed25f2224618165c0e67" +dependencies = [ + "anyhow", + "erased_set", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "once_cell", + "prometheus-client", + "reqwest", + "serde", + "struct_iterable", + "time", + "tokio", + "tracing", +] + +[[package]] +name = "iroh-net" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bea6e221dfbe6301965a5ec9b6bae2c156375a4baafdbdbad7a93c3dcf950d6" +dependencies = [ + "aead", + "anyhow", + "backoff", + "bytes", + "der", + "derive_more", + "duct", + "flume", + "futures-buffered", + "futures-concurrency", + "futures-lite 2.3.0", + "futures-sink", + "futures-util", + "governor", + "hex", + "hickory-proto", + "hickory-resolver", + "hostname", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "igd-next", + "iroh-base", + "iroh-metrics", + "iroh-quinn", + "iroh-quinn-proto", + "iroh-quinn-udp", + "libc", + "netdev", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", + "num_enum 0.7.2", + "once_cell", + "parking_lot", + "pin-project", + "pkarr", + "postcard", + "rand", + "rand_core", + "rcgen 0.11.3", + "reqwest", + "ring 0.17.7", + "rtnetlink", + "rustls", + "rustls-webpki", + "serde", + "smallvec", + "socket2 0.5.7", + "strum", + "stun-rs", + "surge-ping", + "thiserror", + "time", + "tokio", + "tokio-rustls", + "tokio-rustls-acme", + "tokio-util", + "tracing", + "url", + "watchable", + "webpki-roots", + "windows 0.51.1", + "wmi", + "x509-parser 0.15.1", + "z32", +] + +[[package]] +name = "iroh-quinn" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b934380145fd5d53a583d01ae9500f4807efe6b0f0fe115c7be4afa2b35db99f" +dependencies = [ + "bytes", + "iroh-quinn-proto", + "iroh-quinn-udp", + "pin-project-lite", + "rustc-hash", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "iroh-quinn-proto" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f2656b322c7f6cf3eb95e632d1c0f2fa546841915b0270da581f918c70c4be" +dependencies = [ + "bytes", + "rand", + "ring 0.16.20", + "rustc-hash", + "rustls", + "rustls-native-certs", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "iroh-quinn-udp" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6679979a7271c24f9dae9622c0b4a543881508aa3a7396f55dfbaaa56f01c063" +dependencies = [ + "bytes", + "libc", + "socket2 0.5.7", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "itoa" version = "1.0.10" @@ -3073,6 +4252,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lazycell" @@ -3145,10 +4327,10 @@ dependencies = [ ] [[package]] -name = "linux-raw-sys" -version = "0.4.13" +name = "linked-hash-map" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "litrs" @@ -3172,6 +4354,15 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "lyon_algorithms" version = "1.0.4" @@ -3232,6 +4423,12 @@ dependencies = [ "libc", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.1.0" @@ -3247,6 +4444,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + [[package]] name = "mdns-sd" version = "0.10.4" @@ -3255,10 +4458,16 @@ checksum = "1961985d2b8f6764565cfe77916f7926aabb6b377cfb5ddf191f7e34136b547f" dependencies = [ "flume", "if-addrs", - "polling 2.8.0", + "polling", "socket2 0.4.10", ] +[[package]] +name = "memalloc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1" + [[package]] name = "memchr" version = "2.7.1" @@ -3288,6 +4497,12 @@ dependencies = [ "objc", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3344,52 +4559,143 @@ dependencies = [ ] [[package]] -name = "naga_oil" -version = "0.8.2" +name = "naga_oil" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be942a5c21c58b9b0bf4d9b99db3634ddb7a916f8e1d1d0b71820cc4150e56b" +dependencies = [ + "bit-set", + "codespan-reporting", + "data-encoding", + "indexmap 1.9.3", + "naga", + "once_cell", + "regex", + "regex-syntax 0.6.29", + "rustc-hash", + "thiserror", + "tracing", + "unicode-ident", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ndk" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +dependencies = [ + "bitflags 1.3.2", + "jni-sys", + "ndk-sys", + "num_enum 0.5.11", + "raw-window-handle", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.4.1+23.1.7779620" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "netdev" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb353f5a5a852d5cc779c1c80bec0bd14a696ef832f3a761cb10091802c37109" +dependencies = [ + "dlopen2", + "libc", + "memalloc", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", + "once_cell", + "system-configuration 0.6.0", + "windows 0.54.0", +] + +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be942a5c21c58b9b0bf4d9b99db3634ddb7a916f8e1d1d0b71820cc4150e56b" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" dependencies = [ - "bit-set", - "codespan-reporting", - "data-encoding", - "indexmap 1.9.3", - "naga", - "once_cell", - "regex", - "regex-syntax 0.6.29", - "rustc-hash", - "thiserror", - "tracing", - "unicode-ident", + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", ] [[package]] -name = "ndk" -version = "0.7.0" +name = "netlink-packet-utils" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum 0.5.11", - "raw-window-handle", + "anyhow", + "byteorder", + "paste", "thiserror", ] [[package]] -name = "ndk-context" -version = "0.1.1" +name = "netlink-proto" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" +checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "thiserror", + "tokio", +] [[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" +name = "netlink-sys" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" dependencies = [ - "jni-sys", + "bytes", + "futures", + "libc", + "log", + "tokio", ] [[package]] @@ -3426,6 +4732,18 @@ dependencies = [ "libc", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -3459,6 +4777,12 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "notify" version = "6.1.1" @@ -3497,6 +4821,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -3510,11 +4861,21 @@ dependencies = [ [[package]] name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", + "num-integer", "num-traits", ] @@ -3531,14 +4892,24 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "num_enum" version = "0.5.11" @@ -3557,6 +4928,15 @@ dependencies = [ "num_enum_derive 0.6.1", ] +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive 0.7.2", +] + [[package]] name = "num_enum_derive" version = "0.5.11" @@ -3581,6 +4961,18 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "numquant" version = "0.2.0" @@ -3684,6 +5076,24 @@ dependencies = [ "cc", ] +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs 0.5.2", +] + +[[package]] +name = "oid-registry" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" +dependencies = [ + "asn1-rs 0.6.1", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -3698,10 +5108,16 @@ checksum = "8f2d1d09016ea926b4a8c89938674322fca80bc139d605b21a574c0ce1000a19" dependencies = [ "ahash", "hashbrown 0.14.3", - "parking_lot 0.12.1", + "parking_lot", "stable_deref_trait", ] +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl-probe" version = "0.1.5" @@ -3723,6 +5139,16 @@ dependencies = [ "libredox 0.0.2", ] +[[package]] +name = "os_pipe" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "overload" version = "0.1.1" @@ -3739,44 +5165,57 @@ dependencies = [ ] [[package]] -name = "parking" -version = "2.2.0" +name = "p256" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] [[package]] -name = "parking_lot" -version = "0.11.2" +name = "p384" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", ] [[package]] -name = "parking_lot" -version = "0.12.1" +name = "p521" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" dependencies = [ - "lock_api", - "parking_lot_core 0.9.9", + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core", + "sha2", ] [[package]] -name = "parking_lot_core" -version = "0.8.6" +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "lock_api", + "parking_lot_core", ] [[package]] @@ -3828,16 +5267,70 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64", + "base64 0.21.7", "serde", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "petgraph" version = "0.6.4" @@ -3935,26 +5428,112 @@ checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ping-rs" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d873f038f84371f9c7fa13f6afea4d5f1fbcd5070ba8eb7af2a6d41c768eff8b" +dependencies = [ + "futures", + "mio", + "paste", + "socket2 0.4.10", + "windows 0.43.0", +] + +[[package]] +name = "pkarr" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "242ae92dfb9d2ba3aaa9caf4723e72043bc50729ad05a763771771ba03196ffb" +dependencies = [ + "bytes", + "ed25519-dalek", + "rand", + "reqwest", + "self_cell 1.0.3", + "simple-dns", + "thiserror", + "url", + "z32", +] + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" + +[[package]] +name = "platforms" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + +[[package]] +name = "pnet_base" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_macros" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.48", +] [[package]] -name = "ping-rs" -version = "0.1.2" +name = "pnet_macros_support" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d873f038f84371f9c7fa13f6afea4d5f1fbcd5070ba8eb7af2a6d41c768eff8b" +checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" dependencies = [ - "futures", - "mio", - "paste", - "socket2 0.4.10", - "windows 0.43.0", + "pnet_base", ] [[package]] -name = "pkg-config" -version = "0.3.28" +name = "pnet_packet" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba" +dependencies = [ + "glob", + "pnet_base", + "pnet_macros", + "pnet_macros_support", +] [[package]] name = "png" @@ -3986,17 +5565,30 @@ dependencies = [ ] [[package]] -name = "polling" -version = "3.5.0" +name = "poly1305" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" dependencies = [ - "cfg-if", - "concurrent-queue", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.52.0", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "positioned-io" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccabfeeb89c73adf4081f0dca7f8e28dbda90981a222ceea37f619e93ea6afe9" +dependencies = [ + "libc", + "winapi", ] [[package]] @@ -4006,11 +5598,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" dependencies = [ "cobs", + "const_format", "embedded-io", "heapless", + "postcard-derive", "serde", ] +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -4032,6 +5637,40 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precis-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d73e9dd26361c32e7cd13d1032bb01c4e26a23287274e8a4e2f228cf2c9ff77b" +dependencies = [ + "precis-tools", + "ucd-parse", + "unicode-normalization", +] + +[[package]] +name = "precis-profiles" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde4bd6624c60cb0abe2bea1dbdbb9085f629a853861e64df4abb099f8076ad4" +dependencies = [ + "lazy_static", + "precis-core", + "precis-tools", + "unicode-normalization", +] + +[[package]] +name = "precis-tools" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07ecadec70b0f560f09abf815ae0ee1a940d38d2354c938ba7229ac7c9f5f52" +dependencies = [ + "lazy_static", + "regex", + "ucd-parse", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -4042,6 +5681,15 @@ dependencies = [ "yansi", ] +[[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 = "1.3.1" @@ -4052,11 +5700,43 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-error" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "syn-mid", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -4068,66 +5748,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135ede8821cf6376eb7a64148901e1690b788c11ae94dc297ae917dbc91dc0e" [[package]] -name = "quinn" -version = "0.10.2" +name = "prometheus-client" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" +checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" dependencies = [ - "bytes", - "futures-io", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "thiserror", - "tokio", - "tracing", + "dtoa", + "itoa", + "parking_lot", + "prometheus-client-derive-encode", ] [[package]] -name = "quinn-proto" -version = "0.10.6" +name = "prometheus-client-derive-encode" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ - "bytes", - "rand", - "ring 0.16.20", - "rustc-hash", - "rustls", - "rustls-native-certs", - "slab", - "thiserror", - "tinyvec", - "tracing", + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] -name = "quinn-udp" -version = "0.4.1" +name = "quanta" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" dependencies = [ - "bytes", + "crossbeam-utils", "libc", - "socket2 0.5.5", - "tracing", - "windows-sys 0.48.0", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", ] [[package]] -name = "quinn_runtime_bevy" -version = "0.3.0" -dependencies = [ - "async-executor", - "async-io", - "bevy_tasks 0.11.3", - "futures-lite 2.3.0", - "pin-project", - "quinn", - "quinn-udp", -] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" @@ -4138,6 +5800,22 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "quoted-string-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc75379cdb451d001f1cb667a9f74e8b355e9df84cc5193513cbe62b96fc5e9" +dependencies = [ + "pest", + "pest_derive", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "radsort" version = "0.1.0" @@ -4189,12 +5867,45 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" +[[package]] +name = "range-collections" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca9edd21e2db51000ac63eccddabba622f826e631a60be7bade9bd6a76b69537" +dependencies = [ + "binary-merge", + "inplace-vec-builder", + "ref-cast", + "smallvec", +] + +[[package]] +name = "raw-cpuid" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" +dependencies = [ + "bitflags 2.4.1", +] + [[package]] name = "raw-window-handle" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "rcgen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" +dependencies = [ + "pem", + "ring 0.16.20", + "time", + "yasna", +] + [[package]] name = "rcgen" version = "0.12.1" @@ -4213,15 +5924,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.3.5" @@ -4251,6 +5953,26 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "regex" version = "1.10.2" @@ -4283,6 +6005,12 @@ dependencies = [ "regex-syntax 0.8.2", ] +[[package]] +name = "regex-lite" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" + [[package]] name = "regex-syntax" version = "0.6.29" @@ -4301,6 +6029,67 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration 0.5.1", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "ring" version = "0.16.20" @@ -4340,15 +6129,54 @@ dependencies = [ ] [[package]] -name = "ron" -version = "0.8.1" +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.4.1", + "serde", + "serde_derive", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rtnetlink" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ - "base64", - "bitflags 2.4.1", - "serde", - "serde_derive", + "futures", + "log", + "netlink-packet-core", + "netlink-packet-route", + "netlink-packet-utils", + "netlink-proto", + "netlink-sys", + "nix 0.26.4", + "thiserror", + "tokio", ] [[package]] @@ -4373,16 +6201,12 @@ dependencies = [ ] [[package]] -name = "rustix" -version = "0.38.31" +name = "rusticata-macros" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", + "nom", ] [[package]] @@ -4415,7 +6239,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] @@ -4428,12 +6252,27 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "rustversion" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" + [[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -4474,6 +6313,20 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.9.2" @@ -4536,6 +6389,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-error" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e988182713aeed6a619a88bca186f6d6407483485ffe44c869ee264f8eabd13f" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.195" @@ -4558,6 +6420,18 @@ dependencies = [ "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", +] + [[package]] name = "serde_yaml" version = "0.9.30" @@ -4571,6 +6445,27 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" @@ -4591,18 +6486,56 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + [[package]] name = "simd-adler32" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simple-dns" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01607fe2e61894468c6dc0b26103abb073fb08b79a3d9e4b6d76a1a341549958" +dependencies = [ + "bitflags 2.4.1", +] + [[package]] name = "siphasher" version = "0.3.11" @@ -4629,9 +6562,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] @@ -4657,12 +6590,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4680,6 +6613,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.2.0+1.5.4" @@ -4690,12 +6632,64 @@ dependencies = [ "num-traits", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "sptr" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher", + "ssh-encoding", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "pem-rfc7468", + "sha2", +] + +[[package]] +name = "ssh-key" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafc" +dependencies = [ + "ed25519-dalek", + "p256", + "p384", + "p521", + "rand_core", + "rsa", + "sec1", + "sha2", + "signature", + "ssh-cipher", + "ssh-encoding", + "subtle", + "zeroize", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4720,6 +6714,103 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "struct_iterable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "849a064c6470a650b72e41fa6c057879b68f804d113af92900f27574828e7712" +dependencies = [ + "struct_iterable_derive", + "struct_iterable_internal", +] + +[[package]] +name = "struct_iterable_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb939ce88a43ea4e9d012f2f6b4cc789deb2db9d47bad697952a85d6978662c" +dependencies = [ + "erased-serde 0.3.31", + "proc-macro2", + "quote", + "struct_iterable_internal", + "syn 2.0.48", +] + +[[package]] +name = "struct_iterable_internal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9426b2a0c03e6cc2ea8dbc0168dbbf943f88755e409fb91bcb8f6a268305f4a" + +[[package]] +name = "strum" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.48", +] + +[[package]] +name = "stun-rs" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adebf9fb8fba5c39ee34092b0383f247e4d1255b98fcffec94b4b797b85b677" +dependencies = [ + "base64 0.22.1", + "bounded-integer", + "byteorder", + "crc", + "enumflags2", + "fallible-iterator", + "hmac-sha1", + "hmac-sha256", + "hostname-validator", + "lazy_static", + "md5", + "paste", + "precis-core", + "precis-profiles", + "quoted-string-parser", + "rand", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "surge-ping" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbf95ce4c7c5b311d2ce3f088af2b93edef0f09727fa50fbe03c7a979afce77" +dependencies = [ + "hex", + "parking_lot", + "pnet_packet", + "rand", + "socket2 0.5.7", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "svg_fmt" version = "0.4.1" @@ -4873,46 +6964,123 @@ version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "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 = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", + "unicode-xid", +] + +[[package]] +name = "sys-locale" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.29.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "winapi", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys 0.5.0", ] [[package]] -name = "synstructure" -version = "0.13.0" +name = "system-configuration" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", - "unicode-xid", + "bitflags 2.4.1", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] -name = "sys-locale" -version = "0.3.1" +name = "system-configuration-sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ + "core-foundation-sys", "libc", ] [[package]] -name = "sysinfo" -version = "0.29.11" +name = "system-configuration-sys" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ - "cfg-if", "core-foundation-sys", "libc", - "ntapi", - "once_cell", - "winapi", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "termcolor" version = "1.4.1" @@ -4924,18 +7092,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", @@ -4970,9 +7138,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", + "itoa", "powerfmt", "serde", "time-core", + "time-macros", ] [[package]] @@ -4981,6 +7151,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +[[package]] +name = "time-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +dependencies = [ + "time-core", +] + [[package]] name = "tinystr" version = "0.7.5" @@ -5007,12 +7186,82 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.5.7", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-rustls-acme" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ebc06d846f8367f24c3a8882328707d1a5e507ef4f40943723ddbe2c17b9f24" +dependencies = [ + "async-trait", + "base64 0.21.7", + "chrono", + "futures", + "log", + "num-bigint", + "pem", + "proc-macro2", + "rcgen 0.12.1", + "reqwest", + "ring 0.17.7", + "rustls", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-rustls", + "url", + "webpki-roots", + "x509-parser 0.16.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", "pin-project-lite", + "tokio", ] [[package]] @@ -5043,12 +7292,19 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5126,12 +7382,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "ttf-parser" version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +[[package]] +name = "ttl_cache" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4189890526f0168710b6ee65ceaedf1460c48a14318ceec933cb26baa492096a" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "turborand" version = "0.10.0" @@ -5175,6 +7446,21 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-parse" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9" +dependencies = [ + "regex-lite", +] + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "ulid" version = "1.1.0" @@ -5237,6 +7523,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "unsafe-libyaml" version = "0.2.10" @@ -5261,7 +7557,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" dependencies = [ - "base64", + "base64 0.21.7", "flate2", "log", "once_cell", @@ -5278,8 +7574,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna", + "idna 0.5.0", "percent-encoding", + "serde", ] [[package]] @@ -5291,7 +7588,7 @@ dependencies = [ "ahash", "byteorder", "lazy_static", - "parking_lot 0.12.1", + "parking_lot", "serde", ] @@ -5361,6 +7658,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5433,6 +7739,18 @@ version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +[[package]] +name = "watchable" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45b42a2f611916b5965120a9cde2b60f2db4454826dd9ad5e6f47c24a5b3b259" +dependencies = [ + "event-listener 4.0.3", + "futures-util", + "parking_lot", + "thiserror", +] + [[package]] name = "wayland-scanner" version = "0.29.5" @@ -5494,7 +7812,7 @@ dependencies = [ "js-sys", "log", "naga", - "parking_lot 0.11.2", + "parking_lot", "profiling", "raw-window-handle", "smallvec", @@ -5519,7 +7837,7 @@ dependencies = [ "codespan-reporting", "log", "naga", - "parking_lot 0.11.2", + "parking_lot", "profiling", "raw-window-handle", "rustc-hash", @@ -5558,7 +7876,7 @@ dependencies = [ "metal", "naga", "objc", - "parking_lot 0.11.2", + "parking_lot", "profiling", "range-alloc", "raw-window-handle", @@ -5668,8 +7986,18 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.48.0", + "windows-interface 0.48.0", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", "windows-targets 0.48.5", ] @@ -5679,8 +8007,29 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", - "windows-targets 0.52.0", + "windows-core 0.52.0", + "windows-implement 0.52.0", + "windows-interface 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -5689,7 +8038,17 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.5", ] [[package]] @@ -5703,6 +8062,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "windows-implement" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "windows-interface" version = "0.48.0" @@ -5714,6 +8084,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "windows-interface" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "windows-result" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -5738,7 +8128,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -5773,17 +8163,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -5800,9 +8191,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -5818,9 +8209,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -5836,9 +8227,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -5854,9 +8251,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -5872,9 +8269,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -5890,9 +8287,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -5908,9 +8305,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winit" @@ -5951,6 +8348,39 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wmi" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f0a4062ca522aad4705a2948fd4061b3857537990202a8ddd5af21607f79a" +dependencies = [ + "chrono", + "futures", + "log", + "serde", + "thiserror", + "windows 0.52.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11-dl" version = "2.21.0" @@ -5984,12 +8414,55 @@ dependencies = [ "nix 0.26.4", ] +[[package]] +name = "x509-parser" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" +dependencies = [ + "asn1-rs 0.5.2", + "data-encoding", + "der-parser 8.2.0", + "lazy_static", + "nom", + "oid-registry 0.6.1", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "x509-parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +dependencies = [ + "asn1-rs 0.6.1", + "data-encoding", + "der-parser 9.0.0", + "lazy_static", + "nom", + "oid-registry 0.7.0", + "rusticata-macros", + "thiserror", + "time", +] + [[package]] name = "xml-rs" version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + [[package]] name = "yansi" version = "0.5.1" @@ -6005,6 +8478,12 @@ dependencies = [ "time", ] +[[package]] +name = "z32" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb37266251c28b03d08162174a91c3a092e3bd4f476f8205ee1c507b78b7bdc" + [[package]] name = "zerocopy" version = "0.7.32" @@ -6024,3 +8503,9 @@ dependencies = [ "quote", "syn 2.0.48", ] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/framework_crates/bones_framework/Cargo.toml b/framework_crates/bones_framework/Cargo.toml index 151da949de..d6d6bc60cb 100644 --- a/framework_crates/bones_framework/Cargo.toml +++ b/framework_crates/bones_framework/Cargo.toml @@ -78,7 +78,6 @@ async-channel = "1.9" bevy_tasks = "0.11" bytemuck = "1.12" either = "1.8" -futures-lite = "2.3" glam = "0.24" hex = "0.4" instant = { version = "0.1", features = ["wasm-bindgen"] } @@ -129,5 +128,6 @@ postcard = { version = "1.0", features = ["alloc"] } rcgen = "0.12" rustls = { version = "0.21", features = ["dangerous_configuration", "quic"] } smallvec = "1.10" -quinn = { version = "0.10", default-features = false, features = ["native-certs", "tls-rustls"] } -quinn_runtime_bevy = { version = "0.3", path = "../../other_crates/quinn_runtime_bevy" } +iroh-quinn = { version = "0.10" } +iroh-net = { version = "0.16" } +tokio = { version = "1", features = ["rt-multi-thread", "macros"] } diff --git a/framework_crates/bones_framework/src/networking.rs b/framework_crates/bones_framework/src/networking.rs index 8f614e7d23..c92522763d 100644 --- a/framework_crates/bones_framework/src/networking.rs +++ b/framework_crates/bones_framework/src/networking.rs @@ -2,6 +2,7 @@ use std::{fmt::Debug, marker::PhantomData, sync::Arc}; +use bones_matchmaker_proto::{MATCH_ALPN, PLAY_ALPN}; use ggrs::{NetworkStats, P2PSession, PlayerHandle}; use instant::Duration; use once_cell::sync::Lazy; @@ -12,15 +13,20 @@ use crate::prelude::*; use self::{ debug::{NetworkDebugMessage, NETWORK_DEBUG_CHANNEL}, input::{DenseInput, NetworkInputConfig, NetworkPlayerControl, NetworkPlayerControls}, + socket::Socket, }; use crate::input::PlayerControls as PlayerControlsTrait; -pub mod certs; pub mod debug; pub mod input; pub mod lan; pub mod online; pub mod proto; +pub mod socket; + +/// Runtime, needed to execute network related calls. +pub static RUNTIME: Lazy = + Lazy::new(|| tokio::runtime::Runtime::new().expect("unable to crate tokio runtime")); /// Indicates if input from networking is confirmed, predicted, or if player is disconnected. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -45,7 +51,7 @@ impl From for NetworkInputStatus { /// Module prelude. pub mod prelude { - pub use super::{certs, debug::prelude::*, input, lan, online, proto, NetworkInfo}; + pub use super::{debug::prelude::*, input, lan, online, proto, NetworkInfo, RUNTIME}; } /// Muliplier for framerate that will be used when playing an online match. @@ -66,12 +72,8 @@ pub const NETWORK_MAX_PREDICTION_WINDOW_DEFAULT: usize = 7; /// Amount of frames GGRS will delay local input. pub const NETWORK_LOCAL_INPUT_DELAY_DEFAULT: usize = 2; -// TODO: Remove this limitation on max players, a variety of types use this for static arrays, -// should either figure out how to make this a compile-time const value specified by game, or -// use dynamic arrays. -// -/// Max players in networked game -pub const MAX_PLAYERS: usize = 4; +#[doc(inline)] +pub use bones_matchmaker_proto::MAX_PLAYERS; /// Possible errors returned by network loop. pub enum NetworkError { @@ -92,40 +94,32 @@ impl ggrs::Config for GgrsConfig { type Address = usize; } -/// The network endpoint used for all QUIC network communications. -pub static NETWORK_ENDPOINT: Lazy = Lazy::new(|| { - // Generate certificate - let (cert, key) = certs::generate_self_signed_cert().unwrap(); - - let mut transport_config = quinn::TransportConfig::default(); - transport_config.keep_alive_interval(Some(std::time::Duration::from_secs(5))); - - let mut server_config = quinn::ServerConfig::with_single_cert([cert].to_vec(), key).unwrap(); - server_config.transport = Arc::new(transport_config); - - // Open Socket and create endpoint - let port = THREAD_RNG.with(|rng| rng.u16(10000..=11000)); - info!(port, "Started network endpoint"); - let socket = std::net::UdpSocket::bind(("0.0.0.0", port)).unwrap(); - - let client_config = rustls::ClientConfig::builder() - .with_safe_defaults() - .with_custom_certificate_verifier(certs::SkipServerVerification::new()) - .with_no_client_auth(); - let client_config = quinn::ClientConfig::new(Arc::new(client_config)); - - let mut endpoint = quinn::Endpoint::new( - quinn::EndpointConfig::default(), - Some(server_config), - socket, - Arc::new(quinn_runtime_bevy::BevyIoTaskPoolExecutor), - ) - .unwrap(); - - endpoint.set_default_client_config(client_config); - - endpoint -}); +/// The network endpoint used for all network communications. +static NETWORK_ENDPOINT: tokio::sync::OnceCell = + tokio::sync::OnceCell::const_new(); + +/// Get the network endpoint used for all communications. +pub async fn get_network_endpoint() -> &'static iroh_net::MagicEndpoint { + NETWORK_ENDPOINT + .get_or_init(|| async move { + let secret_key = iroh_net::key::SecretKey::generate(); + iroh_net::MagicEndpoint::builder() + .alpns(vec![MATCH_ALPN.to_vec(), PLAY_ALPN.to_vec()]) + .discovery(Box::new( + iroh_net::discovery::ConcurrentDiscovery::from_services(vec![ + Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()), + Box::new(iroh_net::discovery::pkarr_publish::PkarrPublisher::n0_dns( + secret_key.clone(), + )), + ]), + )) + .secret_key(secret_key) + .bind(0) + .await + .unwrap() + }) + .await +} /// Resource containing the [`NetworkSocket`] implementation while there is a connection to a /// network game. @@ -135,17 +129,6 @@ pub static NETWORK_ENDPOINT: Lazy = Lazy::new(|| { #[schema(no_default)] pub struct NetworkMatchSocket(Arc); -/// A type-erased [`ggrs::NonBlockingSocket`] -/// implementation. -#[derive(Deref, DerefMut)] -pub struct BoxedNonBlockingSocket(Box); - -impl Clone for BoxedNonBlockingSocket { - fn clone(&self) -> Self { - self.ggrs_socket() - } -} - /// Wraps [`ggrs::Message`] with included `match_id`, used to determine if message received /// from current match. #[derive(Serialize, Deserialize, Debug, Clone)] @@ -160,23 +143,13 @@ pub struct GameMessage { pub trait GgrsSocket: NetworkSocket + ggrs::NonBlockingSocket {} impl GgrsSocket for T where T: NetworkSocket + ggrs::NonBlockingSocket {} -impl ggrs::NonBlockingSocket for BoxedNonBlockingSocket { - fn send_to(&mut self, msg: &ggrs::Message, addr: &usize) { - self.0.send_to(msg, addr) - } - - fn receive_all_messages(&mut self) -> Vec<(usize, ggrs::Message)> { - self.0.receive_all_messages() - } -} - /// Trait that must be implemented by socket connections establish by matchmakers. /// /// The [`NetworkMatchSocket`] resource will contain an instance of this trait and will be used by /// the game to send network messages after a match has been established. pub trait NetworkSocket: Sync + Send { /// Get a GGRS socket from this network socket. - fn ggrs_socket(&self) -> BoxedNonBlockingSocket; + fn ggrs_socket(&self) -> Socket; /// Send a reliable message to the given [`SocketTarget`]. fn send_reliable(&self, target: SocketTarget, message: &[u8]); /// Receive reliable messages from other players. The `usize` is the index of the player that @@ -216,7 +189,7 @@ pub struct NetworkInfo { pub last_confirmed_frame: i32, /// Socket - pub socket: BoxedNonBlockingSocket, + pub socket: Socket, } /// [`SessionRunner`] implementation that uses [`ggrs`] for network play. @@ -251,7 +224,7 @@ pub struct GgrsSessionRunner<'a, InputTypes: NetworkInputConfig<'a>> { pub input_collector: InputTypes::InputCollector, /// Store copy of socket to be able to restart session runner with existing socket. - socket: BoxedNonBlockingSocket, + socket: Socket, /// Local input delay ggrs session was initialized with local_input_delay: usize, @@ -261,7 +234,7 @@ pub struct GgrsSessionRunner<'a, InputTypes: NetworkInputConfig<'a>> { #[derive(Clone)] pub struct GgrsSessionRunnerInfo { /// The socket that will be converted into GGRS socket implementation. - pub socket: BoxedNonBlockingSocket, + pub socket: Socket, /// The list of local players. pub player_is_local: [bool; MAX_PLAYERS], /// the player count. @@ -282,12 +255,12 @@ pub struct GgrsSessionRunnerInfo { impl GgrsSessionRunnerInfo { /// See [`GgrsSessionRunnerInfo`] fields for info on arguments. pub fn new( - socket: BoxedNonBlockingSocket, + socket: Socket, max_prediction_window: Option, local_input_delay: Option, ) -> Self { - let player_is_local = socket.0.player_is_local(); - let player_count = socket.0.player_count(); + let player_is_local = socket.player_is_local(); + let player_count = socket.player_count(); Self { socket, player_is_local, @@ -591,7 +564,7 @@ where // Increment match id so messages from previous match that are still in flight // will be filtered out. - self.socket.0.increment_match_id(); + self.socket.increment_match_id(); let runner_info = GgrsSessionRunnerInfo { socket: self.socket.clone(), diff --git a/framework_crates/bones_framework/src/networking/certs.rs b/framework_crates/bones_framework/src/networking/certs.rs deleted file mode 100644 index 066fa3e123..0000000000 --- a/framework_crates/bones_framework/src/networking/certs.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! QUIC certificate utilities. -//! -//! - -use std::sync::Arc; - -/// Implementation of `ServerCertVerifier` that verifies everything as trustworthy. -/// -/// This allows us to connect to servers without having to worry about domain verification. -/// -/// TODO: In the future we may want to do domain verification, but allow opting out of it. -pub struct SkipServerVerification; - -impl SkipServerVerification { - /// Make new [`SkipServerVerification`]. - pub fn new() -> Arc { - Arc::new(Self) - } -} - -impl rustls::client::ServerCertVerifier for SkipServerVerification { - fn verify_server_cert( - &self, - _end_entity: &rustls::Certificate, - _intermediates: &[rustls::Certificate], - _server_name: &rustls::ServerName, - _scts: &mut dyn Iterator, - _ocsp_response: &[u8], - _now: std::time::SystemTime, - ) -> Result { - Ok(rustls::client::ServerCertVerified::assertion()) - } -} - -/// Generates a self-signed cert for use in QUIC connections. -pub fn generate_self_signed_cert() -> anyhow::Result<(rustls::Certificate, rustls::PrivateKey)> { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_string()])?; - let key = rustls::PrivateKey(cert.serialize_private_key_der()); - Ok((rustls::Certificate(cert.serialize_der()?), key)) -} diff --git a/framework_crates/bones_framework/src/networking/lan.rs b/framework_crates/bones_framework/src/networking/lan.rs index 82fe39ae11..2f283b595b 100644 --- a/framework_crates/bones_framework/src/networking/lan.rs +++ b/framework_crates/bones_framework/src/networking/lan.rs @@ -10,20 +10,17 @@ // TODO #![allow(missing_docs)] -use std::{ - net::{IpAddr, SocketAddr, SocketAddrV4}, - time::Duration, -}; - -use bevy_tasks::IoTaskPool; -use bytes::Bytes; -use futures_lite::{future, FutureExt}; +use std::{net::IpAddr, time::Duration}; + +use iroh_net::{magic_endpoint::get_remote_node_id, NodeAddr}; use mdns_sd::{ServiceDaemon, ServiceInfo}; use smallvec::SmallVec; use tracing::warn; +use crate::networking::socket::establish_peer_connections; use crate::utils::BiChannelServer; +use super::socket::Socket; use super::*; /// Service discover info and ping. @@ -45,7 +42,11 @@ pub struct ServiceDiscoveryReceiver(mdns_sd::Receiver); static LAN_MATCHMAKER: Lazy = Lazy::new(|| { let (client, server) = bi_channel(); - IoTaskPool::get().spawn(lan_matchmaker(server)).detach(); + RUNTIME.spawn(async move { + if let Err(err) = lan_matchmaker(server).await { + warn!("lan matchmaker failed: {err:?}"); + } + }); LanMatchmaker(client) }); @@ -80,20 +81,23 @@ pub fn start_server(server: ServerInfo, player_count: usize) { /// Stop hosting a server. pub fn stop_server(server: &ServerInfo) { - stop_server_by_name(server.service.get_fullname()) + if let Err(err) = stop_server_by_name(server.service.get_fullname()) { + warn!("Lan: failed to stop server: {err:?}"); + } } /// Stop hosting a server specified by name. (Use [`ServiceInfo::get_fullname()`].) -fn stop_server_by_name(name: &str) { +fn stop_server_by_name(name: &str) -> anyhow::Result<()> { loop { match MDNS.unregister(name) { Ok(_) => break, Err(mdns_sd::Error::Again) => (), Err(e) => { - panic!("Error unregistering MDNS service: {e}") + anyhow::bail!("Error unregistering MDNS service: {e}") } } } + Ok(()) } /// Wait for players to join a hosted server. @@ -105,19 +109,15 @@ pub fn wait_players(joined_players: &mut usize, server: &ServerInfo) -> Option { info!(?player_idx, "Starting network game"); - loop { - match MDNS.unregister(server.service.get_fullname()) { - Ok(_) => break, - Err(mdns_sd::Error::Again) => (), - Err(e) => panic!("Error unregistering MDNS service: {e}"), - } + if let Err(err) = stop_server_by_name(server.service.get_fullname()) { + warn!("Lan: failed to stop server: {err:?}"); } - return Some(NetworkMatchSocket(Arc::new(lan_socket))); + return Some(NetworkMatchSocket(Arc::new(socket))); } } } @@ -125,13 +125,18 @@ pub fn wait_players(joined_players: &mut usize, server: &ServerInfo) -> Option anyhow::Result<()> { + let addr_raw = server + .service + .get_properties() + .get_property_val_str("node-addr") + .ok_or_else(|| anyhow::anyhow!("missing node-addr property from discovery"))?; + let addr_raw = hex::decode(addr_raw)?; + let addr: NodeAddr = postcard::from_bytes(&addr_raw)?; LAN_MATCHMAKER - .try_send(lan::LanMatchmakerRequest::JoinServer { - ip: *server.service.get_addresses().iter().next().unwrap(), - port: server.service.get_port(), - }) + .try_send(lan::LanMatchmakerRequest::JoinServer { addr }) .unwrap(); + Ok(()) } /// Leave a joined server. @@ -147,12 +152,12 @@ pub fn wait_game_start() -> Option { match message { LanMatchmakerResponse::ServerStarted | LanMatchmakerResponse::PlayerCount(_) => {} LanMatchmakerResponse::GameStarting { - lan_socket, + socket, player_idx, player_count: _, } => { info!(?player_idx, "Starting network game"); - return Some(NetworkMatchSocket(Arc::new(lan_socket))); + return Some(NetworkMatchSocket(Arc::new(socket))); } } } @@ -213,20 +218,25 @@ pub fn prepare_to_join( /// Get the current host info or create a new one. When there's an existing /// service but its `service_name` is different, the service is recreated and /// only then the returned `bool` is `true`. -pub fn prepare_to_host<'a>( +pub async fn prepare_to_host<'a>( host_info: &'a mut Option, service_name: &str, ) -> (bool, &'a mut ServerInfo) { - let create_service_info = || { + let create_service_info = || async { info!("New service hosting"); - let port = NETWORK_ENDPOINT.local_addr().unwrap().port(); + let ep = get_network_endpoint().await; + let my_addr = ep.my_addr().await.expect("network endpoint dead"); + let port = ep.local_addr().0.port(); + let mut props = std::collections::HashMap::default(); + let addr_encoded = hex::encode(postcard::to_stdvec(&my_addr).unwrap()); + props.insert("node-addr".to_string(), addr_encoded); let service = mdns_sd::ServiceInfo::new( MDNS_SERVICE_TYPE, service_name, service_name, "", port, - None, + props, ) .unwrap() .enable_addr_auto(); @@ -236,13 +246,17 @@ pub fn prepare_to_host<'a>( } }; - let service_info = host_info.get_or_insert_with(create_service_info); + if host_info.is_none() { + let info = create_service_info().await; + host_info.replace(info); + } + let service_info = host_info.as_mut().unwrap(); let mut is_recreated = false; if service_info.service.get_hostname() != service_name { - stop_server_by_name(service_info.service.get_fullname()); + stop_server_by_name(service_info.service.get_fullname()).unwrap(); is_recreated = true; - *service_info = create_service_info(); + *service_info = create_service_info().await; } (is_recreated, service_info) } @@ -253,239 +267,223 @@ pub fn prepare_to_host<'a>( /// channel. async fn lan_matchmaker( matchmaker_channel: BiChannelServer, -) { - #[derive(Serialize, Deserialize)] - enum MatchmakerNetMsg { - MatchReady { - /// The peers they have for the match, with the index in the array being the player index of the peer. - peers: [Option; MAX_PLAYERS], - /// The player index of the player getting the message. - player_idx: usize, - player_count: usize, - }, - } - +) -> anyhow::Result<()> { while let Ok(request) = matchmaker_channel.recv().await { match request { // Start server - LanMatchmakerRequest::StartServer { mut player_count } => { - info!("Starting LAN server"); - matchmaker_channel - .send(LanMatchmakerResponse::ServerStarted) - .await - .unwrap(); - - let mut connections = Vec::new(); - - loop { - let next_request = async { either::Left(matchmaker_channel.recv().await) }; - let next_conn = async { either::Right(NETWORK_ENDPOINT.accept().await) }; - - match next_request.or(next_conn).await { - // Handle more matchmaker requests - either::Either::Left(next_request) => { - let Ok(next_request) = next_request else { - break; - }; - - match next_request { - LanMatchmakerRequest::StartServer { - player_count: new_player_count, - } => { - connections.clear(); - player_count = new_player_count; - } - LanMatchmakerRequest::StopServer => { - break; - } - LanMatchmakerRequest::StopJoin => {} // Not joining, so don't do anything - LanMatchmakerRequest::JoinServer { .. } => { - error!("Cannot join server while hosting server"); - } - } - } + LanMatchmakerRequest::StartServer { player_count } => { + if let Err(err) = lan_start_server(&matchmaker_channel, player_count).await { + warn!("lan server failed: {err:?}"); + } + // Once we are done with server matchmaking + } + // Server not running or joining so do nothing + LanMatchmakerRequest::StopServer => (), + LanMatchmakerRequest::StopJoin => (), - // Handle new connections - either::Either::Right(Some(new_connection)) => { - let Some(conn) = new_connection.await.ok() else { - continue; - }; - connections.push(conn); - let current_players = connections.len() + 1; - info!(%current_players, "New player connection"); - } - _ => (), - } + // Join a hosted match + LanMatchmakerRequest::JoinServer { addr } => { + if let Err(err) = lan_join_server(&matchmaker_channel, addr).await { + warn!("failed to join server: {err:?}"); + } + } + } + } - // Discard closed connections - connections.retain(|conn| { - if conn.close_reason().is_some() { - info!("Player closed connection"); - false - } else { - true - } - }); + Ok(()) +} - let current_players = connections.len(); - let target_players = player_count; - info!(%current_players, %target_players); - - // If we're ready to start a match - if connections.len() == player_count - 1 { - info!("All players joined."); - - // Tell all clients we're ready - for (i, conn) in connections.iter().enumerate() { - let mut peers = [None; MAX_PLAYERS]; - connections - .iter() - .enumerate() - .filter(|x| x.0 != i) - .for_each(|(i, conn)| { - if let SocketAddr::V4(addr) = conn.remote_address() { - peers[i + 1] = Some(addr); - } else { - unreachable!("IPV6 not supported in LAN matchmaking"); - }; - }); - - let mut uni = conn.open_uni().await.unwrap(); - uni.write_all( - &postcard::to_vec::<_, 20>(&MatchmakerNetMsg::MatchReady { - player_idx: i + 1, - peers, - player_count, - }) - .unwrap(), - ) - .await - .unwrap(); - uni.finish().await.unwrap(); - } +async fn lan_start_server( + matchmaker_channel: &BiChannelServer, + mut player_count: usize, +) -> anyhow::Result<()> { + info!("Starting LAN server"); + matchmaker_channel + .send(LanMatchmakerResponse::ServerStarted) + .await?; - // Collect the list of client connections - let connections = std::array::from_fn(|i| { - if i == 0 { - None - } else { - connections.get(i - 1).cloned() - } - }); - - // Send the connections to the game so that it can start the network match. - matchmaker_channel - .try_send(LanMatchmakerResponse::GameStarting { - lan_socket: LanSocket::new(0, connections), - player_idx: 0, - player_count, - }) - .ok(); - info!(player_idx=0, %player_count, "Matchmaking finished"); - - // Break out of the server loop - break; + let mut connections = Vec::new(); + let ep = get_network_endpoint().await; - // If we don't have enough players yet, send the updated player count to the game. - } else if matchmaker_channel - .try_send(LanMatchmakerResponse::PlayerCount(current_players)) - .is_err() - { + loop { + tokio::select! { + next_request = matchmaker_channel.recv() => { + match next_request? { + LanMatchmakerRequest::StartServer { + player_count: new_player_count, + } => { + connections.clear(); + player_count = new_player_count; + } + LanMatchmakerRequest::StopServer => { break; } + LanMatchmakerRequest::StopJoin => {} // Not joining, so don't do anything + LanMatchmakerRequest::JoinServer { .. } => { + anyhow::bail!("Cannot join server while hosting server"); + } } + } - // Once we are done with server matchmaking + // Handle new connections + new_connection = ep.accept() => { + let Some(mut new_connection) = new_connection else { + anyhow::bail!("unable to accept new connections"); + }; + let result = async move { + let alpn = new_connection.alpn().await?; + anyhow::ensure!(alpn.as_bytes() == PLAY_ALPN, "unexpected ALPN"); + let conn = new_connection.await?; + anyhow::Ok(conn) + }; + + match result.await { + Ok(conn) => { + connections.push(conn); + let current_players = connections.len() + 1; + info!(%current_players, "New player connection"); + } + Err(err) => { + warn!("failed to accept connection: {:?}", err); + continue; + } + } } - // Server not running or joining so do nothing - LanMatchmakerRequest::StopServer => (), - LanMatchmakerRequest::StopJoin => (), + } - // Join a hosted match - LanMatchmakerRequest::JoinServer { ip, port } => { - let conn = NETWORK_ENDPOINT - .connect((ip, port).into(), "jumpy-host") - .unwrap() - .await - .expect("Could not connect to server"); - - // Wait for match to start - let mut uni = conn.accept_uni().await.unwrap(); - let bytes = uni.read_to_end(20).await.unwrap(); - let message: MatchmakerNetMsg = postcard::from_bytes(&bytes).unwrap(); - - match message { - MatchmakerNetMsg::MatchReady { - peers: peer_addrs, - player_idx, - player_count, - } => { - info!(%player_count, %player_idx, ?peer_addrs, "Matchmaking finished"); - let mut peer_connections = std::array::from_fn(|_| None); - - // Set the connection to the matchmaker for player 0 - peer_connections[0] = Some(conn.clone()); - - // For every peer with a player index that is higher than ours, wait for - // them to connect to us. - let range = (player_idx + 1)..player_count; - info!(players=?range, "Waiting for {} peer connections", range.len()); - for _ in range { - // Wait for connection - let conn = NETWORK_ENDPOINT - .accept() - .await - .unwrap() - .await - .expect("Could not accept incomming connection"); - - // Receive the player index - let idx = { - let mut buf = [0; 1]; - let mut channel = conn.accept_uni().await.unwrap(); - channel.read_exact(&mut buf).await.unwrap(); - - buf[0] as usize - }; - assert!(idx < MAX_PLAYERS, "Invalid player index"); - - peer_connections[idx] = Some(conn); - } + // Discard closed connections + connections.retain(|conn| { + if conn.close_reason().is_some() { + info!("Player closed connection"); + false + } else { + true + } + }); + + let current_players = connections.len(); + let target_players = player_count; + info!(%current_players, %target_players); + + // If we're ready to start a match + if connections.len() == player_count - 1 { + info!("All players joined."); + + let endpoint = get_network_endpoint().await; - // For every peer with a player index lower than ours, connect to them. - let range = 1..player_idx; - info!(players=?range, "Connecting to {} peers", range.len()); - for i in range { - let addr = peer_addrs[i].unwrap(); - let conn = NETWORK_ENDPOINT - .connect(addr.into(), "jumpy-peer") - .unwrap() - .await - .expect("Could not connect to peer"); - - // Send player index - let mut channel = conn.open_uni().await.unwrap(); - channel.write(&[player_idx as u8]).await.unwrap(); - channel.finish().await.unwrap(); - - peer_connections[i] = Some(conn); + // Tell all clients we're ready + for (i, conn) in connections.iter().enumerate() { + let mut peers = std::array::from_fn(|_| None); + connections + .iter() + .enumerate() + .filter(|x| x.0 != i) + .for_each(|(i, conn)| { + let id = get_remote_node_id(conn).expect("invalid connection"); + let mut addr = NodeAddr::new(id); + if let Some(info) = endpoint.connection_info(id) { + if let Some(relay_url) = info.relay_url { + addr = addr.with_relay_url(relay_url.relay_url); + } + addr = addr.with_direct_addresses( + info.addrs.into_iter().map(|addr| addr.addr), + ); } - let lan_socket = LanSocket::new(player_idx, peer_connections); - info!("Connections established."); + peers[i + 1] = Some(addr); + }); - matchmaker_channel - .try_send(LanMatchmakerResponse::GameStarting { - lan_socket, - player_idx, - player_count, - }) - .ok(); - } - } + let mut uni = conn.open_uni().await?; + uni.write_all(&postcard::to_vec::<_, 20>(&MatchmakerNetMsg::MatchReady { + player_idx: i + 1, + peers, + player_count, + })?) + .await?; + uni.finish().await?; } + + // Collect the list of client connections + let connections = std::array::from_fn(|i| { + if i == 0 { + None + } else { + connections.get(i - 1).cloned() + } + }); + + // Send the connections to the game so that it can start the network match. + matchmaker_channel + .send(LanMatchmakerResponse::GameStarting { + socket: Socket::new(0, connections), + player_idx: 0, + player_count, + }) + .await?; + info!(player_idx=0, %player_count, "Matchmaking finished"); + + // Break out of the server loop + break; + + // If we don't have enough players yet, send the updated player count to the game. + } else { + matchmaker_channel + .send(LanMatchmakerResponse::PlayerCount(current_players)) + .await?; } } + + Ok(()) +} + +async fn lan_join_server( + matchmaker_channel: &BiChannelServer, + addr: NodeAddr, +) -> anyhow::Result<()> { + let ep = get_network_endpoint().await; + let conn = ep.connect(addr, PLAY_ALPN).await?; + + // Wait for match to start + let mut uni = conn.accept_uni().await?; + let bytes = uni.read_to_end(20).await?; + let message: MatchmakerNetMsg = postcard::from_bytes(&bytes)?; + + match message { + MatchmakerNetMsg::MatchReady { + peers: peer_addrs, + player_idx, + player_count, + } => { + info!(%player_count, %player_idx, ?peer_addrs, "Matchmaking finished"); + + let peer_connections = + establish_peer_connections(player_idx, player_count, peer_addrs, Some(conn)) + .await?; + + let socket = Socket::new(player_idx, peer_connections); + info!("Connections established."); + + matchmaker_channel + .send(LanMatchmakerResponse::GameStarting { + socket, + player_idx, + player_count, + }) + .await?; + } + } + Ok(()) +} + +#[derive(Serialize, Deserialize)] +enum MatchmakerNetMsg { + MatchReady { + /// The peers they have for the match, with the index in the array being the player index of the peer. + peers: [Option; MAX_PLAYERS], + /// The player index of the player getting the message. + player_idx: usize, + player_count: usize, + }, } /// The type of the `LAN_MATCHMAKER` channel. @@ -502,10 +500,8 @@ pub enum LanMatchmakerRequest { }, /// Join server JoinServer { - /// Server address - ip: IpAddr, - /// Server port - port: u16, + /// Node Addr + addr: NodeAddr, }, /// Stop matchmaking server StopServer, @@ -522,7 +518,7 @@ pub enum LanMatchmakerResponse { /// Game is starting GameStarting { /// Lan socket to game - lan_socket: LanSocket, + socket: Socket, /// Local player index player_idx: usize, /// Game player count @@ -530,242 +526,6 @@ pub enum LanMatchmakerResponse { }, } -/// The LAN [`NetworkSocket`] implementation. -#[derive(Debug, Clone)] -pub struct LanSocket { - /// - pub connections: [Option; MAX_PLAYERS], - pub ggrs_receiver: async_channel::Receiver<(usize, GameMessage)>, - pub reliable_receiver: async_channel::Receiver<(usize, Vec)>, - pub player_idx: usize, - pub player_count: usize, - /// ID for current match, messages received that do not match ID are dropped. - pub match_id: u8, -} - -impl LanSocket { - pub fn new(player_idx: usize, connections: [Option; MAX_PLAYERS]) -> Self { - let (ggrs_sender, ggrs_receiver) = async_channel::unbounded(); - let (reliable_sender, reliable_receiver) = async_channel::unbounded(); - - let pool = bevy_tasks::IoTaskPool::get(); - - // Spawn tasks to receive network messages from each peer - #[allow(clippy::needless_range_loop)] - for i in 0..MAX_PLAYERS { - if let Some(conn) = connections[i].clone() { - let ggrs_sender = ggrs_sender.clone(); - - // Unreliable message receiver - let conn_ = conn.clone(); - pool.spawn(async move { - let conn = conn_; - - #[cfg(feature = "debug-network-slowdown")] - use turborand::prelude::*; - #[cfg(feature = "debug-network-slowdown")] - let rng = AtomicRng::new(); - - loop { - let event = - future::or(async { either::Left(conn.closed().await) }, async { - either::Right(conn.read_datagram().await) - }) - .await; - - match event { - either::Either::Left(closed) => { - warn!("Connection error: {closed}"); - break; - } - either::Either::Right(datagram_result) => match datagram_result { - Ok(data) => { - let message: GameMessage = postcard::from_bytes(&data) - .expect("Could not deserialize net message"); - - // Debugging code to introduce artificial latency - #[cfg(feature = "debug-network-slowdown")] - { - use async_timer::Oneshot; - async_timer::oneshot::Timer::new( - std::time::Duration::from_millis( - (rng.f32_normalized() * 100.0) as u64 + 1, - ), - ) - .await; - } - if ggrs_sender.send((i, message)).await.is_err() { - break; - } - } - Err(e) => { - warn!("Connection error: {e}"); - } - }, - } - } - }) - .detach(); - - // Reliable message receiver - let reliable_sender = reliable_sender.clone(); - pool.spawn(async move { - #[cfg(feature = "debug-network-slowdown")] - use turborand::prelude::*; - #[cfg(feature = "debug-network-slowdown")] - let rng = AtomicRng::new(); - - loop { - let event = - future::or(async { either::Left(conn.closed().await) }, async { - either::Right(conn.accept_uni().await) - }) - .await; - - match event { - either::Either::Left(closed) => { - warn!("Connection error: {closed}"); - break; - } - either::Either::Right(result) => match result { - Ok(mut stream) => { - let data = - stream.read_to_end(4096).await.expect("Network read error"); - - // Debugging code to introduce artificial latency - #[cfg(feature = "debug-network-slowdown")] - { - use async_timer::Oneshot; - async_timer::oneshot::Timer::new( - std::time::Duration::from_millis( - (rng.f32_normalized() * 100.0) as u64 + 1, - ), - ) - .await; - } - if reliable_sender.send((i, data)).await.is_err() { - break; - } - } - Err(e) => { - warn!("Connection error: {e}"); - } - }, - } - } - }) - .detach(); - } - } - - Self { - player_idx, - player_count: connections.iter().flatten().count() + 1, - connections, - ggrs_receiver, - reliable_receiver, - match_id: 0, - } - } -} - -impl NetworkSocket for LanSocket { - fn send_reliable(&self, target: SocketTarget, message: &[u8]) { - let task_pool = IoTaskPool::get(); - let message = Bytes::copy_from_slice(message); - - match target { - SocketTarget::Player(i) => { - let conn = self.connections[i].as_ref().unwrap().clone(); - - task_pool - .spawn(async move { - let mut stream = conn.open_uni().await.unwrap(); - stream.write_chunk(message).await.unwrap(); - stream.finish().await.unwrap(); - }) - .detach(); - } - SocketTarget::All => { - for conn in &self.connections { - if let Some(conn) = conn.clone() { - let message = message.clone(); - task_pool - .spawn(async move { - let mut stream = conn.open_uni().await.unwrap(); - stream.write_chunk(message).await.unwrap(); - stream.finish().await.unwrap(); - }) - .detach(); - } - } - } - } - } - - fn recv_reliable(&self) -> Vec<(usize, Vec)> { - let mut messages = Vec::new(); - while let Ok(message) = self.reliable_receiver.try_recv() { - messages.push(message); - } - messages - } - - fn ggrs_socket(&self) -> BoxedNonBlockingSocket { - BoxedNonBlockingSocket(Box::new(self.clone())) - } - - fn close(&self) { - for conn in self.connections.iter().flatten() { - conn.close(0u8.into(), &[]); - } - } - - fn player_idx(&self) -> usize { - self.player_idx - } - - fn player_count(&self) -> usize { - self.player_count - } - - fn player_is_local(&self) -> [bool; MAX_PLAYERS] { - std::array::from_fn(|i| self.connections[i].is_none() && i < self.player_count) - } - - fn increment_match_id(&mut self) { - self.match_id = self.match_id.wrapping_add(1); - } -} - -impl ggrs::NonBlockingSocket for LanSocket { - fn send_to(&mut self, msg: &ggrs::Message, addr: &usize) { - let msg = GameMessage { - // Consider a way we can send message by reference and avoid clone? - message: msg.clone(), - match_id: self.match_id, - }; - let conn = self.connections[*addr].as_ref().unwrap(); - let message = bones_matchmaker_proto::SendProxyMessage { - target_client: bones_matchmaker_proto::TargetClient::One(*addr as u8), - message: postcard::to_allocvec(&msg).unwrap(), - }; - let msg_bytes = postcard::to_allocvec(&message).unwrap(); - conn.send_datagram(Bytes::copy_from_slice(&msg_bytes[..])) - .ok(); - } - - fn receive_all_messages(&mut self) -> Vec<(usize, ggrs::Message)> { - let mut messages = Vec::new(); - while let Ok(message) = self.ggrs_receiver.try_recv() { - if message.1.match_id == self.match_id { - messages.push((message.0, message.1.message)); - } - } - messages - } -} - fn pinger(server: BiChannelServer) { while let Ok(servers) = server.recv_blocking() { let mut pings = SmallVec::new(); diff --git a/framework_crates/bones_framework/src/networking/online.md b/framework_crates/bones_framework/src/networking/online.md index 3c3d94d92c..dc633a03ee 100644 --- a/framework_crates/bones_framework/src/networking/online.md +++ b/framework_crates/bones_framework/src/networking/online.md @@ -1,4 +1,4 @@ -Contains the online matchmaker and the [`NetworkSocket`] implementation. +Contains the online matchmaker. ## Matchmaking diff --git a/framework_crates/bones_framework/src/networking/online.rs b/framework_crates/bones_framework/src/networking/online.rs index a0f2b8c0cb..cfaed2a33a 100644 --- a/framework_crates/bones_framework/src/networking/online.rs +++ b/framework_crates/bones_framework/src/networking/online.rs @@ -2,25 +2,20 @@ // TODO #![allow(missing_docs)] -use std::{ - net::{SocketAddr, ToSocketAddrs}, - sync::Arc, -}; +use std::sync::Arc; -use bevy_tasks::IoTaskPool; -use bones_matchmaker_proto::{MatchInfo, MatchmakerRequest, MatchmakerResponse}; -use bytes::Bytes; -use futures_lite::future; +use bones_matchmaker_proto::{MatchInfo, MatchmakerRequest, MatchmakerResponse, MATCH_ALPN}; +use iroh_net::NodeId; use once_cell::sync::Lazy; -use quinn::Connection; use tracing::{info, warn}; -use crate::{networking::NetworkMatchSocket, prelude::*}; - -use super::{ - BoxedNonBlockingSocket, GameMessage, NetworkSocket, SocketTarget, MAX_PLAYERS, NETWORK_ENDPOINT, +use crate::{ + networking::{get_network_endpoint, socket::establish_peer_connections, NetworkMatchSocket}, + prelude::*, }; +use super::socket::Socket; + #[derive(Default, PartialEq, Eq, Clone, Copy)] pub enum SearchState { #[default] @@ -33,7 +28,11 @@ pub enum SearchState { pub static ONLINE_MATCHMAKER: Lazy = Lazy::new(|| { let (client, server) = bi_channel(); - IoTaskPool::get().spawn(online_matchmaker(server)).detach(); + RUNTIME.spawn(async move { + if let Err(err) = online_matchmaker(server).await { + warn!("online matchmaker failed: {err:?}"); + } + }); OnlineMatchmaker(client) }); @@ -45,7 +44,7 @@ pub struct OnlineMatchmaker(BiChannelClient, -) { +) -> anyhow::Result<()> { while let Ok(message) = matchmaker_channel.recv().await { match message { - OnlineMatchmakerRequest::SearchForGame { addr, player_count } => { - info!("Connecting to online matchmaker"); - let addr = resolve_addr_blocking(&addr).unwrap(); - let conn = NETWORK_ENDPOINT - .connect(addr, "matchmaker") - .unwrap() - .await - .unwrap(); - info!("Connected to online matchmaker"); - - matchmaker_channel - .try_send(OnlineMatchmakerResponse::Searching) - .unwrap(); - - // Send a match request to the server - let (mut send, mut recv) = conn.open_bi().await.unwrap(); - - let message = MatchmakerRequest::RequestMatch(MatchInfo { - client_count: player_count.try_into().unwrap(), - match_data: b"jumpy_default_game".to_vec(), - }); - info!(request=?message, "Sending match request"); - let message = postcard::to_allocvec(&message).unwrap(); - send.write_all(&message).await.unwrap(); - send.finish().await.unwrap(); - - let response = recv.read_to_end(256).await.unwrap(); - let message: MatchmakerResponse = postcard::from_bytes(&response).unwrap(); - - if let MatchmakerResponse::Accepted = message { - info!("Waiting for match..."); - } else { - panic!("Invalid response from matchmaker"); - } - - loop { - let recv_ui_message = matchmaker_channel.recv(); - let recv_online_matchmaker = conn.accept_uni(); - - let next_message = futures_lite::future::or( - async move { either::Left(recv_ui_message.await) }, - async move { either::Right(recv_online_matchmaker.await) }, - ) - .await; - - match next_message { - // UI message - either::Either::Left(message) => { - let message = message.unwrap(); - - match message { - OnlineMatchmakerRequest::SearchForGame { .. } => { - panic!("Unexpected message from UI"); - } - OnlineMatchmakerRequest::StopSearch => { - info!("Canceling online search"); - break; - } - } - } - - // Matchmaker message - either::Either::Right(recv) => { - let mut recv = recv.unwrap(); - let message = recv.read_to_end(256).await.unwrap(); - let message: MatchmakerResponse = - postcard::from_bytes(&message).unwrap(); - - match message { - MatchmakerResponse::ClientCount(count) => { - info!("Online match player count: {count}"); - matchmaker_channel - .try_send(OnlineMatchmakerResponse::PlayerCount(count as _)) - .unwrap(); - } - MatchmakerResponse::Success { - random_seed, - player_idx, - client_count, - } => { - info!(%random_seed, %player_idx, player_count=%client_count, "Online match complete"); - let online_socket = OnlineSocket::new( - player_idx as usize, - client_count as usize, - conn, - ); - - matchmaker_channel - .try_send(OnlineMatchmakerResponse::GameStarting { - online_socket, - player_idx: player_idx as _, - player_count: client_count as _, - }) - .unwrap(); - break; - } - _ => panic!("Unexpected message from matchmaker"), - } - } - } + OnlineMatchmakerRequest::SearchForGame { id, player_count } => { + if let Err(err) = search_for_game(&matchmaker_channel, id, player_count).await { + warn!("Online Game Search failed: {err:?}"); } } OnlineMatchmakerRequest::StopSearch => (), // Not searching, don't do anything } } -} - -/// Resolve a server address. -/// -/// Note: This may block the thread -fn resolve_addr_blocking(addr: &str) -> anyhow::Result { - let formatting_err = - || anyhow::format_err!("Matchmaking server must be in the format `host:port`"); - - let mut iter = addr.split(':'); - let host = iter.next().ok_or_else(formatting_err)?; - let port = iter.next().ok_or_else(formatting_err)?; - let port: u16 = port.parse().context("Couldn't parse port number")?; - if iter.next().is_some() { - return Err(formatting_err()); - } - - let addr = (host, port) - .to_socket_addrs() - .context("Couldn't resolve matchmaker address")? - .find(|x| x.is_ipv4()) // For now, only support IpV4. I don't think IpV6 works right. - .ok_or_else(|| anyhow::format_err!("Couldn't resolve matchmaker address"))?; - Ok(addr) + Ok(()) } -#[derive(Debug, Clone)] -pub struct OnlineSocket { - pub conn: Connection, - pub ggrs_receiver: async_channel::Receiver<(usize, GameMessage)>, - pub reliable_receiver: async_channel::Receiver<(usize, Vec)>, - pub player_idx: usize, - pub player_count: usize, - /// ID for current match, messages received that do not match ID are dropped. - pub match_id: u8, -} +async fn search_for_game( + matchmaker_channel: &BiChannelServer, + id: NodeId, + player_count: usize, +) -> anyhow::Result<()> { + info!("Connecting to online matchmaker"); + let ep = get_network_endpoint().await; + let conn = ep.connect(id.into(), MATCH_ALPN).await?; + info!("Connected to online matchmaker"); + + matchmaker_channel + .send(OnlineMatchmakerResponse::Searching) + .await?; + + // Send a match request to the server + let (mut send, mut recv) = conn.open_bi().await?; + + let message = MatchmakerRequest::RequestMatch(MatchInfo { + client_count: player_count.try_into().unwrap(), + match_data: b"jumpy_default_game".to_vec(), + }); + info!(request=?message, "Sending match request"); + + let message = postcard::to_allocvec(&message)?; + send.write_all(&message).await?; + send.finish().await?; + + let response = recv.read_to_end(256).await?; + let message: MatchmakerResponse = postcard::from_bytes(&response)?; + + if let MatchmakerResponse::Accepted = message { + info!("Waiting for match..."); + } else { + panic!("Invalid response from matchmaker"); + } -impl OnlineSocket { - pub fn new(player_idx: usize, player_count: usize, conn: Connection) -> Self { - let (ggrs_sender, ggrs_receiver) = async_channel::unbounded(); - let (reliable_sender, reliable_receiver) = async_channel::unbounded(); - - let task_pool = IoTaskPool::get(); - - let conn_ = conn.clone(); - task_pool - .spawn(async move { - let conn = conn_; - loop { - let event = future::or(async { either::Left(conn.closed().await) }, async { - either::Right(conn.read_datagram().await) - }) - .await; - - match event { - either::Either::Left(closed) => { - warn!("Connection error: {closed}"); - break; - } - either::Either::Right(datagram_result) => match datagram_result { - Ok(data) => { - let message: bones_matchmaker_proto::RecvProxyMessage = - postcard::from_bytes(&data) - .expect("Could not deserialize net message"); - let player = message.from_client; - let message = postcard::from_bytes(&message.message).unwrap(); - - if ggrs_sender.send((player as _, message)).await.is_err() { - break; - } - } - Err(e) => { - warn!("Connection error: {e}"); - } - }, + loop { + tokio::select! { + // UI message + message = matchmaker_channel.recv() => { + match message { + Ok(OnlineMatchmakerRequest::SearchForGame { .. }) => { + anyhow::bail!("Unexpected message from UI"); + } + Ok(OnlineMatchmakerRequest::StopSearch) => { + info!("Canceling online search"); + break; + } + Err(err) => { + anyhow::bail!("Failed to recv from match maker channel: {err:?}"); } } - }) - .detach(); - - let conn_ = conn.clone(); - task_pool - .spawn(async move { - let conn = conn_; - loop { - let event = future::or(async { either::Left(conn.closed().await) }, async { - either::Right(conn.accept_uni().await) - }) - .await; - - match event { - either::Either::Left(closed) => { - warn!("Connection error: {closed}"); - break; - } - either::Either::Right(result) => match result { - Ok(mut stream) => { - let data = - stream.read_to_end(4096).await.expect("Network read error"); - let message: bones_matchmaker_proto::RecvProxyMessage = - postcard::from_bytes(&data).unwrap(); - - if reliable_sender - .send((message.from_client as usize, message.message)) - .await - .is_err() - { - break; - } - } - Err(e) => { - warn!("Connection error: {e}"); - } - }, + } + // Matchmaker message + recv = conn.accept_uni() => { + let mut recv = recv?; + let message = recv.read_to_end(5 * 1024).await?; + let message: MatchmakerResponse = postcard::from_bytes(&message)?; + + match message { + MatchmakerResponse::ClientCount(count) => { + info!("Online match player count: {count}"); + matchmaker_channel.try_send(OnlineMatchmakerResponse::PlayerCount(count as _))?; + } + MatchmakerResponse::Success { + random_seed, + player_idx, + client_count, + player_ids, + } => { + info!(%random_seed, %player_idx, player_count=%client_count, "Online match complete"); + + let peer_connections = establish_peer_connections( + player_idx as usize, + client_count as usize, + player_ids, + None, + ) + .await?; + + let socket = Socket::new(player_idx as usize, peer_connections); + + matchmaker_channel.try_send(OnlineMatchmakerResponse::GameStarting { + socket, + player_idx: player_idx as _, + player_count: client_count as _, + })?; + break; } + other => anyhow::bail!("Unexpected message from matchmaker: {other:?}"), } - }) - .detach(); - - Self { - conn, - ggrs_receiver, - reliable_receiver, - player_idx, - player_count, - match_id: 0, - } - } -} - -impl NetworkSocket for OnlineSocket { - fn ggrs_socket(&self) -> BoxedNonBlockingSocket { - BoxedNonBlockingSocket(Box::new(self.clone())) - } - - fn send_reliable(&self, target: SocketTarget, message: &[u8]) { - let task_pool = IoTaskPool::get(); - let target_client = match target { - SocketTarget::Player(player) => bones_matchmaker_proto::TargetClient::One(player as _), - SocketTarget::All => bones_matchmaker_proto::TargetClient::All, - }; - let message = bones_matchmaker_proto::SendProxyMessage { - target_client, - message: message.into(), - }; - - let conn = self.conn.clone(); - task_pool - .spawn(async move { - let mut send = conn.open_uni().await.unwrap(); - - send.write_all(&postcard::to_allocvec(&message).unwrap()) - .await - .unwrap(); - send.finish().await.unwrap(); - }) - .detach(); - } - - fn recv_reliable(&self) -> Vec<(usize, Vec)> { - let mut messages = Vec::new(); - while let Ok(message) = self.reliable_receiver.try_recv() { - messages.push(message); - } - messages - } - - fn close(&self) { - self.conn.close(0u8.into(), &[]); - } - - fn player_idx(&self) -> usize { - self.player_idx - } - - fn player_is_local(&self) -> [bool; MAX_PLAYERS] { - std::array::from_fn(|i| i == self.player_idx) - } - - fn player_count(&self) -> usize { - self.player_count - } - - fn increment_match_id(&mut self) { - // This is wrapping addition - self.match_id = self.match_id.wrapping_add(1); - } -} - -impl ggrs::NonBlockingSocket for OnlineSocket { - fn send_to(&mut self, msg: &ggrs::Message, addr: &usize) { - let msg = GameMessage { - message: msg.clone(), - match_id: self.match_id, - }; - let message = bones_matchmaker_proto::SendProxyMessage { - target_client: bones_matchmaker_proto::TargetClient::One(*addr as u8), - message: postcard::to_allocvec(&msg).unwrap(), - }; - let msg_bytes = postcard::to_allocvec(&message).unwrap(); - self.conn - .send_datagram(Bytes::copy_from_slice(&msg_bytes[..])) - .ok(); - } - - fn receive_all_messages(&mut self) -> Vec<(usize, ggrs::Message)> { - let mut messages = Vec::new(); - while let Ok(message) = self.ggrs_receiver.try_recv() { - if message.1.match_id == self.match_id { - messages.push((message.0, message.1.message)); } } - messages } + + Ok(()) } /// Search for game with `matchmaking_server` and `player_count` -pub fn start_search_for_game(matchmaking_server: String, player_count: usize) { +pub fn start_search_for_game(matchmaking_server: NodeId, player_count: usize) { // TODO remove info!("Starting search for online game with player count {player_count}"); ONLINE_MATCHMAKER .try_send(OnlineMatchmakerRequest::SearchForGame { - addr: matchmaking_server.clone(), + id: matchmaking_server, player_count, }) .unwrap() @@ -414,7 +202,7 @@ pub fn update_search_for_game(search_state: &mut SearchState) -> Option { @@ -422,7 +210,7 @@ pub fn update_search_for_game(search_state: &mut SearchState) -> Option; MAX_PLAYERS], + pub ggrs_receiver: async_channel::Receiver<(usize, GameMessage)>, + pub reliable_receiver: async_channel::Receiver<(usize, Vec)>, + pub player_idx: usize, + pub player_count: usize, + /// ID for current match, messages received that do not match ID are dropped. + pub match_id: u8, +} + +impl Socket { + pub fn new( + player_idx: usize, + connections: [Option; MAX_PLAYERS], + ) -> Self { + let (ggrs_sender, ggrs_receiver) = async_channel::unbounded(); + let (reliable_sender, reliable_receiver) = async_channel::unbounded(); + + // Spawn tasks to receive network messages from each peer + #[allow(clippy::needless_range_loop)] + for i in 0..MAX_PLAYERS { + if let Some(conn) = connections[i].clone() { + let ggrs_sender = ggrs_sender.clone(); + + // Unreliable message receiver + let conn_ = conn.clone(); + RUNTIME.spawn(async move { + let conn = conn_; + + #[cfg(feature = "debug-network-slowdown")] + use turborand::prelude::*; + #[cfg(feature = "debug-network-slowdown")] + let rng = AtomicRng::new(); + + loop { + tokio::select! { + closed = conn.closed() => { + warn!("Connection error: {closed}"); + break; + } + datagram_result = conn.read_datagram() => match datagram_result { + Ok(data) => { + let message: GameMessage = postcard::from_bytes(&data) + .expect("Could not deserialize net message"); + + // Debugging code to introduce artificial latency + #[cfg(feature = "debug-network-slowdown")] + { + use async_timer::Oneshot; + async_timer::oneshot::Timer::new( + std::time::Duration::from_millis( + (rng.f32_normalized() * 100.0) as u64 + 1, + ), + ) + .await; + } + if ggrs_sender.send((i, message)).await.is_err() { + break; + } + } + Err(e) => { + warn!("Connection error: {e}"); + } + } + } + } + }); + + // Reliable message receiver + let reliable_sender = reliable_sender.clone(); + RUNTIME.spawn(async move { + #[cfg(feature = "debug-network-slowdown")] + use turborand::prelude::*; + #[cfg(feature = "debug-network-slowdown")] + let rng = AtomicRng::new(); + + loop { + tokio::select! { + closed = conn.closed() => { + warn!("Connection error: {closed}"); + break; + } + result = conn.accept_uni() => match result { + Ok(mut stream) => { + let data = stream.read_to_end(4096).await.expect("Network read error"); + + // Debugging code to introduce artificial latency + #[cfg(feature = "debug-network-slowdown")] + { + use async_timer::Oneshot; + async_timer::oneshot::Timer::new( + std::time::Duration::from_millis( + (rng.f32_normalized() * 100.0) as u64 + 1, + ), + ) + .await; + } + if reliable_sender.send((i, data)).await.is_err() { + break; + } + } + Err(e) => { + warn!("Connection error: {e}"); + } + }, + } + } + }); + } + } + + Self { + player_idx, + player_count: connections.iter().flatten().count() + 1, + connections, + ggrs_receiver, + reliable_receiver, + match_id: 0, + } + } +} + +impl NetworkSocket for Socket { + fn send_reliable(&self, target: SocketTarget, message: &[u8]) { + let message = Bytes::copy_from_slice(message); + + match target { + SocketTarget::Player(i) => { + let conn = self.connections[i].as_ref().unwrap().clone(); + + RUNTIME.spawn(async move { + let result = async move { + let mut stream = conn.open_uni().await?; + stream.write_chunk(message).await?; + stream.finish().await?; + anyhow::Ok(()) + }; + if let Err(err) = result.await { + warn!("send reliable to {i} failed: {err:?}"); + } + }); + } + SocketTarget::All => { + for conn in &self.connections { + if let Some(conn) = conn.clone() { + let message = message.clone(); + RUNTIME.spawn(async move { + let result = async move { + let mut stream = conn.open_uni().await?; + stream.write_chunk(message).await?; + stream.finish().await?; + anyhow::Ok(()) + }; + if let Err(err) = result.await { + warn!("send reliable all failed: {err:?}"); + } + }); + } + } + } + } + } + + fn recv_reliable(&self) -> Vec<(usize, Vec)> { + let mut messages = Vec::new(); + while let Ok(message) = self.reliable_receiver.try_recv() { + messages.push(message); + } + messages + } + + fn ggrs_socket(&self) -> Self { + self.clone() + } + + fn close(&self) { + for conn in self.connections.iter().flatten() { + conn.close(0u8.into(), &[]); + } + } + + fn player_idx(&self) -> usize { + self.player_idx + } + + fn player_count(&self) -> usize { + self.player_count + } + + fn player_is_local(&self) -> [bool; MAX_PLAYERS] { + std::array::from_fn(|i| self.connections[i].is_none() && i < self.player_count) + } + + fn increment_match_id(&mut self) { + self.match_id = self.match_id.wrapping_add(1); + } +} + +pub(super) async fn establish_peer_connections( + player_idx: usize, + player_count: usize, + peer_addrs: [Option; MAX_PLAYERS], + conn: Option, +) -> anyhow::Result<[Option; MAX_PLAYERS]> { + let mut peer_connections = std::array::from_fn(|_| None); + + if let Some(conn) = conn { + // Set the connection to the matchmaker for player 0 + peer_connections[0] = Some(conn); + } + + let ep = get_network_endpoint().await; + + // For every peer with a player index that is higher than ours, wait for + // them to connect to us. + let range = (player_idx + 1)..player_count; + info!(players=?range, "Waiting for {} peer connections", range.len()); + for i in range { + // Wait for connection + let mut conn = ep + .accept() + .await + .ok_or_else(|| anyhow::anyhow!("no connection for {}", i))?; + let alpn = conn.alpn().await?; + anyhow::ensure!(alpn.as_bytes() == PLAY_ALPN, "invalid ALPN: {}", alpn); + + let conn = conn.await?; + + // Receive the player index + let idx = { + let mut buf = [0; 1]; + let mut channel = conn.accept_uni().await?; + channel.read_exact(&mut buf).await?; + + buf[0] as usize + }; + anyhow::ensure!(idx < MAX_PLAYERS, "Invalid player index"); + + peer_connections[idx] = Some(conn); + } + + // For every peer with a player index lower than ours, connect to them. + let start_range = if peer_connections[0].is_some() { 1 } else { 0 }; + let range = start_range..player_idx; + info!(players=?range, "Connecting to {} peers", range.len()); + + for i in range { + let addr = peer_addrs[i].as_ref().unwrap(); + let conn = ep.connect(addr.clone(), PLAY_ALPN).await?; + + // Send player index + let mut channel = conn.open_uni().await?; + channel.write(&[player_idx as u8]).await?; + channel.finish().await?; + + peer_connections[i] = Some(conn); + } + + Ok(peer_connections) +} + +impl ggrs::NonBlockingSocket for Socket { + fn send_to(&mut self, msg: &ggrs::Message, addr: &usize) { + let msg = GameMessage { + // Consider a way we can send message by reference and avoid clone? + message: msg.clone(), + match_id: self.match_id, + }; + let conn = self.connections[*addr].as_ref().unwrap(); + + let msg_bytes = postcard::to_allocvec(&msg).unwrap(); + conn.send_datagram(Bytes::copy_from_slice(&msg_bytes[..])) + .ok(); + } + + fn receive_all_messages(&mut self) -> Vec<(usize, ggrs::Message)> { + let mut messages = Vec::new(); + while let Ok(message) = self.ggrs_receiver.try_recv() { + if message.1.match_id == self.match_id { + messages.push((message.0, message.1.message)); + } + } + messages + } +} diff --git a/other_crates/bones_matchmaker/Cargo.toml b/other_crates/bones_matchmaker/Cargo.toml index 5d0cc1e89c..3c88496b5d 100644 --- a/other_crates/bones_matchmaker/Cargo.toml +++ b/other_crates/bones_matchmaker/Cargo.toml @@ -9,10 +9,8 @@ repository.workspace = true [dependencies] anyhow = "1.0" -bevy_tasks = "0.11" bytes = "1.2" either = "1.8" -futures-lite = "2.3" once_cell = "1.15" scc = "1.0" rcgen = "0.12" @@ -22,11 +20,8 @@ bones_matchmaker_proto = { version = "0.2", path = "../bones_matchmaker_proto" } clap = { version = "4.0", features = ["derive", "env"] } futures = { version = "0.3", default-features = false, features = ["std", "async-await"] } postcard = { version = "1.0", default-features = false, features = ["alloc"] } -quinn = { version = "0.10", default-features = false, features = ["futures-io", "native-certs", "tls-rustls"] } -quinn_runtime_bevy = { version = "0.3", path = "../quinn_runtime_bevy" } -rustls = { version = "0.21", features = ["dangerous_configuration", "quic"] } serde = { version = "1.0", features = ["derive"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -[dev-dependencies] -async-io = "2.3" +tokio = { version = "1", features = ["rt-multi-thread", "macros"] } +iroh-net = { version = "0.16" } +quinn = { version = "0.10", package = "iroh-quinn" } diff --git a/other_crates/bones_matchmaker/examples/matchmaker_client.rs b/other_crates/bones_matchmaker/examples/matchmaker_client.rs index 1c058c4ebf..f3f161e25a 100644 --- a/other_crates/bones_matchmaker/examples/matchmaker_client.rs +++ b/other_crates/bones_matchmaker/examples/matchmaker_client.rs @@ -1,92 +1,50 @@ -use std::{net::SocketAddr, sync::Arc, time::Duration}; +use std::time::Duration; -use bevy_tasks::{IoTaskPool, TaskPool}; -use bones_matchmaker_proto::{MatchInfo, MatchmakerRequest, MatchmakerResponse}; -use certs::SkipServerVerification; -use quinn::{ClientConfig, Endpoint, EndpointConfig}; -use quinn_runtime_bevy::BevyIoTaskPoolExecutor; +use bones_matchmaker_proto::{ + MatchInfo, MatchmakerRequest, MatchmakerResponse, MATCH_ALPN, PLAY_ALPN, +}; use serde::{Deserialize, Serialize}; +use tokio::task::JoinSet; -static SERVER_NAME: &str = "localhost"; - -fn client_addr() -> SocketAddr { - "127.0.0.1:0".parse::().unwrap() -} - -fn server_addr() -> SocketAddr { - "127.0.0.1:8943".parse::().unwrap() -} +const CLIENT_PORT: u16 = 0; #[derive(Debug, Clone, Serialize, Deserialize)] struct Hello { i_am: String, } -mod certs { - use std::sync::Arc; - - // Implementation of `ServerCertVerifier` that verifies everything as trustworthy. - pub struct SkipServerVerification; - - impl SkipServerVerification { - pub fn new() -> Arc { - Arc::new(Self) - } - } - - impl rustls::client::ServerCertVerifier for SkipServerVerification { - fn verify_server_cert( - &self, - _end_entity: &rustls::Certificate, - _intermediates: &[rustls::Certificate], - _server_name: &rustls::ServerName, - _scts: &mut dyn Iterator, - _ocsp_response: &[u8], - _now: std::time::SystemTime, - ) -> Result { - Ok(rustls::client::ServerCertVerified::assertion()) - } +#[tokio::main] +async fn main() { + if let Err(e) = client().await { + eprintln!("Error: {e}"); } } -fn configure_client() -> ClientConfig { - let crypto = rustls::ClientConfig::builder() - .with_safe_defaults() - .with_custom_certificate_verifier(SkipServerVerification::new()) - .with_no_client_auth(); - - ClientConfig::new(Arc::new(crypto)) -} - -pub fn main() { - IoTaskPool::init(TaskPool::new); - let task_pool = IoTaskPool::get(); - futures_lite::future::block_on(task_pool.spawn(async move { - if let Err(e) = client().await { - eprintln!("Error: {e}"); - } - })); -} - async fn client() -> anyhow::Result<()> { - let client_config = configure_client(); - let socket = std::net::UdpSocket::bind(client_addr())?; - // Bind this endpoint to a UDP socket on the given client address. - let endpoint = Endpoint::new( - EndpointConfig::default(), - None, - socket, - Arc::new(BevyIoTaskPoolExecutor), - )?; + let secret_key = iroh_net::key::SecretKey::generate(); + let endpoint = iroh_net::MagicEndpoint::builder() + .alpns(vec![MATCH_ALPN.to_vec(), PLAY_ALPN.to_vec()]) + .discovery(Box::new( + iroh_net::discovery::ConcurrentDiscovery::from_services(vec![ + Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()), + Box::new(iroh_net::discovery::pkarr_publish::PkarrPublisher::n0_dns( + secret_key.clone(), + )), + ]), + )) + .secret_key(secret_key) + .bind(CLIENT_PORT) + .await?; let i_am = std::env::args().nth(2).unwrap(); let hello = Hello { i_am }; - println!("o Opened client on {}. {hello:?}", endpoint.local_addr()?); + println!("o Opened client ID: {}. {hello:?}", endpoint.node_id()); - // Connect to the server passing in the server name which is supposed to be in the server certificate. - let conn = endpoint - .connect_with(client_config, server_addr(), SERVER_NAME)? - .await?; + let server_id: iroh_net::NodeId = std::env::args().nth(3).expect("missing node id").parse()?; + let server_addr = iroh_net::NodeAddr::new(server_id); + + // Connect to the server + let conn = endpoint.connect(server_addr, MATCH_ALPN).await?; // Send a match request to the server let (mut send, mut recv) = conn.open_bi().await?; @@ -115,7 +73,7 @@ async fn client() -> anyhow::Result<()> { panic!("<= Unexpected message from server!"); } - loop { + let (player_idx, player_ids, client_count) = loop { let mut recv = conn.accept_uni().await?; let message = recv.read_to_end(256).await?; let message: MatchmakerResponse = postcard::from_bytes(&message)?; @@ -128,69 +86,87 @@ async fn client() -> anyhow::Result<()> { random_seed, player_idx, client_count, + player_ids, } => { println!("<= Match is ready! Random seed: {random_seed}. Player IDX: {player_idx}. Client count: {client_count}"); - break; + break (player_idx, player_ids, client_count as usize); } _ => panic!("<= Unexpected message from server"), } - } + }; - let task_pool = IoTaskPool::get(); - - let conn_ = conn.clone(); - task_pool - .spawn(async move { - let result = async move { - for _ in 0..3 { - println!("=> {hello:?}"); - let mut sender = conn_.open_uni().await?; - sender - .write_all(&postcard::to_allocvec(&hello.clone())?) - .await?; - sender.finish().await?; - - async_io::Timer::after(Duration::from_secs(1)).await; - } + println!("Closing matchmaking connection"); + conn.close(0u8.into(), b"done"); - Ok::<_, anyhow::Error>(()) - }; + let mut tasks = JoinSet::default(); + for idx in 0..client_count { + if idx != player_idx as usize { + let endpoint_ = endpoint.clone(); + let hello = hello.clone(); + let player_id = player_ids[idx].as_ref().unwrap().clone(); - if let Err(e) = result.await { - eprintln!("<= Error: {e:?}"); - } - }) - .detach(); + tasks.spawn(async move { + let result = async move { + let conn = endpoint_.connect(player_id.clone(), PLAY_ALPN).await?; + println!("Connected to {}", player_id.node_id); - let conn_ = conn.clone(); - task_pool - .spawn(async move { - loop { - let result = async { - let mut recv = conn_.accept_uni().await?; + for _ in 0..3 { + println!("=> {hello:?}"); + let mut sender = conn.open_uni().await?; + sender + .write_all(&postcard::to_allocvec(&hello.clone())?) + .await?; + sender.finish().await?; - let incomming = recv.read_to_end(256).await?; - let message: Hello = postcard::from_bytes(&incomming).unwrap(); + tokio::time::sleep(Duration::from_secs(1)).await; + } - println!("<= {message:?}"); + conn.close(0u8.into(), b"done"); Ok::<_, anyhow::Error>(()) }; + if let Err(e) = result.await { - eprintln!("Error: {e:?}"); - break; + eprintln!("<= Error: {e:?}"); } - } - }) - .detach(); - - async_io::Timer::after(Duration::from_secs(4)).await; + }); + + let endpoint = endpoint.clone(); + tasks.spawn(async move { + if let Some(mut conn) = endpoint.accept().await { + let result = async { + let alpn = conn.alpn().await?; + if alpn.as_bytes() != PLAY_ALPN { + anyhow::bail!("unexpected ALPN: {}", alpn); + } + let conn = conn.await?; + + for _ in 0..3 { + let mut recv = conn.accept_uni().await?; + println!("<= accepted connection"); + + let incomming = recv.read_to_end(256).await?; + let message: Hello = postcard::from_bytes(&incomming).unwrap(); + + println!("<= {message:?}"); + } + Ok::<_, anyhow::Error>(()) + }; + if let Err(e) = result.await { + eprintln!("Error: {e:?}"); + } + } + }); + } + } - println!("Closing connection"); - conn.close(0u8.into(), b"done"); + // Wait for all tasks to finish + while let Some(task) = tasks.join_next().await { + task?; + } - endpoint.close(0u8.into(), b"done"); - endpoint.wait_idle().await; + // Shutdown the endpoint + endpoint.close(0u8.into(), b"done").await?; Ok(()) } diff --git a/other_crates/bones_matchmaker/src/certs.rs b/other_crates/bones_matchmaker/src/certs.rs deleted file mode 100644 index da79c901c0..0000000000 --- a/other_crates/bones_matchmaker/src/certs.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub fn generate_self_signed_cert() -> anyhow::Result<(rustls::Certificate, rustls::PrivateKey)> { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_string()])?; - let key = rustls::PrivateKey(cert.serialize_private_key_der()); - Ok((rustls::Certificate(cert.serialize_der()?), key)) -} diff --git a/other_crates/bones_matchmaker/src/cli.rs b/other_crates/bones_matchmaker/src/cli.rs index 00ed07cb20..8cb957ac93 100644 --- a/other_crates/bones_matchmaker/src/cli.rs +++ b/other_crates/bones_matchmaker/src/cli.rs @@ -1,19 +1,14 @@ -use bevy_tasks::{IoTaskPool, TaskPool}; use clap::Parser; use tracing::metadata::LevelFilter; -pub fn start() { - IoTaskPool::init(TaskPool::new); - let task_pool = IoTaskPool::get(); +pub async fn start() { configure_logging(); let args = crate::Config::parse(); - futures_lite::future::block_on(task_pool.spawn(async move { - if let Err(e) = super::server(args).await { - eprintln!("Error: {e}"); - } - })); + if let Err(e) = super::server(args).await { + eprintln!("Error: {e}"); + } } fn configure_logging() { diff --git a/other_crates/bones_matchmaker/src/lib.rs b/other_crates/bones_matchmaker/src/lib.rs index 0626d682f1..65c9ffa093 100644 --- a/other_crates/bones_matchmaker/src/lib.rs +++ b/other_crates/bones_matchmaker/src/lib.rs @@ -5,17 +5,13 @@ #[macro_use] extern crate tracing; -use std::{net::SocketAddr, sync::Arc, time::Duration}; +use std::net::SocketAddr; -use bevy_tasks::IoTaskPool; -use quinn::{Endpoint, EndpointConfig, ServerConfig, TransportConfig}; -use quinn_runtime_bevy::BevyIoTaskPoolExecutor; +use bones_matchmaker_proto::MATCH_ALPN; pub mod cli; -mod certs; mod matchmaker; -mod proxy; #[derive(clap::Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -26,26 +22,28 @@ struct Config { } async fn server(args: Config) -> anyhow::Result<()> { - let task_pool = IoTaskPool::get(); + let port = args.listen_addr.port(); - // Generate certificate - let (cert, key) = certs::generate_self_signed_cert()?; + let secret_key = iroh_net::key::SecretKey::generate(); + let endpoint = iroh_net::MagicEndpoint::builder() + .alpns(vec![MATCH_ALPN.to_vec()]) + .discovery(Box::new( + iroh_net::discovery::ConcurrentDiscovery::from_services(vec![ + Box::new(iroh_net::discovery::dns::DnsDiscovery::n0_dns()), + Box::new(iroh_net::discovery::pkarr_publish::PkarrPublisher::n0_dns( + secret_key.clone(), + )), + ]), + )) + .secret_key(secret_key) + .bind(port) + .await?; - let mut transport_config = TransportConfig::default(); - transport_config.keep_alive_interval(Some(Duration::from_secs(5))); + let my_addr = endpoint.my_addr().await?; - let mut server_config = ServerConfig::with_single_cert([cert].to_vec(), key)?; - server_config.transport = Arc::new(transport_config); + info!(address=?my_addr, "Started server"); - // Open Socket and create endpoint - let socket = std::net::UdpSocket::bind(args.listen_addr)?; - let endpoint = Endpoint::new( - EndpointConfig::default(), - Some(server_config), - socket, - Arc::new(BevyIoTaskPoolExecutor), - )?; - info!(address=%endpoint.local_addr()?, "Started server"); + println!("Node ID: {}", my_addr.node_id); // Listen for incomming connections while let Some(connecting) = endpoint.accept().await { @@ -59,9 +57,7 @@ async fn server(args: Config) -> anyhow::Result<()> { ); // Spawn a task to handle the new connection - task_pool - .spawn(matchmaker::handle_connection(conn)) - .detach(); + tokio::task::spawn(matchmaker::handle_connection(endpoint.clone(), conn)); } Err(e) => error!("Error opening client connection: {e:?}"), } diff --git a/other_crates/bones_matchmaker/src/main.rs b/other_crates/bones_matchmaker/src/main.rs index d5652126e0..ca68aeef33 100644 --- a/other_crates/bones_matchmaker/src/main.rs +++ b/other_crates/bones_matchmaker/src/main.rs @@ -1,3 +1,4 @@ -fn main() { - bones_matchmaker::cli::start(); +#[tokio::main] +async fn main() { + bones_matchmaker::cli::start().await; } diff --git a/other_crates/bones_matchmaker/src/matchmaker.rs b/other_crates/bones_matchmaker/src/matchmaker.rs index 932382b44b..200174019b 100644 --- a/other_crates/bones_matchmaker/src/matchmaker.rs +++ b/other_crates/bones_matchmaker/src/matchmaker.rs @@ -1,17 +1,14 @@ -use bevy_tasks::IoTaskPool; use bones_matchmaker_proto::{MatchInfo, MatchmakerRequest, MatchmakerResponse}; -use futures_lite::future; +use iroh_net::{magic_endpoint::get_remote_node_id, MagicEndpoint, NodeAddr}; use once_cell::sync::Lazy; use quinn::{Connection, ConnectionError}; use scc::HashMap; -use crate::proxy::start_proxy; - -pub async fn handle_connection(conn: Connection) { +pub async fn handle_connection(ep: MagicEndpoint, conn: Connection) { let connection_id = conn.stable_id(); debug!(connection_id, "Accepted matchmaker connection"); - if let Err(e) = impl_matchmaker(conn).await { + if let Err(e) = impl_matchmaker(ep, conn).await { match e.downcast::() { Ok(conn_err) => match conn_err { ConnectionError::ApplicationClosed(e) => { @@ -41,22 +38,17 @@ static STATE: Lazy = Lazy::new(State::default); /// client. /// /// At this point the client is free to engage in the matchmaking protocol over that channel. -async fn impl_matchmaker(conn: Connection) -> anyhow::Result<()> { +async fn impl_matchmaker(ep: iroh_net::MagicEndpoint, conn: Connection) -> anyhow::Result<()> { let connection_id = conn.stable_id(); loop { // Get the next channel open or connection close event - let event = future::or(async { either::Left(conn.closed().await) }, async { - either::Right(conn.accept_bi().await) - }) - .await; - - match event { - either::Either::Left(close) => { + tokio::select! { + close = conn.closed() => { debug!("Connection closed {close:?}"); return Ok(()); } - either::Either::Right(bi) => { + bi = conn.accept_bi() => { let (mut send, mut recv) = bi?; // Parse matchmaker request @@ -93,48 +85,46 @@ async fn impl_matchmaker(conn: Connection) -> anyhow::Result<()> { // Spawn task to wait for connction to close and remove it from the room if it does let conn = conn.clone(); let info = match_info.clone(); - IoTaskPool::get() - .spawn(async move { - conn.closed().await; - let members = STATE - .rooms - .update_async(&info, |_, members| { - let mut was_removed = false; - members.retain(|x| { - if x.stable_id() != conn.stable_id() { - true - } else { - was_removed = true; - false - } - }); - - if was_removed { - Some(members.clone()) + tokio::task::spawn(async move { + conn.closed().await; + let members = STATE + .rooms + .update_async(&info, |_, members| { + let mut was_removed = false; + members.retain(|x| { + if x.stable_id() != conn.stable_id() { + true } else { - None + was_removed = true; + false } - }) - .await - .flatten(); - if let Some(members) = members { - let result = async { - let message = postcard::to_allocvec( - &MatchmakerResponse::ClientCount( - members.len() as u8 - ), - )?; - for conn in members { - let mut send = conn.open_uni().await?; - send.write_all(&message).await?; - send.finish().await?; - } - Ok::<(), anyhow::Error>(()) - }; - result.await.ok(); - } - }) - .detach(); + }); + + if was_removed { + Some(members.clone()) + } else { + None + } + }) + .await + .flatten(); + if let Some(members) = members { + let result = async { + let message = postcard::to_allocvec( + &MatchmakerResponse::ClientCount( + members.len() as u8 + ), + )?; + for conn in members { + let mut send = conn.open_uni().await?; + send.write_all(&message).await?; + send.finish().await?; + } + Ok::<(), anyhow::Error>(()) + }; + result.await.ok(); + } + }); let member_count = members.len(); @@ -166,25 +156,43 @@ async fn impl_matchmaker(conn: Connection) -> anyhow::Result<()> { if !members_to_join.is_empty() { // Send the match ID to all of the clients in the room - let mut clients = Vec::with_capacity(player_count as usize); + let mut player_ids = std::array::from_fn(|_| None); let random_seed = rand::random(); - for (idx, conn) in members_to_join.drain(..).enumerate() { + + for (idx, conn) in members_to_join.iter().enumerate() { + let id = get_remote_node_id(&conn)?; + let mut addr = NodeAddr::new(id); + if let Some(info) = ep.connection_info(id) { + if let Some(relay_url) = info.relay_url { + addr = addr.with_relay_url(relay_url.relay_url); + } + addr = addr.with_direct_addresses( + info.addrs.into_iter().map(|addr| addr.addr), + ); + } + + player_ids[idx] = Some(addr); + } + + for (player_idx, conn) in members_to_join.into_iter().enumerate() { // Respond with success let message = postcard::to_allocvec(&MatchmakerResponse::Success { random_seed, client_count: player_count, - player_idx: idx as u8, + player_idx: player_idx as u8, + player_ids: player_ids.clone(), })?; let mut send = conn.open_uni().await?; send.write_all(&message).await?; send.finish().await?; - clients.push(conn); + // Close connection, we are done here + conn.close(0u32.into(), b"done"); } - // Hand the clients off to the game manager - start_proxy(match_info, clients).await; + // cleanup + STATE.rooms.remove_async(&match_info).await; } } } diff --git a/other_crates/bones_matchmaker/src/proxy.rs b/other_crates/bones_matchmaker/src/proxy.rs deleted file mode 100644 index 6c9e72f031..0000000000 --- a/other_crates/bones_matchmaker/src/proxy.rs +++ /dev/null @@ -1,143 +0,0 @@ -use anyhow::format_err; -use bevy_tasks::IoTaskPool; -use bones_matchmaker_proto::{MatchInfo, RecvProxyMessage, SendProxyMessage}; -use bytes::Bytes; -use quinn::Connection; - -pub async fn start_proxy(match_info: MatchInfo, clients: Vec) { - info!(?match_info, "Starting match"); - let client_ids = clients.iter().map(|x| x.stable_id()).collect::>(); - - if let Err(e) = impl_proxy(match_info.clone(), clients).await { - error!(?match_info, ?client_ids, "Error running match: {e}"); - } -} - -async fn impl_proxy(match_info: MatchInfo, clients: Vec) -> anyhow::Result<()> { - let task_pool = IoTaskPool::get(); - - // For each connected client - for (i, conn) in clients.iter().enumerate() { - // Get the client connection - let conn = conn.clone(); - - // And all the connections to it's peers - let peers = clients.clone(); - - // Spawn a task for handling this client's reliable connections - let conn_ = conn.clone(); - let peers_ = peers.clone(); - task_pool - .spawn(async move { - let result = async { - loop { - // Wait for an incomming connection - let mut accept = conn_.accept_uni().await?; - - // Parse the message - let message = accept.read_to_end(1024).await?; - let message = postcard::from_bytes::(&message)?; - let target_client = message.target_client; - let message = message.message; - - let targets = match target_client { - bones_matchmaker_proto::TargetClient::All => peers_.clone(), - bones_matchmaker_proto::TargetClient::One(i) => vec![peers_ - .get(i as usize) - .cloned() - .ok_or_else(|| format_err!("Invalid target client: {i}"))?], - }; - - // Send message to all target clients - let mut send_tasks = Vec::with_capacity(targets.len()); - for target_client in targets { - let message_ = message.clone(); - let task = task_pool.spawn(async move { - // Send the message to the target client - let mut send = target_client.open_uni().await?; - let send_message = RecvProxyMessage { - from_client: i as u8, - message: message_, - }; - let send_message = postcard::to_allocvec(&send_message)?; - send.write_all(&send_message).await?; - send.finish().await?; - - Ok::<_, anyhow::Error>(()) - }); - - send_tasks.push(task); - } - futures::future::try_join_all(send_tasks).await?; - } - - #[allow(unreachable_code)] - Ok::<_, anyhow::Error>(()) - }; - - if let Err(e) = result.await { - warn!("Error in client connection: {e:?}"); - } - }) - .detach(); - - // Spawn task for handling the client's unreliable messages - // TODO: De-duplicate matchmaker proxy code if possible. - // These two task pool spawns have very similar code. It could be good to de-duplicate - // it if possible. - task_pool - .spawn(async move { - let result = async { - loop { - // Wait for an incomming connection - let bytes = conn.read_datagram().await?; - - // Parse the message - let message = postcard::from_bytes::(&bytes)?; - let target_client = message.target_client; - let message = message.message; - - let targets = match target_client { - bones_matchmaker_proto::TargetClient::All => peers.clone(), - bones_matchmaker_proto::TargetClient::One(i) => vec![peers - .get(i as usize) - .cloned() - .ok_or_else(|| format_err!("Invalid target client: {i}"))?], - }; - - // Send message to all target clients - let mut send_tasks = Vec::with_capacity(targets.len()); - // Send the message to the target client - let send_message = RecvProxyMessage { - from_client: i as u8, - message, - }; - let send_message = Bytes::from(postcard::to_allocvec(&send_message)?); - for target_client in targets { - let send_message = send_message.clone(); - let task = task_pool.spawn(async move { - target_client.send_datagram(send_message)?; - - Ok::<_, anyhow::Error>(()) - }); - - send_tasks.push(task); - } - futures::future::try_join_all(send_tasks).await?; - } - - #[allow(unreachable_code)] - Ok::<_, anyhow::Error>(()) - }; - - if let Err(e) = result.await { - warn!("Error in client connection: {e:?}"); - } - }) - .detach(); - } - - info!(?match_info, "Match finished"); - - Ok(()) -} diff --git a/other_crates/bones_matchmaker_proto/Cargo.toml b/other_crates/bones_matchmaker_proto/Cargo.toml index 18441691b9..0ff4cd1f80 100644 --- a/other_crates/bones_matchmaker_proto/Cargo.toml +++ b/other_crates/bones_matchmaker_proto/Cargo.toml @@ -8,4 +8,5 @@ license.workspace = true repository.workspace = true [dependencies] -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } +iroh-net = "0.16" diff --git a/other_crates/bones_matchmaker_proto/src/lib.rs b/other_crates/bones_matchmaker_proto/src/lib.rs index 577d99aaa9..845f8601aa 100644 --- a/other_crates/bones_matchmaker_proto/src/lib.rs +++ b/other_crates/bones_matchmaker_proto/src/lib.rs @@ -5,6 +5,19 @@ use serde::{Deserialize, Serialize}; +/// ALPN used for the matchmaking protocol. +pub const MATCH_ALPN: &[u8] = b"/bones/match/0"; + +/// ALPN used for the direct connections between players. +pub const PLAY_ALPN: &[u8] = b"/bones/play/0"; + +// TODO: Remove this limitation on max players, a variety of types use this for static arrays, +// should either figure out how to make this a compile-time const value specified by game, or +// use dynamic arrays. +// +/// Max players in networked game +pub const MAX_PLAYERS: usize = 4; + // // === Matchmaking Mode === // @@ -47,6 +60,8 @@ pub enum MatchmakerResponse { player_idx: u8, /// The number of connected clients in the match client_count: u8, + /// The node ids of all players. + player_ids: [Option; MAX_PLAYERS], }, } diff --git a/other_crates/quinn_runtime_bevy/CHANGELOG.md b/other_crates/quinn_runtime_bevy/CHANGELOG.md deleted file mode 100644 index cc1d800df9..0000000000 --- a/other_crates/quinn_runtime_bevy/CHANGELOG.md +++ /dev/null @@ -1,82 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## 0.2.0 (2023-06-01) - -### New Features - - - upgrade to Bevy 0.10. - -### Commit Statistics - - - - - 1 commit contributed to the release. - - 134 days passed between releases. - - 1 commit was understood as [conventional](https://www.conventionalcommits.org). - - 1 unique issue was worked on: [#122](https://github.com/fishfolk/bones/issues/122) - -### Commit Details - - - -
view details - - * **[#122](https://github.com/fishfolk/bones/issues/122)** - - upgrade to Bevy 0.10. ([`3f2e348`](https://github.com/fishfolk/bones/commit/3f2e3485f9556cc68eb4c04df34d3aa2c6087330)) -
- -## 0.1.0 (2023-01-18) - - - - -### Documentation - - - document source repository in cargo manifest. - The `repository` key under `bones_ecs` previously pointed to https://github.com/fishfolk/jumpy. - - This updates this to point to the bones repo, and also adds the `repository` key to the other - crates in the repository. - -### New Features - - - migrate crates from the jumpy repository - -### Chore (BREAKING) - - - update bevy_tasks dependency to 0.9.1 - -### Chore - - - generate changelogs for all crates. - -### Commit Statistics - - - - - 5 commits contributed to the release over the course of 26 calendar days. - - 4 commits were understood as [conventional](https://www.conventionalcommits.org). - - 3 unique issues were worked on: [#37](https://github.com/fishfolk/bones/issues/37), [#67](https://github.com/fishfolk/bones/issues/67), [#8](https://github.com/fishfolk/bones/issues/8) - -### Commit Details - - - -
view details - - * **[#37](https://github.com/fishfolk/bones/issues/37)** - - document source repository in cargo manifest. ([`a693894`](https://github.com/fishfolk/bones/commit/a69389412d22b8cb48bab0ed96d739b0fee35348)) - * **[#67](https://github.com/fishfolk/bones/issues/67)** - - generate changelogs for all crates. ([`a68cb79`](https://github.com/fishfolk/bones/commit/a68cb79e6b7d3774c53c0236edf3a12175f297b5)) - * **[#8](https://github.com/fishfolk/bones/issues/8)** - - update bevy_tasks dependency to 0.9.1 ([`98ae10e`](https://github.com/fishfolk/bones/commit/98ae10e7d49a0facc20e08729865c6bc1ebca37a)) - * **Uncategorized** - - Release bones_matchmaker_proto v0.1.0, quinn_runtime_bevy v0.1.0, bones_matchmaker v0.1.0 ([`c6d682f`](https://github.com/fishfolk/bones/commit/c6d682fa4f428f9cb9c963c93061bd477f1d281e)) - - migrate crates from the jumpy repository ([`3724c69`](https://github.com/fishfolk/bones/commit/3724c69a0bb24828d1710380bb8d139e304b7955)) -
- diff --git a/other_crates/quinn_runtime_bevy/Cargo.toml b/other_crates/quinn_runtime_bevy/Cargo.toml deleted file mode 100644 index 622964d902..0000000000 --- a/other_crates/quinn_runtime_bevy/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "quinn_runtime_bevy" -description = "Quinn runtime implementation built on Bevy's IO task pool." -version = "0.3.0" -authors.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true - -[dependencies] -async-executor = "1.4" -async-io = "2.3" -bevy_tasks = "0.11" -futures-lite = "2.3" -pin-project = "1.0" -quinn = { version = "0.10", default-features = false, features = ["native-certs", "tls-rustls"] } -quinn-udp = { version = "0.4", default-features = false } diff --git a/other_crates/quinn_runtime_bevy/README.md b/other_crates/quinn_runtime_bevy/README.md deleted file mode 100644 index 7060772ab4..0000000000 --- a/other_crates/quinn_runtime_bevy/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Quinn Runtime Bevy - -Bevy executor backend for [`quinn`]. diff --git a/other_crates/quinn_runtime_bevy/src/lib.rs b/other_crates/quinn_runtime_bevy/src/lib.rs deleted file mode 100644 index 6e4e784507..0000000000 --- a/other_crates/quinn_runtime_bevy/src/lib.rs +++ /dev/null @@ -1,126 +0,0 @@ -#![doc = include_str!("../README.md")] -// This cfg_attr is needed because `rustdoc::all` includes lints not supported on stable -#![cfg_attr(doc, allow(unknown_lints))] -#![deny(rustdoc::all)] - -use std::{ - io, - ops::Deref, - sync::Arc, - task::{ready, Context, Poll}, -}; - -use async_io::Async; -use bevy_tasks::IoTaskPool; - -#[derive(Clone, Debug)] -pub struct BevyIoTaskPoolExecutor; - -#[derive(Clone, Debug)] -pub struct AsyncExecutor<'a>(pub Arc>); - -impl<'a> Deref for AsyncExecutor<'a> { - type Target = async_executor::Executor<'a>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[derive(Debug)] -#[pin_project::pin_project] -pub struct AsyncIoTimer(#[pin] pub async_io::Timer); - -impl quinn::AsyncTimer for AsyncIoTimer { - fn reset(mut self: std::pin::Pin<&mut Self>, i: std::time::Instant) { - self.0 = async_io::Timer::at(i); - } - - fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context) -> Poll<()> { - let pinned_timer = self.project().0; - ::poll(pinned_timer, cx).map(|_| ()) - } -} - -impl quinn::Runtime for AsyncExecutor<'static> { - fn new_timer(&self, i: std::time::Instant) -> std::pin::Pin> { - Box::pin(AsyncIoTimer(async_io::Timer::at(i))) as _ - } - - fn spawn(&self, future: std::pin::Pin + Send>>) { - self.0.spawn(future).detach(); - } - - fn wrap_udp_socket( - &self, - sock: std::net::UdpSocket, - ) -> io::Result> { - quinn_udp::UdpSocketState::configure((&sock).into())?; - Ok(Box::new(AsyncIoUdpSocket { - io: Async::new(sock)?, - inner: quinn_udp::UdpSocketState::new(), - })) - } -} - -impl quinn::Runtime for BevyIoTaskPoolExecutor { - fn new_timer(&self, i: std::time::Instant) -> std::pin::Pin> { - Box::pin(AsyncIoTimer(async_io::Timer::at(i))) as _ - } - - fn spawn(&self, future: std::pin::Pin + Send>>) { - let io_pool = IoTaskPool::get(); - - io_pool.spawn(future).detach(); - } - - fn wrap_udp_socket( - &self, - sock: std::net::UdpSocket, - ) -> io::Result> { - Ok(Box::new(AsyncIoUdpSocket { - io: Async::new(sock)?, - inner: quinn_udp::UdpSocketState::new(), - })) - } -} - -#[derive(Debug)] -struct AsyncIoUdpSocket { - io: async_io::Async, - inner: quinn_udp::UdpSocketState, -} - -impl quinn::AsyncUdpSocket for AsyncIoUdpSocket { - fn poll_send( - &self, - state: &quinn_udp::UdpState, - cx: &mut Context, - transmits: &[quinn_udp::Transmit], - ) -> Poll> { - loop { - ready!(self.io.poll_writable(cx))?; - if let Ok(res) = self.inner.send((&self.io).into(), state, transmits) { - return Poll::Ready(Ok(res)); - } - } - } - - fn poll_recv( - &self, - cx: &mut Context, - bufs: &mut [io::IoSliceMut<'_>], - meta: &mut [quinn_udp::RecvMeta], - ) -> Poll> { - loop { - ready!(self.io.poll_readable(cx))?; - if let Ok(res) = self.inner.recv((&self.io).into(), bufs, meta) { - return Poll::Ready(Ok(res)); - } - } - } - - fn local_addr(&self) -> io::Result { - self.io.as_ref().local_addr() - } -}