Merge pull request #133 from greatest-ape/work-2023-03-09

udp: improve docs, uring code and uring performance; update README; update dependencies
This commit is contained in:
Joakim Frostegård 2023-03-09 23:34:33 +01:00 committed by GitHub
commit a0c0e85122
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 191 additions and 156 deletions

164
Cargo.lock generated
View file

@ -122,7 +122,7 @@ dependencies = [
"serde", "serde",
"signal-hook", "signal-hook",
"slab", "slab",
"socket2 0.4.7", "socket2 0.4.9",
] ]
[[package]] [[package]]
@ -166,7 +166,7 @@ dependencies = [
"rustls", "rustls",
"serde", "serde",
"signal-hook", "signal-hook",
"socket2 0.4.7", "socket2 0.4.9",
"sqlx", "sqlx",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
@ -223,7 +223,7 @@ dependencies = [
"aquatic_udp_protocol", "aquatic_udp_protocol",
"blake3", "blake3",
"cfg-if", "cfg-if",
"constant_time_eq", "constant_time_eq 0.2.4",
"crossbeam-channel", "crossbeam-channel",
"getrandom", "getrandom",
"hashbrown 0.13.2", "hashbrown 0.13.2",
@ -243,7 +243,7 @@ dependencies = [
"serde", "serde",
"signal-hook", "signal-hook",
"slab", "slab",
"socket2 0.4.7", "socket2 0.4.9",
"time", "time",
"tinytemplate", "tinytemplate",
] ]
@ -282,7 +282,7 @@ dependencies = [
"rand", "rand",
"rand_distr", "rand_distr",
"serde", "serde",
"socket2 0.4.7", "socket2 0.4.9",
] ]
[[package]] [[package]]
@ -324,7 +324,7 @@ dependencies = [
"serde", "serde",
"signal-hook", "signal-hook",
"slab", "slab",
"socket2 0.4.7", "socket2 0.4.9",
"tungstenite", "tungstenite",
] ]
@ -387,9 +387,9 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.64" version = "0.1.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -510,9 +510,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]] [[package]]
name = "base64ct" name = "base64ct"
version = "1.5.3" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bendy" name = "bendy"
@ -546,32 +546,32 @@ checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403"
[[package]] [[package]]
name = "blake3" name = "blake3"
version = "1.3.3" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" checksum = "526c210b4520e416420759af363083471656e819a75e831b8d2c9d5a584f2413"
dependencies = [ dependencies = [
"arrayref", "arrayref",
"arrayvec", "arrayvec",
"cc", "cc",
"cfg-if", "cfg-if",
"constant_time_eq", "constant_time_eq 0.1.5",
"digest", "digest 0.9.0",
] ]
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.3" version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [ dependencies = [
"generic-array", "generic-array",
] ]
[[package]] [[package]]
name = "buddy-alloc" name = "buddy-alloc"
version = "0.4.1" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ff9f338986406db85e2b5deb40a9255b796ca03a194c7457403d215173f3fd5" checksum = "3240a4cb09cf0da6a51641bd40ce90e96ea6065e3a1adc46434029254bcc2d09"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
@ -688,6 +688,12 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]] [[package]]
name = "constant_time_eq" name = "constant_time_eq"
version = "0.2.4" version = "0.2.4"
@ -779,9 +785,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.6" version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
@ -789,9 +795,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-deque" name = "crossbeam-deque"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"crossbeam-epoch", "crossbeam-epoch",
@ -800,14 +806,14 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.13" version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cfg-if", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
"memoffset 0.7.1", "memoffset 0.8.0",
"scopeguard", "scopeguard",
] ]
@ -823,9 +829,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.14" version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
@ -852,9 +858,9 @@ dependencies = [
[[package]] [[package]]
name = "csv" name = "csv"
version = "1.2.0" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad"
dependencies = [ dependencies = [
"csv-core", "csv-core",
"itoa", "itoa",
@ -884,13 +890,21 @@ dependencies = [
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.6" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]]
name = "digest"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"crypto-common", "crypto-common",
"subtle",
] ]
[[package]] [[package]]
@ -1433,7 +1447,7 @@ dependencies = [
"httpdate", "httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"socket2 0.4.7", "socket2 0.4.9",
"tokio", "tokio",
"tower-service", "tower-service",
"tracing", "tracing",
@ -1517,9 +1531,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.5" version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
@ -1551,9 +1565,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.139" version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "libm" name = "libm"
@ -1997,9 +2011,9 @@ dependencies = [
[[package]] [[package]]
name = "paste" name = "paste"
version = "1.0.11" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]] [[package]]
name = "pem-rfc7468" name = "pem-rfc7468"
@ -2248,18 +2262,18 @@ dependencies = [
[[package]] [[package]]
name = "raw-cpuid" name = "raw-cpuid"
version = "10.6.1" version = "10.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c307f7aacdbab3f0adee67d52739a1d71112cc068d6fab169ddeb18e48877fad" checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.6.1" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
dependencies = [ dependencies = [
"either", "either",
"rayon-core", "rayon-core",
@ -2267,9 +2281,9 @@ dependencies = [
[[package]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.10.2" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"crossbeam-deque", "crossbeam-deque",
@ -2334,7 +2348,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"digest", "digest 0.10.5",
"num-bigint-dig", "num-bigint-dig",
"num-integer", "num-integer",
"num-iter", "num-iter",
@ -2376,15 +2390,15 @@ dependencies = [
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.11" version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.12" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]] [[package]]
name = "same-file" name = "same-file"
@ -2419,9 +2433,9 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.154"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
@ -2457,9 +2471,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.152" version = "1.0.154"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2468,9 +2482,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.93" version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -2485,7 +2499,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cpufeatures", "cpufeatures",
"digest", "digest 0.10.5",
] ]
[[package]] [[package]]
@ -2496,7 +2510,7 @@ checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"cpufeatures", "cpufeatures",
"digest", "digest 0.10.5",
] ]
[[package]] [[package]]
@ -2612,9 +2626,9 @@ dependencies = [
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.7" version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [ dependencies = [
"libc", "libc",
"winapi 0.3.9", "winapi 0.3.9",
@ -2679,7 +2693,7 @@ dependencies = [
"bytes", "bytes",
"crc", "crc",
"crossbeam-queue", "crossbeam-queue",
"digest", "digest 0.10.5",
"dotenvy", "dotenvy",
"either", "either",
"event-listener", "event-listener",
@ -2763,9 +2777,9 @@ dependencies = [
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.1" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
@ -2795,18 +2809,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.38" version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.38" version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2869,9 +2883,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.25.0" version = "1.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"bytes", "bytes",
@ -2882,9 +2896,9 @@ dependencies = [
"parking_lot 0.12.1", "parking_lot 0.12.1",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2 0.4.7", "socket2 0.4.9",
"tokio-macros", "tokio-macros",
"windows-sys 0.42.0", "windows-sys 0.45.0",
] ]
[[package]] [[package]]
@ -3042,15 +3056,15 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.10" version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" checksum = "524b68aca1d05e03fdf03fcdce2c6c94b6daf6d16861ddaa7e4f2b6638a9052c"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-normalization"

View file

@ -13,11 +13,11 @@ of sub-implementations for different protocols:
[mio]: https://github.com/tokio-rs/mio [mio]: https://github.com/tokio-rs/mio
[glommio]: https://github.com/DataDog/glommio [glommio]: https://github.com/DataDog/glommio
| Name | Protocol | OS requirements | | Name | Protocol | OS requirements |
|--------------|----------------------------------------------|------------------------------| |--------------|-----------------------------------|--------------------------------------|
| aquatic_udp | [BitTorrent over UDP] | Unix-like (using [mio]) | | aquatic_udp | [BitTorrent over UDP] | Unix-like / Linux 6.0+ with io_uring |
| aquatic_http | [BitTorrent over HTTP] over TLS ([rustls]) | Linux 5.8+ (using [glommio]) | | aquatic_http | [BitTorrent over HTTP] over TLS | Linux 5.8+ |
| aquatic_ws | [WebTorrent], optionally over TLS ([rustls]) | Linux 5.8+ (using [glommio]) | | aquatic_ws | [WebTorrent], optionally over TLS | Linux 5.8+ |
Features at a glance: Features at a glance:
@ -27,6 +27,7 @@ Features at a glance:
- Supports forbidding/allowing info hashes - Supports forbidding/allowing info hashes
- Built-in TLS support (no reverse proxy needed) - Built-in TLS support (no reverse proxy needed)
- Automated CI testing of full file transfers - Automated CI testing of full file transfers
- Prometheus metrics
Known users: Known users:
@ -190,22 +191,24 @@ Implements:
This is the most mature of the implementations. I consider it ready for production use. This is the most mature of the implementations. I consider it ready for production use.
#### Performance
![UDP BitTorrent tracker throughput comparison](./documents/aquatic-udp-load-test-illustration-2023-01-11.png)
More details are available [here](./documents/aquatic-udp-load-test-2023-01-11.pdf).
#### io_uring #### io_uring
An experimental io_uring backend can be compiled in by passing the `io-uring` An experimental io_uring backend is available. It currently requires Linux
feature. Currently, Linux 6.0 or later is required. The application will 6.0 or later and will attempt to fall back to the [mio] backend if run with
attempt to fall back to the mio backend if your kernel is not supported. older kernels. To enable it, pass the `io-uring` feature when compiling:
```sh ```sh
cargo build --release -p aquatic_udp --features "io-uring" cargo build --release -p aquatic_udp --features "io-uring"
``` ```
#### Performance
![UDP BitTorrent tracker throughput comparison](./documents/aquatic-udp-load-test-illustration-2023-01-11.png)
The mio backend was used. More details are available [here](./documents/aquatic-udp-load-test-2023-01-11.pdf).
---
### aquatic_http: HTTP BitTorrent tracker ### aquatic_http: HTTP BitTorrent tracker
[BEP 003]: https://www.bittorrent.org/beps/bep_0003.html [BEP 003]: https://www.bittorrent.org/beps/bep_0003.html
@ -236,6 +239,8 @@ without knowing the exact setup.
More details are available [here](./documents/aquatic-http-load-test-2023-01-25.pdf). More details are available [here](./documents/aquatic-http-load-test-2023-01-25.pdf).
---
### aquatic_ws: WebTorrent tracker ### aquatic_ws: WebTorrent tracker
Aims for compatibility with [WebTorrent](https://github.com/webtorrent) Aims for compatibility with [WebTorrent](https://github.com/webtorrent)

View file

@ -3,9 +3,7 @@
## High priority ## High priority
* udp uring * udp uring
* should queues be synced?
* miri * miri
* uneven performance?
* thiserror? * thiserror?
* CI * CI
* uring load test? * uring load test?

View file

@ -11,23 +11,30 @@ use aquatic_toml_config::TomlConfig;
#[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)] #[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)]
#[serde(default, deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct Config { pub struct Config {
/// Socket workers receive requests from the socket, parse them and send /// Number of socket workers. Increase with core count
/// them on to the swarm workers. They then receive responses from the ///
/// swarm workers, encode them and send them back over the socket. /// Socket workers receive requests from clients and parse them.
/// Responses to connect requests are sent back immediately. Announce and
/// scrape requests are passed on to swarm workers, which generate
/// responses and send them back to the socket worker, which sends them
/// to the client.
pub socket_workers: usize, pub socket_workers: usize,
/// Swarm workers receive a number of requests from socket workers, /// Number of swarm workers. One is enough in almost all cases
/// generate responses and send them back to the socket workers. ///
/// Swarm workers receive parsed announce and scrape requests from socket
/// workers, generate responses and send them back to the socket workers.
pub swarm_workers: usize, pub swarm_workers: usize,
pub log_level: LogLevel, pub log_level: LogLevel,
/// Maximum number of items in each channel passing requests/responses /// Maximum number of items in each channel passing requests/responses
/// between workers. A value of zero means that the channel will be of /// between workers. A value of zero means that the channels will be of
/// unbounded size. /// unbounded size.
pub worker_channel_size: usize, pub worker_channel_size: usize,
/// How long to block waiting for requests in swarm workers. Higher /// How long to block waiting for requests in swarm workers.
/// values means that with zero traffic, the worker will not unnecessarily ///
/// cause the CPU to wake up as often. However, high values (something like /// Higher values means that with zero traffic, the worker will not
/// larger than 1000) combined with very low traffic can cause delays /// unnecessarily cause the CPU to wake up as often. However, high values
/// in torrent cleaning. /// (something like larger than 1000) combined with very low traffic can
/// cause delays in torrent cleaning.
pub request_channel_recv_timeout_ms: u64, pub request_channel_recv_timeout_ms: u64,
pub network: NetworkConfig, pub network: NetworkConfig,
pub protocol: ProtocolConfig, pub protocol: ProtocolConfig,
@ -85,16 +92,18 @@ pub struct NetworkConfig {
/// $ sudo sysctl -w net.core.rmem_max=104857600 /// $ sudo sysctl -w net.core.rmem_max=104857600
/// $ sudo sysctl -w net.core.rmem_default=104857600 /// $ sudo sysctl -w net.core.rmem_default=104857600
pub socket_recv_buffer_size: usize, pub socket_recv_buffer_size: usize,
/// Poll event capacity (mio backend) /// Poll event capacity (mio backend only)
pub poll_event_capacity: usize, pub poll_event_capacity: usize,
/// Poll timeout in milliseconds (mio backend) /// Poll timeout in milliseconds (mio backend only)
pub poll_timeout_ms: u64, pub poll_timeout_ms: u64,
/// Number of ring entries (io_uring backend) /// Number of ring entries (io_uring backend only)
/// ///
/// Will be rounded to next power of two if not already one /// Will be rounded to next power of two if not already one. Increasing
/// this value can help throughput up to a certain point.
#[cfg(feature = "io-uring")] #[cfg(feature = "io-uring")]
pub ring_entries: u16, pub ring_size: u16,
/// Store this many responses at most for retrying (once) on send failure /// Store this many responses at most for retrying (once) on send failure
/// (mio backend only)
/// ///
/// Useful on operating systems that do not provide an udp send buffer, /// Useful on operating systems that do not provide an udp send buffer,
/// such as FreeBSD. Setting the value to zero disables resending /// such as FreeBSD. Setting the value to zero disables resending
@ -120,7 +129,7 @@ impl Default for NetworkConfig {
poll_event_capacity: 4096, poll_event_capacity: 4096,
poll_timeout_ms: 50, poll_timeout_ms: 50,
#[cfg(feature = "io-uring")] #[cfg(feature = "io-uring")]
ring_entries: 1024, ring_size: 1024,
resend_buffer_max_len: 0, resend_buffer_max_len: 0,
} }
} }
@ -129,7 +138,7 @@ impl Default for NetworkConfig {
#[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)] #[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)]
#[serde(default, deny_unknown_fields)] #[serde(default, deny_unknown_fields)]
pub struct ProtocolConfig { pub struct ProtocolConfig {
/// Maximum number of torrents to accept in scrape request /// Maximum number of torrents to allow in scrape request
pub max_scrape_torrents: u8, pub max_scrape_torrents: u8,
/// Maximum number of peers to return in announce response /// Maximum number of peers to return in announce response
pub max_response_peers: usize, pub max_response_peers: usize,
@ -210,8 +219,7 @@ pub struct CleaningConfig {
/// Clean pending scrape responses this often (seconds) /// Clean pending scrape responses this often (seconds)
/// ///
/// In regular operation, there should be no pending scrape responses /// In regular operation, there should be no pending scrape responses
/// lingering for a long time. However, the cleaning also returns unused /// lingering for long enough to have to be cleaned up this way.
/// allocated memory to the OS, so the interval can be configured here.
pub pending_scrape_cleaning_interval: u64, pub pending_scrape_cleaning_interval: u64,
/// Allow clients to use a connection token for this long (seconds) /// Allow clients to use a connection token for this long (seconds)
pub max_connection_age: u32, pub max_connection_age: u32,

View file

@ -34,7 +34,8 @@ use super::storage::PendingScrapeResponseSlab;
use super::validator::ConnectionValidator; use super::validator::ConnectionValidator;
use super::{create_socket, EXTRA_PACKET_SIZE_IPV4, EXTRA_PACKET_SIZE_IPV6}; use super::{create_socket, EXTRA_PACKET_SIZE_IPV4, EXTRA_PACKET_SIZE_IPV6};
const BUF_LEN: usize = 8192; const RESPONSE_BUF_LEN: usize = 8192;
const REQUEST_BUF_LEN: usize = 4096;
const USER_DATA_RECV: u64 = u64::MAX; const USER_DATA_RECV: u64 = u64::MAX;
const USER_DATA_PULSE_TIMEOUT: u64 = u64::MAX - 1; const USER_DATA_PULSE_TIMEOUT: u64 = u64::MAX - 1;
@ -92,9 +93,9 @@ impl SocketWorker {
response_receiver: Receiver<(ConnectedResponse, CanonicalSocketAddr)>, response_receiver: Receiver<(ConnectedResponse, CanonicalSocketAddr)>,
priv_dropper: PrivilegeDropper, priv_dropper: PrivilegeDropper,
) { ) {
let ring_entries = config.network.ring_entries.next_power_of_two(); let ring_entries = config.network.ring_size.next_power_of_two();
// Bias ring towards sending to prevent build-up of unsent responses // Try to fill up the ring with send requests
let send_buffer_entries = ring_entries - (ring_entries / 4); let send_buffer_entries = ring_entries;
let socket = create_socket(&config, priv_dropper).expect("create socket"); let socket = create_socket(&config, priv_dropper).expect("create socket");
let access_list_cache = create_access_list_cache(&shared_state.access_list); let access_list_cache = create_access_list_cache(&shared_state.access_list);
@ -119,7 +120,7 @@ impl SocketWorker {
let buf_ring = buf_ring::Builder::new(0) let buf_ring = buf_ring::Builder::new(0)
.ring_entries(ring_entries) .ring_entries(ring_entries)
.buf_len(BUF_LEN) .buf_len(REQUEST_BUF_LEN)
.build() .build()
.unwrap(); .unwrap();
@ -153,8 +154,9 @@ impl SocketWorker {
let recv_entry = self let recv_entry = self
.recv_helper .recv_helper
.create_entry(self.buf_ring.bgid().try_into().unwrap()); .create_entry(self.buf_ring.bgid().try_into().unwrap());
// This timeout makes it possible to avoid busy-polling and enables // This timeout enables regular updates of pending_scrape_valid_until
// regular updates of pending_scrape_valid_until // and wakes the main loop to send any pending responses in the case
// of no incoming requests
let pulse_timeout_entry = Timeout::new(&self.pulse_timeout as *const _) let pulse_timeout_entry = Timeout::new(&self.pulse_timeout as *const _)
.build() .build()
.user_data(USER_DATA_PULSE_TIMEOUT); .user_data(USER_DATA_PULSE_TIMEOUT);
@ -250,11 +252,11 @@ impl SocketWorker {
} }
} }
// Wait for all sendmsg entries to complete, as well as at least // Wait for all sendmsg entries to complete. If none were added,
// one recvmsg or timeout, in order to avoid busy-polling if there // wait for at least one recvmsg or timeout in order to avoid
// is no incoming data. // busy-polling if there is no incoming data.
ring.submitter() ring.submitter()
.submit_and_wait(num_send_added + 1) .submit_and_wait(num_send_added.max(1))
.unwrap(); .unwrap();
for cqe in ring.completion() { for cqe in ring.completion() {
@ -320,8 +322,13 @@ impl SocketWorker {
response_counter.fetch_add(1, Ordering::Relaxed); response_counter.fetch_add(1, Ordering::Relaxed);
} }
self.send_buffers // Safety: OK because cqe using buffer has been
.mark_index_as_free(send_buffer_index as usize); // returned and contents will no longer be accessed
// by kernel
unsafe {
self.send_buffers
.mark_buffer_as_free(send_buffer_index as usize);
}
} }
} }
} }
@ -339,7 +346,7 @@ impl SocketWorker {
if result < 0 { if result < 0 {
if -result == libc::ENOBUFS { if -result == libc::ENOBUFS {
::log::warn!("recv failed due to lack of buffers, try increasing ring size"); ::log::info!("recv failed due to lack of buffers. If increasing ring size doesn't help, get faster hardware");
} else { } else {
::log::warn!( ::log::warn!(
"recv failed: {:#}", "recv failed: {:#}",

View file

@ -6,7 +6,7 @@ use io_uring::opcode::SendMsg;
use crate::config::Config; use crate::config::Config;
use super::{BUF_LEN, SOCKET_IDENTIFIER}; use super::{RESPONSE_BUF_LEN, SOCKET_IDENTIFIER};
pub enum Error { pub enum Error {
NoBuffers, NoBuffers,
@ -35,13 +35,13 @@ impl ResponseType {
struct SendBuffer { struct SendBuffer {
name_v4: UnsafeCell<libc::sockaddr_in>, name_v4: UnsafeCell<libc::sockaddr_in>,
name_v6: UnsafeCell<libc::sockaddr_in6>, name_v6: UnsafeCell<libc::sockaddr_in6>,
bytes: UnsafeCell<[u8; BUF_LEN]>, bytes: UnsafeCell<[u8; RESPONSE_BUF_LEN]>,
iovec: UnsafeCell<libc::iovec>, iovec: UnsafeCell<libc::iovec>,
msghdr: UnsafeCell<libc::msghdr>, msghdr: UnsafeCell<libc::msghdr>,
free: bool, free: bool,
// Only used for statistics /// Only used for statistics
receiver_is_ipv4: bool, receiver_is_ipv4: bool,
// Only used for statistics /// Only used for statistics
response_type: ResponseType, response_type: ResponseType,
} }
@ -61,7 +61,7 @@ impl SendBuffer {
sin6_addr: libc::in6_addr { s6_addr: [0; 16] }, sin6_addr: libc::in6_addr { s6_addr: [0; 16] },
sin6_scope_id: 0, sin6_scope_id: 0,
}), }),
bytes: UnsafeCell::new([0; BUF_LEN]), bytes: UnsafeCell::new([0; RESPONSE_BUF_LEN]),
iovec: UnsafeCell::new(libc::iovec { iovec: UnsafeCell::new(libc::iovec {
iov_base: null_mut(), iov_base: null_mut(),
iov_len: 0, iov_len: 0,
@ -81,32 +81,34 @@ impl SendBuffer {
} }
} }
/// # Safety fn setup_pointers(&mut self, socket_is_ipv4: bool) {
/// unsafe {
/// - SendBuffer must be stored at a fixed location in memory let iovec = &mut *self.iovec.get();
unsafe fn setup_pointers(&mut self, socket_is_ipv4: bool) {
let iovec = &mut *self.iovec.get();
iovec.iov_base = self.bytes.get() as *mut libc::c_void; iovec.iov_base = self.bytes.get() as *mut libc::c_void;
iovec.iov_len = (&*self.bytes.get()).len(); iovec.iov_len = (&*self.bytes.get()).len();
let msghdr = &mut *self.msghdr.get(); let msghdr = &mut *self.msghdr.get();
msghdr.msg_iov = self.iovec.get(); msghdr.msg_iov = self.iovec.get();
if socket_is_ipv4 { if socket_is_ipv4 {
msghdr.msg_name = self.name_v4.get() as *mut libc::c_void; msghdr.msg_name = self.name_v4.get() as *mut libc::c_void;
msghdr.msg_namelen = core::mem::size_of::<libc::sockaddr_in>() as u32; msghdr.msg_namelen = core::mem::size_of::<libc::sockaddr_in>() as u32;
} else { } else {
msghdr.msg_name = self.name_v6.get() as *mut libc::c_void; msghdr.msg_name = self.name_v6.get() as *mut libc::c_void;
msghdr.msg_namelen = core::mem::size_of::<libc::sockaddr_in6>() as u32; msghdr.msg_namelen = core::mem::size_of::<libc::sockaddr_in6>() as u32;
}
} }
} }
/// # Safety /// # Safety
/// ///
/// - SendBuffer must be stored at a fixed location in memory /// - SendBuffer must be stored at a fixed location in memory
/// - SendBuffer.setup_pointers must have been called previously /// - SendBuffer.setup_pointers must have been called while stored at that
/// fixed location
/// - Contents of struct fields wrapped in UnsafeCell can NOT be accessed
/// simultaneously to this function call
unsafe fn prepare_entry( unsafe fn prepare_entry(
&mut self, &mut self,
response: &Response, response: &Response,
@ -128,6 +130,7 @@ impl SendBuffer {
name.sin_port = addr.port().to_be(); name.sin_port = addr.port().to_be();
name.sin_addr.s_addr = u32::from(*addr.ip()).to_be(); name.sin_addr.s_addr = u32::from(*addr.ip()).to_be();
} else { } else {
// Set receiver protocol type before calling addr.get_ipv6_mapped()
self.receiver_is_ipv4 = addr.is_ipv4(); self.receiver_is_ipv4 = addr.is_ipv4();
let addr = if let SocketAddr::V6(addr) = addr.get_ipv6_mapped() { let addr = if let SocketAddr::V6(addr) = addr.get_ipv6_mapped() {
@ -153,9 +156,7 @@ impl SendBuffer {
self.response_type = ResponseType::from_response(response); self.response_type = ResponseType::from_response(response);
self.free = false; self.free = false;
let sqe = SendMsg::new(SOCKET_IDENTIFIER, self.msghdr.get()).build(); Ok(SendMsg::new(SOCKET_IDENTIFIER, self.msghdr.get()).build())
Ok(sqe)
} }
Err(err) => Err(Error::SerializationFailed(err)), Err(err) => Err(Error::SerializationFailed(err)),
} }
@ -178,10 +179,7 @@ impl SendBuffers {
.into_boxed_slice(); .into_boxed_slice();
for buffer in buffers.iter_mut() { for buffer in buffers.iter_mut() {
// Safety: OK because buffers are stored in fixed memory location buffer.setup_pointers(socket_is_ipv4);
unsafe {
buffer.setup_pointers(socket_is_ipv4);
}
} }
Self { Self {
@ -197,7 +195,11 @@ impl SendBuffers {
(buffer.response_type, buffer.receiver_is_ipv4) (buffer.response_type, buffer.receiver_is_ipv4)
} }
pub fn mark_index_as_free(&mut self, index: usize) { /// # Safety
///
/// Only safe to call once buffer is no longer referenced by in-flight
/// io_uring queue entries
pub unsafe fn mark_buffer_as_free(&mut self, index: usize) {
self.buffers[index].free = true; self.buffers[index].free = true;
} }
@ -215,8 +217,9 @@ impl SendBuffers {
let buffer = self.buffers.index_mut(index); let buffer = self.buffers.index_mut(index);
// Safety: OK because buffers are stored in fixed memory location // Safety: OK because buffers are stored in fixed memory location,
// and buffer pointers were set up in SendBuffers::new() // buffer pointers were set up in SendBuffers::new() and pointers to
// SendBuffer UnsafeCell contents are not accessed elsewhere
unsafe { unsafe {
match buffer.prepare_entry(response, addr, self.socket_is_ipv4) { match buffer.prepare_entry(response, addr, self.socket_is_ipv4) {
Ok(entry) => { Ok(entry) => {