[add] ping jitter, receiver backpressure, stream frame limits
Some checks failed
CI / checks (push) Failing after 1m50s
Some checks failed
CI / checks (push) Failing after 1m50s
This commit is contained in:
parent
c148314742
commit
a6dd73a41f
7 changed files with 449 additions and 189 deletions
270
Cargo.lock
generated
270
Cargo.lock
generated
|
|
@ -176,9 +176,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.12.0"
|
version = "1.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cast"
|
name = "cast"
|
||||||
|
|
@ -188,9 +188,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.65"
|
version = "1.2.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
checksum = "e17dd265a7d0f31ef544e1b20e03add05d3b45b491b633b10d67145d2acc1a38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
|
|
@ -221,6 +221,17 @@ dependencies = [
|
||||||
"cpufeatures 0.2.17",
|
"cpufeatures 0.2.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures 0.3.0",
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chacha20poly1305"
|
name = "chacha20poly1305"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
|
@ -228,7 +239,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aead",
|
"aead",
|
||||||
"chacha20",
|
"chacha20 0.9.1",
|
||||||
"cipher",
|
"cipher",
|
||||||
"poly1305",
|
"poly1305",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
|
@ -402,9 +413,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71fd89660b2dc699704064e59e9dba0147b903e85319429e131620d022be411b"
|
checksum = "a69dedd701da44b0536442edf09c81a64b0ab97a7a4a5e3d1971f00027cbc63d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"const-oid 0.10.2",
|
"const-oid 0.10.2",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
|
@ -592,20 +603,6 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.3.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"js-sys",
|
|
||||||
"libc",
|
|
||||||
"r-efi 5.3.0",
|
|
||||||
"wasip2",
|
|
||||||
"wasm-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
|
@ -615,7 +612,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 6.0.0",
|
"r-efi",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
@ -806,11 +803,11 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jobserver"
|
name = "jobserver"
|
||||||
version = "0.1.34"
|
version = "0.1.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.4.3",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -891,9 +888,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.2"
|
version = "2.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minicov"
|
name = "minicov"
|
||||||
|
|
@ -913,9 +910,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.2.1"
|
version = "1.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
|
checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
|
@ -987,7 +984,7 @@ dependencies = [
|
||||||
"mtp-host",
|
"mtp-host",
|
||||||
"mtp-transport",
|
"mtp-transport",
|
||||||
"mtp-type-map",
|
"mtp-type-map",
|
||||||
"rand 0.8.6",
|
"rand 0.8.7",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
@ -999,9 +996,12 @@ dependencies = [
|
||||||
"mtp-codec",
|
"mtp-codec",
|
||||||
"mtp-common",
|
"mtp-common",
|
||||||
"mtp-crypto",
|
"mtp-crypto",
|
||||||
|
"mtp-host",
|
||||||
"mtp-transport",
|
"mtp-transport",
|
||||||
"rand 0.8.6",
|
"rand 0.8.7",
|
||||||
|
"rcgen",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1013,7 +1013,7 @@ dependencies = [
|
||||||
"mtp-common",
|
"mtp-common",
|
||||||
"mtp-crypto",
|
"mtp-crypto",
|
||||||
"mtp-type-map",
|
"mtp-type-map",
|
||||||
"rand 0.8.6",
|
"rand 0.8.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1061,7 +1061,7 @@ dependencies = [
|
||||||
"mtp-common",
|
"mtp-common",
|
||||||
"mtp-crypto",
|
"mtp-crypto",
|
||||||
"mtp-transport",
|
"mtp-transport",
|
||||||
"rand 0.8.6",
|
"rand 0.8.7",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1076,6 +1076,7 @@ dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
"wtransport",
|
"wtransport",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1269,7 +1270,7 @@ version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
|
checksum = "451913da69c775a56034ea8d9003d27ee8948e12443eae7c038ba100a4f21cb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"der 0.8.0",
|
"der 0.8.1",
|
||||||
"spki 0.8.0",
|
"spki 0.8.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1357,15 +1358,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn-proto"
|
name = "quinn-proto"
|
||||||
version = "0.11.15"
|
version = "0.11.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e"
|
checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"bytes",
|
"bytes",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.4.3",
|
||||||
"lru-slab",
|
"lru-slab",
|
||||||
"rand 0.9.4",
|
"rand 0.10.2",
|
||||||
|
"rand_pcg",
|
||||||
"ring",
|
"ring",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
|
@ -1379,16 +1381,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn-udp"
|
name = "quinn-udp"
|
||||||
version = "0.5.14"
|
version = "0.5.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
|
checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1400,12 +1402,6 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "r-efi"
|
|
||||||
version = "5.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "r-efi"
|
name = "r-efi"
|
||||||
version = "6.0.0"
|
version = "6.0.0"
|
||||||
|
|
@ -1414,23 +1410,24 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.6"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.9.4"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
|
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_chacha 0.9.0",
|
"chacha20 0.10.1",
|
||||||
"rand_core 0.9.5",
|
"getrandom 0.4.3",
|
||||||
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1443,16 +1440,6 @@ dependencies = [
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_chacha"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
|
||||||
dependencies = [
|
|
||||||
"ppv-lite86",
|
|
||||||
"rand_core 0.9.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
|
|
@ -1462,21 +1449,21 @@ dependencies = [
|
||||||
"getrandom 0.2.17",
|
"getrandom 0.2.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.9.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom 0.3.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_pcg"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rcgen"
|
name = "rcgen"
|
||||||
version = "0.14.8"
|
version = "0.14.8"
|
||||||
|
|
@ -1541,9 +1528,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.41"
|
version = "0.23.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
|
checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -1591,9 +1578,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.22"
|
version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
|
|
@ -1802,9 +1789,9 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.4"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
|
|
@ -1827,7 +1814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
|
checksum = "1d9efca8738c78ee9484207732f728b1ef517bbb1833d6fc0879ca898a522f6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64ct",
|
"base64ct",
|
||||||
"der 0.8.0",
|
"der 0.8.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1952,9 +1939,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.11.0"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
|
checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tinyvec_macros",
|
"tinyvec_macros",
|
||||||
]
|
]
|
||||||
|
|
@ -2104,15 +2091,6 @@ version = "0.11.1+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasip2"
|
|
||||||
version = "1.0.4+wasi-0.2.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
|
||||||
dependencies = [
|
|
||||||
"wit-bindgen",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.126"
|
version = "0.2.126"
|
||||||
|
|
@ -2238,16 +2216,7 @@ version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.60.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.53.5",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2265,31 +2234,14 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.6",
|
"windows_aarch64_gnullvm",
|
||||||
"windows_aarch64_msvc 0.52.6",
|
"windows_aarch64_msvc",
|
||||||
"windows_i686_gnu 0.52.6",
|
"windows_i686_gnu",
|
||||||
"windows_i686_gnullvm 0.52.6",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc 0.52.6",
|
"windows_i686_msvc",
|
||||||
"windows_x86_64_gnu 0.52.6",
|
"windows_x86_64_gnu",
|
||||||
"windows_x86_64_gnullvm 0.52.6",
|
"windows_x86_64_gnullvm",
|
||||||
"windows_x86_64_msvc 0.52.6",
|
"windows_x86_64_msvc",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.53.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
|
||||||
dependencies = [
|
|
||||||
"windows-link",
|
|
||||||
"windows_aarch64_gnullvm 0.53.1",
|
|
||||||
"windows_aarch64_msvc 0.53.1",
|
|
||||||
"windows_i686_gnu 0.53.1",
|
|
||||||
"windows_i686_gnullvm 0.53.1",
|
|
||||||
"windows_i686_msvc 0.53.1",
|
|
||||||
"windows_x86_64_gnu 0.53.1",
|
|
||||||
"windows_x86_64_gnullvm 0.53.1",
|
|
||||||
"windows_x86_64_msvc 0.53.1",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2298,102 +2250,48 @@ version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnullvm"
|
name = "windows_i686_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnullvm"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.53.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen"
|
|
||||||
version = "0.57.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "writeable"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
|
|
@ -2502,18 +2400,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.52"
|
version = "0.8.54"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f"
|
checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.52"
|
version = "0.8.54"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930"
|
checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -2596,6 +2494,6 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.21"
|
version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@ mtp-transport = { version = "0.1.0", path = "../transport" }
|
||||||
mtp-crypto = { version = "0.1.0", path = "../crypto", optional = true }
|
mtp-crypto = { version = "0.1.0", path = "../crypto", optional = true }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
tokio = { version = "1", features = ["rt", "sync", "time"] }
|
tokio = { version = "1", features = ["rt", "sync", "time"] }
|
||||||
|
tracing = "0.1"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
mtp-host = { version = "0.1.0", path = "../host" }
|
||||||
|
mtp-transport = { version = "0.1.0", path = "../transport", features = ["host"] }
|
||||||
|
rcgen = "0.14"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
crypto = ["dep:mtp-crypto", "mtp-codec/crypto"]
|
crypto = ["dep:mtp-crypto", "mtp-codec/crypto"]
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ use mtp_codec::{CommunicationValue, DataType, DataValue, PROTOCOL_VERSION, Versi
|
||||||
use mtp_common::CommunicationError;
|
use mtp_common::CommunicationError;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{mpsc, Mutex};
|
use rand::Rng;
|
||||||
|
use tokio::sync::{Mutex, mpsc};
|
||||||
use tokio::time::{Duration, Instant};
|
use tokio::time::{Duration, Instant};
|
||||||
|
|
||||||
pub use MTPClient as Client;
|
pub use MTPClient as Client;
|
||||||
pub use MTPConnection as Connection;
|
pub use MTPConnection as Connection;
|
||||||
pub use mtp_transport::Policy;
|
pub use mtp_transport::Policy;
|
||||||
pub use mtp_transport::Receiver;
|
pub use mtp_transport::Receiver;
|
||||||
#[cfg(feature = "streaming")]
|
|
||||||
pub use mtp_transport::SendMode;
|
pub use mtp_transport::SendMode;
|
||||||
pub use mtp_transport::Sender;
|
pub use mtp_transport::Sender;
|
||||||
|
|
||||||
|
|
@ -34,6 +34,7 @@ pub struct ClientConfig {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub policy: Policy,
|
pub policy: Policy,
|
||||||
pub ping_interval: Duration,
|
pub ping_interval: Duration,
|
||||||
|
pub ping_jitter: Option<Duration>,
|
||||||
pub max_missed_pings: usize,
|
pub max_missed_pings: usize,
|
||||||
pub ping_timestamp: bool,
|
pub ping_timestamp: bool,
|
||||||
#[cfg(feature = "crypto")]
|
#[cfg(feature = "crypto")]
|
||||||
|
|
@ -55,6 +56,7 @@ impl ClientConfig {
|
||||||
description: None,
|
description: None,
|
||||||
policy: Policy::default(),
|
policy: Policy::default(),
|
||||||
ping_interval: Duration::ZERO,
|
ping_interval: Duration::ZERO,
|
||||||
|
ping_jitter: None,
|
||||||
max_missed_pings: 3,
|
max_missed_pings: 3,
|
||||||
ping_timestamp: true,
|
ping_timestamp: true,
|
||||||
#[cfg(feature = "crypto")]
|
#[cfg(feature = "crypto")]
|
||||||
|
|
@ -91,6 +93,11 @@ impl ClientConfig {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_ping_jitter(mut self, jitter: Option<Duration>) -> Self {
|
||||||
|
self.ping_jitter = jitter;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_max_missed_pings(mut self, max_missed_pings: usize) -> Self {
|
pub fn with_max_missed_pings(mut self, max_missed_pings: usize) -> Self {
|
||||||
self.max_missed_pings = max_missed_pings;
|
self.max_missed_pings = max_missed_pings;
|
||||||
self
|
self
|
||||||
|
|
@ -209,6 +216,7 @@ fn start_ping_session(
|
||||||
let last_ping = Arc::new(Mutex::new(None));
|
let last_ping = Arc::new(Mutex::new(None));
|
||||||
let ping_state = last_ping.clone();
|
let ping_state = last_ping.clone();
|
||||||
let interval = config.ping_interval;
|
let interval = config.ping_interval;
|
||||||
|
let ping_jitter = config.ping_jitter;
|
||||||
let max_missed_pings = config.max_missed_pings;
|
let max_missed_pings = config.max_missed_pings;
|
||||||
let ping_timestamp = config.ping_timestamp;
|
let ping_timestamp = config.ping_timestamp;
|
||||||
let mut close_rx = receiver.handle().subscribe_close();
|
let mut close_rx = receiver.handle().subscribe_close();
|
||||||
|
|
@ -231,6 +239,12 @@ fn start_ping_session(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(jitter) = ping_jitter && !jitter.is_zero() {
|
||||||
|
let max_ms = jitter.as_millis() as u64;
|
||||||
|
let extra = rand::thread_rng().gen_range(0..=max_ms);
|
||||||
|
tokio::time::sleep(Duration::from_millis(extra)).await;
|
||||||
|
}
|
||||||
|
|
||||||
let mut ping = CommunicationValue::new(mtp_codec::CommunicationType::Ping);
|
let mut ping = CommunicationValue::new(mtp_codec::CommunicationType::Ping);
|
||||||
if ping_timestamp {
|
if ping_timestamp {
|
||||||
let sent_at = std::time::SystemTime::now()
|
let sent_at = std::time::SystemTime::now()
|
||||||
|
|
@ -817,6 +831,7 @@ mod tests {
|
||||||
.with_max_missed_pings(2)
|
.with_max_missed_pings(2)
|
||||||
.with_ping_timestamp(false);
|
.with_ping_timestamp(false);
|
||||||
assert_eq!(config.ping_interval, Duration::from_secs(5));
|
assert_eq!(config.ping_interval, Duration::from_secs(5));
|
||||||
|
assert_eq!(config.ping_jitter, None);
|
||||||
assert_eq!(config.max_missed_pings, 2);
|
assert_eq!(config.max_missed_pings, 2);
|
||||||
assert!(!config.ping_timestamp);
|
assert!(!config.ping_timestamp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
80
client/tests/ping.rs
Normal file
80
client/tests/ping.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
|
||||||
|
use mtp_client::{ClientConfig, MTPClient};
|
||||||
|
use mtp_host::{HostConfig, MTPHost};
|
||||||
|
|
||||||
|
fn generate_self_signed_cert() -> (Vec<u8>, Vec<u8>) {
|
||||||
|
let key_pair = rcgen::KeyPair::generate().unwrap();
|
||||||
|
let params =
|
||||||
|
rcgen::CertificateParams::new(vec!["localhost".into(), "127.0.0.1".into()]).unwrap();
|
||||||
|
let cert = params.self_signed(&key_pair).unwrap();
|
||||||
|
let cert_pem = cert.pem();
|
||||||
|
let key_pem = key_pair.serialize_pem();
|
||||||
|
(cert_pem.into_bytes(), key_pem.into_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start_host(send_pongs: bool) -> (MTPHost, Vec<u8>) {
|
||||||
|
let (cert_pem, key_pem) = generate_self_signed_cert();
|
||||||
|
let host = MTPHost::new(
|
||||||
|
HostConfig::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0, cert_pem.clone(), key_pem)
|
||||||
|
.with_pongs(send_pongs),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
(host, cert_pem)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_ping_rtt_and_missed_ping_teardown() {
|
||||||
|
let (mut host, cert_pem) = start_host(true).await;
|
||||||
|
let url = format!("https://127.0.0.1:{}", host.local_addr().port());
|
||||||
|
|
||||||
|
let client = MTPClient::connect(
|
||||||
|
ClientConfig::new(url)
|
||||||
|
.with_pinned_pem(cert_pem)
|
||||||
|
.with_ping_interval(std::time::Duration::from_millis(25))
|
||||||
|
.with_max_missed_pings(3),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let _accepted = host.accept().await.unwrap().unwrap();
|
||||||
|
|
||||||
|
let ping = tokio::time::timeout(std::time::Duration::from_secs(5), async {
|
||||||
|
loop {
|
||||||
|
if let Some(ping) = client.get_ping() {
|
||||||
|
return ping;
|
||||||
|
}
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(ping > std::time::Duration::ZERO);
|
||||||
|
|
||||||
|
let (mut silent_host, silent_cert_pem) = start_host(false).await;
|
||||||
|
let silent_url = format!("https://127.0.0.1:{}", silent_host.local_addr().port());
|
||||||
|
let silent_client = MTPClient::connect(
|
||||||
|
ClientConfig::new(silent_url)
|
||||||
|
.with_pinned_pem(silent_cert_pem)
|
||||||
|
.with_ping_interval(std::time::Duration::from_millis(25))
|
||||||
|
.with_max_missed_pings(2),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let _accepted = silent_host.accept().await.unwrap().unwrap();
|
||||||
|
|
||||||
|
let closed = tokio::time::timeout(std::time::Duration::from_secs(5), async {
|
||||||
|
loop {
|
||||||
|
if silent_client.sender.is_closed() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(closed.is_ok(), "client should close after missed pings");
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ tokio = { version = "1", features = ["full"] }
|
||||||
rustls-native-certs = "0.8.4"
|
rustls-native-certs = "0.8.4"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rcgen = "0.14"
|
rcgen = "0.14"
|
||||||
|
tracing = "0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@ use crate::ConnectionHandle;
|
||||||
use mtp_codec::CommunicationValue;
|
use mtp_codec::CommunicationValue;
|
||||||
use mtp_common::CommunicationError;
|
use mtp_common::CommunicationError;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::{mpsc, Mutex, RwLock, Semaphore};
|
use tokio::sync::{mpsc, Mutex, Notify, RwLock, Semaphore};
|
||||||
use tokio::time::{Duration, sleep, timeout};
|
use tokio::time::{Duration, sleep, timeout};
|
||||||
use wtransport::Connection;
|
use wtransport::Connection;
|
||||||
|
use tracing::{debug, info, instrument, trace};
|
||||||
|
|
||||||
const APPLICATION_CLOSE_REASON: &str = "mtp-close";
|
const APPLICATION_CLOSE_REASON: &str = "mtp-close";
|
||||||
|
|
||||||
|
|
@ -33,6 +34,7 @@ pub struct Policy {
|
||||||
pub persistent_stream_retry_backoff: Duration,
|
pub persistent_stream_retry_backoff: Duration,
|
||||||
pub receiver_queue_capacity: usize,
|
pub receiver_queue_capacity: usize,
|
||||||
pub max_concurrent_stream_tasks: usize,
|
pub max_concurrent_stream_tasks: usize,
|
||||||
|
pub max_frames_per_stream: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Policy {
|
impl Default for Policy {
|
||||||
|
|
@ -55,6 +57,7 @@ impl Default for Policy {
|
||||||
persistent_stream_retry_backoff: Duration::from_millis(20),
|
persistent_stream_retry_backoff: Duration::from_millis(20),
|
||||||
receiver_queue_capacity: 1000,
|
receiver_queue_capacity: 1000,
|
||||||
max_concurrent_stream_tasks: 128,
|
max_concurrent_stream_tasks: 128,
|
||||||
|
max_frames_per_stream: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,6 +117,11 @@ impl Policy {
|
||||||
self.max_concurrent_stream_tasks = max_concurrent_stream_tasks;
|
self.max_concurrent_stream_tasks = max_concurrent_stream_tasks;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_max_frames_per_stream(mut self, max_frames_per_stream: Option<usize>) -> Self {
|
||||||
|
self.max_frames_per_stream = max_frames_per_stream;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ReceivedFrame {
|
enum ReceivedFrame {
|
||||||
|
|
@ -142,6 +150,7 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(stream, data, policy), level = "trace")]
|
||||||
async fn write_frame(
|
async fn write_frame(
|
||||||
stream: &mut wtransport::SendStream,
|
stream: &mut wtransport::SendStream,
|
||||||
data: &CommunicationValue,
|
data: &CommunicationValue,
|
||||||
|
|
@ -189,6 +198,7 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(conn, policy), level = "trace")]
|
||||||
async fn open_uni_stream(
|
async fn open_uni_stream(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
policy: &Policy,
|
policy: &Policy,
|
||||||
|
|
@ -221,6 +231,7 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(conn, stream_opt, data, policy), level = "trace")]
|
||||||
async fn send_on_persistent_stream(
|
async fn send_on_persistent_stream(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
stream_opt: &mut Option<wtransport::SendStream>,
|
stream_opt: &mut Option<wtransport::SendStream>,
|
||||||
|
|
@ -254,6 +265,7 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(conn, data, policy), level = "trace")]
|
||||||
async fn send_on_single_stream(
|
async fn send_on_single_stream(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
data: &CommunicationValue,
|
data: &CommunicationValue,
|
||||||
|
|
@ -279,6 +291,7 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(conn, policy), level = "trace")]
|
||||||
async fn send_close_frame(
|
async fn send_close_frame(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
policy: &Policy,
|
policy: &Policy,
|
||||||
|
|
@ -319,6 +332,7 @@ impl Sender {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self, data), level = "trace")]
|
||||||
pub async fn send(&self, data: &CommunicationValue) -> Result<(), CommunicationError> {
|
pub async fn send(&self, data: &CommunicationValue) -> Result<(), CommunicationError> {
|
||||||
if self.handle.is_closed() {
|
if self.handle.is_closed() {
|
||||||
return Err(self
|
return Err(self
|
||||||
|
|
@ -374,6 +388,7 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
pub async fn finish_stream(&self) -> Result<(), CommunicationError> {
|
pub async fn finish_stream(&self) -> Result<(), CommunicationError> {
|
||||||
let _send_lock = self.send_guard.lock().await;
|
let _send_lock = self.send_guard.lock().await;
|
||||||
let mut stream_opt = self.stream_guard.lock().await;
|
let mut stream_opt = self.stream_guard.lock().await;
|
||||||
|
|
@ -403,7 +418,9 @@ impl Sender {
|
||||||
&self.handle
|
&self.handle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
pub fn close(&self) {
|
pub fn close(&self) {
|
||||||
|
info!(target = "mtp.transport", "fire-and-forget close requested");
|
||||||
let connection = self.connection.clone();
|
let connection = self.connection.clone();
|
||||||
let handle = self.handle.clone();
|
let handle = self.handle.clone();
|
||||||
let policy = self.policy.clone();
|
let policy = self.policy.clone();
|
||||||
|
|
@ -431,6 +448,7 @@ impl Sender {
|
||||||
let _ = Self::send_close_frame(&connection, &policy).await;
|
let _ = Self::send_close_frame(&connection, &policy).await;
|
||||||
|
|
||||||
handle.close(Some(CommunicationError::StreamClosed));
|
handle.close(Some(CommunicationError::StreamClosed));
|
||||||
|
info!(target = "mtp.transport", "connection closed");
|
||||||
|
|
||||||
sleep(policy.force_close_delay).await;
|
sleep(policy.force_close_delay).await;
|
||||||
if connection.quic_connection().close_reason().is_none() {
|
if connection.quic_connection().close_reason().is_none() {
|
||||||
|
|
@ -442,6 +460,51 @@ impl Sender {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
|
/// Initiate a best-effort graceful close and wait for the configured force-close delay.
|
||||||
|
pub async fn close_and_wait(&self) {
|
||||||
|
info!(target = "mtp.transport", "graceful close initiated");
|
||||||
|
let connection = self.connection.clone();
|
||||||
|
let handle = self.handle.clone();
|
||||||
|
let policy = self.policy.clone();
|
||||||
|
let mut stream_opt = self.stream_guard.lock().await;
|
||||||
|
|
||||||
|
if connection.quic_connection().close_reason().is_some() || handle.is_closed() {
|
||||||
|
handle.close(Some(CommunicationError::StreamClosed));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut stream) = stream_opt.take() {
|
||||||
|
let close_bytes = policy.close_frame_len.to_be_bytes();
|
||||||
|
let close_write = async {
|
||||||
|
stream.write_all(&close_bytes).await?;
|
||||||
|
stream.finish().await
|
||||||
|
};
|
||||||
|
|
||||||
|
match timeout(policy.write_timeout, close_write).await {
|
||||||
|
Ok(Ok(())) => {}
|
||||||
|
Ok(Err(wtransport::error::StreamWriteError::Stopped(code))) => log::warn!(
|
||||||
|
"[Sender] close_and_wait failed: peer sent STOP_SENDING (error code {code})"
|
||||||
|
),
|
||||||
|
Ok(Err(e)) => log::warn!("[Sender] close_and_wait failed: {e}"),
|
||||||
|
Err(_) => log::warn!("[Sender] close_and_wait timed out"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let _ = Self::send_close_frame(&connection, &policy).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.close(Some(CommunicationError::StreamClosed));
|
||||||
|
info!(target = "mtp.transport", "connection closed");
|
||||||
|
|
||||||
|
sleep(policy.force_close_delay).await;
|
||||||
|
if connection.quic_connection().close_reason().is_none() {
|
||||||
|
connection.quic_connection().close(
|
||||||
|
policy.application_close_code.into(),
|
||||||
|
APPLICATION_CLOSE_REASON.as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_open(&self) -> bool {
|
pub fn is_open(&self) -> bool {
|
||||||
self.handle.is_open()
|
self.handle.is_open()
|
||||||
}
|
}
|
||||||
|
|
@ -455,11 +518,17 @@ impl Sender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Single-consumer framed message receiver.
|
||||||
|
///
|
||||||
|
/// `receive()` is intended to be driven by one task at a time. Internally the
|
||||||
|
/// underlying `mpsc::Receiver` is protected by a mutex so the type remains
|
||||||
|
/// `Sync`, but it is not a multi-consumer queue.
|
||||||
pub struct Receiver {
|
pub struct Receiver {
|
||||||
rx: Mutex<mpsc::Receiver<Result<CommunicationValue, CommunicationError>>>,
|
rx: Mutex<mpsc::Receiver<Result<CommunicationValue, CommunicationError>>>,
|
||||||
_accept_task: tokio::task::JoinHandle<()>,
|
_accept_task: tokio::task::JoinHandle<()>,
|
||||||
handle: Arc<ConnectionHandle>,
|
handle: Arc<ConnectionHandle>,
|
||||||
ping_control: Arc<RwLock<PingControl>>,
|
ping_control: Arc<RwLock<PingControl>>,
|
||||||
|
queue_notify: Arc<Notify>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
|
@ -491,13 +560,40 @@ impl Receiver {
|
||||||
let accept_policy = policy.clone();
|
let accept_policy = policy.clone();
|
||||||
let ping_control = Arc::new(RwLock::new(PingControl::default()));
|
let ping_control = Arc::new(RwLock::new(PingControl::default()));
|
||||||
let accept_ping_control = ping_control.clone();
|
let accept_ping_control = ping_control.clone();
|
||||||
|
let queue_notify = Arc::new(Notify::new());
|
||||||
|
let accept_queue_notify = queue_notify.clone();
|
||||||
let stream_limit = Arc::new(Semaphore::new(policy.max_concurrent_stream_tasks.max(1)));
|
let stream_limit = Arc::new(Semaphore::new(policy.max_concurrent_stream_tasks.max(1)));
|
||||||
let accept_stream_limit = stream_limit.clone();
|
let accept_stream_limit = stream_limit.clone();
|
||||||
|
debug!(
|
||||||
|
target = "mtp.transport",
|
||||||
|
max_concurrent_stream_tasks = policy.max_concurrent_stream_tasks,
|
||||||
|
receiver_queue_capacity = policy.receiver_queue_capacity,
|
||||||
|
"receiver accept loop started"
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
target = "mtp.transport",
|
||||||
|
max_concurrent_stream_tasks = policy.max_concurrent_stream_tasks,
|
||||||
|
receiver_queue_capacity = policy.receiver_queue_capacity,
|
||||||
|
"connection accepted"
|
||||||
|
);
|
||||||
|
|
||||||
let accept_task = tokio::spawn(async move {
|
let accept_task = tokio::spawn(async move {
|
||||||
let mut close_rx = conn_handle.subscribe_close();
|
let mut close_rx = conn_handle.subscribe_close();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
if tx.capacity() == 0 {
|
||||||
|
trace!(target = "mtp.transport", "accept loop paused: receiver queue full");
|
||||||
|
tokio::select! {
|
||||||
|
_ = close_rx.changed() => {
|
||||||
|
if close_rx.borrow().is_some() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = accept_queue_notify.notified() => {}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = close_rx.changed() => {
|
_ = close_rx.changed() => {
|
||||||
if close_rx.borrow().is_some() {
|
if close_rx.borrow().is_some() {
|
||||||
|
|
@ -523,9 +619,20 @@ impl Receiver {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let _permit = permit;
|
let _permit = permit;
|
||||||
let mut s = stream;
|
let mut s = stream;
|
||||||
|
let mut frame_count = 0usize;
|
||||||
loop {
|
loop {
|
||||||
|
if let Some(max_frames) = stream_policy.max_frames_per_stream
|
||||||
|
&& frame_count >= max_frames
|
||||||
|
{
|
||||||
|
let close_error = CommunicationError::StreamError;
|
||||||
|
let _ = tx_stream.send(Err(close_error.clone())).await;
|
||||||
|
stream_handle.close(Some(close_error));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
match Self::read_one_frame(&mut s, &stream_policy).await {
|
match Self::read_one_frame(&mut s, &stream_policy).await {
|
||||||
Ok(ReceivedFrame::Message(msg)) => {
|
Ok(ReceivedFrame::Message(msg)) => {
|
||||||
|
frame_count += 1;
|
||||||
let ping_type = mtp_codec::CommunicationType::Ping
|
let ping_type = mtp_codec::CommunicationType::Ping
|
||||||
.to_id(&mtp_codec::TypeMap::latest());
|
.to_id(&mtp_codec::TypeMap::latest());
|
||||||
let pong_type = mtp_codec::CommunicationType::Pong
|
let pong_type = mtp_codec::CommunicationType::Pong
|
||||||
|
|
@ -630,6 +737,7 @@ impl Receiver {
|
||||||
_accept_task: accept_task,
|
_accept_task: accept_task,
|
||||||
handle,
|
handle,
|
||||||
ping_control,
|
ping_control,
|
||||||
|
queue_notify,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -651,6 +759,7 @@ impl Receiver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(stream, policy), level = "trace")]
|
||||||
async fn read_one_frame(
|
async fn read_one_frame(
|
||||||
stream: &mut wtransport::RecvStream,
|
stream: &mut wtransport::RecvStream,
|
||||||
policy: &Policy,
|
policy: &Policy,
|
||||||
|
|
@ -726,6 +835,7 @@ impl Receiver {
|
||||||
Ok(ReceivedFrame::Message(message))
|
Ok(ReceivedFrame::Message(message))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "trace")]
|
||||||
pub async fn receive(&self) -> Result<CommunicationValue, CommunicationError> {
|
pub async fn receive(&self) -> Result<CommunicationValue, CommunicationError> {
|
||||||
if self.handle.is_closed() {
|
if self.handle.is_closed() {
|
||||||
return Err(self
|
return Err(self
|
||||||
|
|
@ -736,7 +846,10 @@ impl Receiver {
|
||||||
|
|
||||||
let mut rx = self.rx.lock().await;
|
let mut rx = self.rx.lock().await;
|
||||||
match rx.recv().await {
|
match rx.recv().await {
|
||||||
Some(result) => result,
|
Some(result) => {
|
||||||
|
self.queue_notify.notify_one();
|
||||||
|
result
|
||||||
|
}
|
||||||
_ => Err(self
|
_ => Err(self
|
||||||
.handle
|
.handle
|
||||||
.close_reason()
|
.close_reason()
|
||||||
|
|
@ -796,6 +909,7 @@ mod tests {
|
||||||
assert_eq!(p.persistent_stream_retry_backoff, Duration::from_millis(20));
|
assert_eq!(p.persistent_stream_retry_backoff, Duration::from_millis(20));
|
||||||
assert_eq!(p.receiver_queue_capacity, 1000);
|
assert_eq!(p.receiver_queue_capacity, 1000);
|
||||||
assert_eq!(p.max_concurrent_stream_tasks, 128);
|
assert_eq!(p.max_concurrent_stream_tasks, 128);
|
||||||
|
assert_eq!(p.max_frames_per_stream, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -199,3 +199,149 @@ async fn test_drop_receiver_keeps_sender_alive() {
|
||||||
client_tx.close();
|
client_tx.close();
|
||||||
host_tx.close();
|
host_tx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_persistent_stream_reopens_after_local_finish() {
|
||||||
|
let (_h, client_tx, client_rx, host_tx, host_rx) = connected_pair().await;
|
||||||
|
|
||||||
|
let tm = TypeMap::latest();
|
||||||
|
let msg1 = numbered_message(CommunicationType::Ping, 11, &tm);
|
||||||
|
client_tx.send(&msg1).await.unwrap();
|
||||||
|
let received1 = host_rx.receive().await.unwrap();
|
||||||
|
assert_numbered_message(&received1, CommunicationType::Ping, 11, &tm);
|
||||||
|
|
||||||
|
client_tx.finish_stream().await.unwrap();
|
||||||
|
|
||||||
|
let msg2 = numbered_message(CommunicationType::Pong, 22, &tm);
|
||||||
|
client_tx.send(&msg2).await.unwrap();
|
||||||
|
let received2 = host_rx.receive().await.unwrap();
|
||||||
|
assert_numbered_message(&received2, CommunicationType::Pong, 22, &tm);
|
||||||
|
|
||||||
|
client_tx.close();
|
||||||
|
host_tx.close();
|
||||||
|
drop(client_rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_receiver_backpressure_with_small_queue() {
|
||||||
|
let (cert_pem, key_pem) = generate_self_signed_cert();
|
||||||
|
let mut h = start_test_host(cert_pem.clone(), key_pem).await;
|
||||||
|
let url = format!("https://127.0.0.1:{}", h.local_addr().port());
|
||||||
|
let policy = Policy::default().with_receiver_queue_capacity(1);
|
||||||
|
let (client_tx, client_rx) = connect(&url, Some(cert_pem), policy.clone())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let (_host_tx, host_rx) = h.next().await.unwrap();
|
||||||
|
|
||||||
|
let tm = TypeMap::latest();
|
||||||
|
for i in 0..8u128 {
|
||||||
|
client_tx
|
||||||
|
.send(&numbered_message(CommunicationType::Ping, i, &tm))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..8u128 {
|
||||||
|
let received = tokio::time::timeout(
|
||||||
|
std::time::Duration::from_secs(5),
|
||||||
|
host_rx.receive(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
assert_numbered_message(&received, CommunicationType::Ping, i, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
client_tx.close();
|
||||||
|
drop(client_rx);
|
||||||
|
h.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_max_frames_per_stream_enforced() {
|
||||||
|
let (cert_pem, key_pem) = generate_self_signed_cert();
|
||||||
|
let policy = Policy::default().with_max_frames_per_stream(Some(1));
|
||||||
|
let mut h = host(
|
||||||
|
IpAddr::V4(Ipv4Addr::LOCALHOST),
|
||||||
|
0,
|
||||||
|
cert_pem.clone(),
|
||||||
|
key_pem,
|
||||||
|
policy,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let url = format!("https://127.0.0.1:{}", h.local_addr().port());
|
||||||
|
let (client_tx, _client_rx) = connect(&url, Some(cert_pem), Policy::default())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let (_host_tx, host_rx) = h.next().await.unwrap();
|
||||||
|
|
||||||
|
let tm = TypeMap::latest();
|
||||||
|
client_tx
|
||||||
|
.send(&numbered_message(CommunicationType::Ping, 1, &tm))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let first = host_rx.receive().await.unwrap();
|
||||||
|
assert_numbered_message(&first, CommunicationType::Ping, 1, &tm);
|
||||||
|
|
||||||
|
client_tx
|
||||||
|
.send(&numbered_message(CommunicationType::Ping, 2, &tm))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let second = host_rx.receive().await;
|
||||||
|
assert!(second.is_err(), "stream should be closed after frame limit");
|
||||||
|
|
||||||
|
client_tx.close();
|
||||||
|
h.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_semaphore_saturation_with_concurrent_streams() {
|
||||||
|
let (cert_pem, key_pem) = generate_self_signed_cert();
|
||||||
|
let policy = Policy::default()
|
||||||
|
.with_send_mode(mtp_transport::SendMode::SingleStreamPerMessage)
|
||||||
|
.with_receiver_queue_capacity(1)
|
||||||
|
.with_max_concurrent_stream_tasks(1);
|
||||||
|
let mut h = host(
|
||||||
|
IpAddr::V4(Ipv4Addr::LOCALHOST),
|
||||||
|
0,
|
||||||
|
cert_pem.clone(),
|
||||||
|
key_pem,
|
||||||
|
policy,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let url = format!("https://127.0.0.1:{}", h.local_addr().port());
|
||||||
|
let (client_tx, _client_rx) = connect(&url, Some(cert_pem), Policy::default())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let (_host_tx, host_rx) = h.next().await.unwrap();
|
||||||
|
|
||||||
|
let tm = TypeMap::latest();
|
||||||
|
let mut joins = Vec::new();
|
||||||
|
for i in 0..6u128 {
|
||||||
|
let tx = client_tx.clone();
|
||||||
|
let msg = numbered_message(CommunicationType::Ping, i, &tm);
|
||||||
|
joins.push(tokio::spawn(async move { tx.send(&msg).await }));
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||||
|
|
||||||
|
for join in joins {
|
||||||
|
join.await.unwrap().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..6u128 {
|
||||||
|
let received = tokio::time::timeout(
|
||||||
|
std::time::Duration::from_secs(5),
|
||||||
|
host_rx.receive(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
assert_numbered_message(&received, CommunicationType::Ping, i, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
client_tx.close();
|
||||||
|
h.shutdown();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue