From 11829f98ebe45e087ab59c26cfd0abf0e37f6188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 12:27:48 +0200 Subject: [PATCH 01/62] WIP: start work on aquatic_http_private --- Cargo.lock | 904 ++++++++- Cargo.toml | 4 +- aquatic_http_private/.gitignore | 2 + aquatic_http_private/Cargo.lock | 1664 +++++++++++++++++ aquatic_http_private/Cargo.toml | 13 + aquatic_http_private/README.md | 41 + aquatic_http_private/src/main.rs | 24 + aquatic_http_private/src/workers/mod.rs | 1 + aquatic_http_private/src/workers/socket/db.rs | 102 + .../src/workers/socket/mod.rs | 67 + .../src/workers/socket/routes.rs | 21 + 11 files changed, 2821 insertions(+), 22 deletions(-) create mode 100644 aquatic_http_private/.gitignore create mode 100644 aquatic_http_private/Cargo.lock create mode 100644 aquatic_http_private/Cargo.toml create mode 100644 aquatic_http_private/README.md create mode 100644 aquatic_http_private/src/main.rs create mode 100644 aquatic_http_private/src/workers/mod.rs create mode 100644 aquatic_http_private/src/workers/socket/db.rs create mode 100644 aquatic_http_private/src/workers/socket/mod.rs create mode 100644 aquatic_http_private/src/workers/socket/routes.rs diff --git a/Cargo.lock b/Cargo.lock index 5eaf471..3151194 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,10 +135,22 @@ dependencies = [ "quickcheck_macros", "rand", "rand_distr", - "rustls", + "rustls 0.20.4", "serde", ] +[[package]] +name = "aquatic_http_private" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "dotenv", + "socket2 0.4.4", + "sqlx", + "tokio", +] + [[package]] name = "aquatic_http_protocol" version = "0.2.0" @@ -279,7 +291,7 @@ dependencies = [ "quickcheck", "quickcheck_macros", "rand", - "rustls", + "rustls 0.20.4", "rustls-pemfile", "serde", "signal-hook", @@ -307,7 +319,7 @@ dependencies = [ "quickcheck_macros", "rand", "rand_distr", - "rustls", + "rustls 0.20.4", "serde", "serde_json", "tungstenite", @@ -343,6 +355,17 @@ dependencies = [ "nodrop", ] +[[package]] +name = "async-trait" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-tungstenite" version = "0.17.2" @@ -356,6 +379,15 @@ dependencies = [ "tungstenite", ] +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] + [[package]] name = "atone" version = "0.3.5" @@ -373,12 +405,65 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5611d4977882c5af1c0f7a34d51b5d87f784f86912bb543986b014ea4995ef93" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "hyper", + "itoa 1.0.1", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cd109b3e93c9541dcce5b0219dcf89169dcc58c1bebed65082808324258afb" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", +] + [[package]] name = "backtrace" version = "0.3.64" @@ -400,6 +485,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b4d9b1225d28d360ec6a231d65af1fd99a2a095154c8040689617290569c5c" + [[package]] name = "bendy" version = "0.3.3" @@ -429,6 +520,15 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "303cec55cd9c5fde944b061b902f142b52a8bb5438cc822481ea1e3ebc96bbcb" +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.2" @@ -545,6 +645,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" + [[package]] name = "cpufeatures" version = "0.2.2" @@ -554,6 +660,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + [[package]] name = "criterion" version = "0.3.5" @@ -631,7 +752,7 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ - "autocfg", + "autocfg 1.1.0", "cfg-if", "crossbeam-utils", "lazy_static", @@ -659,6 +780,17 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crypto-bigint" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" +dependencies = [ + "generic-array", + "rand_core", + "subtle", +] + [[package]] name = "crypto-common" version = "0.1.3" @@ -691,16 +823,41 @@ dependencies = [ "memchr", ] +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid", + "crypto-bigint", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "digest" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer", + "block-buffer 0.10.2", "crypto-common", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "either" version = "1.6.1" @@ -861,6 +1018,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + [[package]] name = "futures-io" version = "0.3.21" @@ -900,8 +1068,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01fe9932a224b72b45336d96040aa86386d674a31d0af27d800ea7bc8ca97fe" dependencies = [ "futures-io", - "rustls", - "webpki", + "rustls 0.20.4", + "webpki 0.22.0", ] [[package]] @@ -1053,6 +1221,15 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.12.0" @@ -1063,6 +1240,49 @@ dependencies = [ "serde", ] +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown 0.11.2", +] + +[[package]] +name = "headers" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +dependencies = [ + "base64", + "bitflags 1.3.2", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha-1 0.10.0", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1089,12 +1309,35 @@ dependencies = [ "itoa 1.0.1", ] +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + [[package]] name = "httparse" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + [[package]] name = "hwloc" version = "0.5.0" @@ -1110,6 +1353,29 @@ dependencies = [ "winapi 0.2.8", ] +[[package]] +name = "hyper" +version = "0.14.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.1", + "pin-project-lite", + "socket2 0.4.4", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "idna" version = "0.2.3" @@ -1121,6 +1387,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg 1.1.0", + "hashbrown 0.11.2", +] + [[package]] name = "indexmap-amortized" version = "1.6.1" @@ -1128,7 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81b5a05ffb45214e51fdd40c1f773ab57c74d2a7b41cfadc7ea443acf0359df1" dependencies = [ "atone", - "autocfg", + "autocfg 1.1.0", "griddle", ] @@ -1207,6 +1483,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" @@ -1235,7 +1514,7 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ - "autocfg", + "autocfg 1.1.0", "scopeguard", ] @@ -1263,6 +1542,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "matchit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + [[package]] name = "membarrier" version = "0.2.2" @@ -1287,7 +1572,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -1296,7 +1581,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -1308,6 +1593,18 @@ dependencies = [ "libmimalloc-sys", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.4.4" @@ -1315,7 +1612,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", - "autocfg", + "autocfg 1.1.0", ] [[package]] @@ -1375,6 +1672,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "ntapi" version = "0.3.7" @@ -1395,6 +1702,35 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4547ee5541c18742396ae2c895d0717d0f886d8823b8399cdaf7b07d63ad0480" +dependencies = [ + "autocfg 0.1.8", + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-format" version = "0.4.0" @@ -1411,7 +1747,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-traits", ] @@ -1421,7 +1757,7 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" dependencies = [ - "autocfg", + "autocfg 1.1.0", "num-integer", "num-traits", ] @@ -1432,7 +1768,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg", + "autocfg 1.1.0", "libm", ] @@ -1482,6 +1818,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "owned-alloc" version = "0.2.0" @@ -1494,6 +1836,69 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.2", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "paste" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" + +[[package]] +name = "pem-rfc7468" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e93a3b1cc0510b03020f33f21e62acdde3dcaef432edc95bea377fbd4c2cd4" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -1532,6 +1937,30 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "116bee8279d783c0cf370efa1a94632f2108e5ef0bb32df31f051647810a4e2c" +dependencies = [ + "der", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" +dependencies = [ + "der", + "pem-rfc7468", + "pkcs1", + "spki", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -1668,7 +2097,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ - "autocfg", + "autocfg 1.1.0", "crossbeam-deque", "either", "rayon-core", @@ -1687,6 +2116,15 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "regex" version = "1.5.5" @@ -1734,6 +2172,26 @@ dependencies = [ "libc", ] +[[package]] +name = "rsa" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c2603e2823634ab331437001b411b9ed11660fbc4066f3908c84a9439260d" +dependencies = [ + "byteorder", + "digest 0.9.0", + "lazy_static", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -1749,6 +2207,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct 0.6.1", + "webpki 0.21.4", +] + [[package]] name = "rustls" version = "0.20.4" @@ -1757,8 +2228,8 @@ checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" dependencies = [ "log", "ring", - "sct", - "webpki", + "sct 0.7.0", + "webpki 0.22.0", ] [[package]] @@ -1797,6 +2268,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sct" version = "0.7.0" @@ -1873,6 +2354,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha-1" version = "0.10.0" @@ -1881,7 +2375,20 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.10.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", ] [[package]] @@ -1959,7 +2466,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" dependencies = [ - "autocfg", + "autocfg 1.1.0", "static_assertions", "version_check", ] @@ -2000,12 +2507,135 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" +dependencies = [ + "der", +] + +[[package]] +name = "sqlformat" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc15591eb44ffb5816a4a70a7efd5dd87bfd3aa84c4c200401c4396140525826" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "195183bf6ff8328bb82c0511a83faf60aacf75840103388851db61d7a9854ae3" +dependencies = [ + "ahash", + "atoi", + "bitflags 1.3.2", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "digest 0.9.0", + "either", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-util", + "generic-array", + "hashlink", + "hex", + "indexmap", + "itoa 1.0.1", + "libc", + "log", + "memchr", + "num-bigint", + "once_cell", + "paste", + "percent-encoding", + "rand", + "rsa", + "rustls 0.19.1", + "sha-1 0.9.8", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki 0.21.4", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee35713129561f5e55c554bba1c378e2a7e67f81257b7311183de98c50e6f94" +dependencies = [ + "dotenv", + "either", + "heck", + "once_cell", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls", +] + [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.90" @@ -2017,6 +2647,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "sync_wrapper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + [[package]] name = "synstructure" version = "0.12.6" @@ -2111,6 +2747,72 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot 0.12.0", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.4.4", + "tokio-macros", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki 0.21.4", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.8" @@ -2120,6 +2822,54 @@ dependencies = [ "serde", ] +[[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +dependencies = [ + "bitflags 1.3.2", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + [[package]] name = "tracing" version = "0.1.32" @@ -2127,6 +2877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2152,6 +2903,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "tungstenite" version = "0.17.2" @@ -2165,7 +2922,7 @@ dependencies = [ "httparse", "log", "rand", - "sha-1", + "sha-1 0.10.0", "thiserror", "url", "utf-8", @@ -2192,6 +2949,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + [[package]] name = "unicode-width" version = "0.1.9" @@ -2204,6 +2967,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "untrusted" version = "0.7.1" @@ -2269,6 +3038,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -2345,6 +3124,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "webpki" version = "0.22.0" @@ -2355,6 +3144,15 @@ dependencies = [ "untrusted", ] +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4", +] + [[package]] name = "winapi" version = "0.2.8" @@ -2397,3 +3195,67 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "zeroize" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/Cargo.toml b/Cargo.toml index 92ec3a4..76433b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "aquatic_common", "aquatic_http", "aquatic_http_load_test", + "aquatic_http_private", "aquatic_http_protocol", "aquatic_toml_config", "aquatic_toml_config_derive", @@ -24,6 +25,7 @@ aquatic_cli_helpers = { path = "aquatic_cli_helpers" } aquatic_common = { path = "aquatic_common" } aquatic_http_load_test = { path = "aquatic_http_load_test" } aquatic_http = { path = "aquatic_http" } +aquatic_http_private = { path = "aquatic_http_private" } aquatic_http_protocol = { path = "aquatic_http_protocol" } aquatic_toml_config_derive = { path = "aquatic_toml_config_derive" } aquatic_toml_config = { path = "aquatic_toml_config" } @@ -45,4 +47,4 @@ opt-level = 3 [profile.bench] debug = true opt-level = 3 -lto = true \ No newline at end of file +lto = true diff --git a/aquatic_http_private/.gitignore b/aquatic_http_private/.gitignore new file mode 100644 index 0000000..fedaa2b --- /dev/null +++ b/aquatic_http_private/.gitignore @@ -0,0 +1,2 @@ +/target +.env diff --git a/aquatic_http_private/Cargo.lock b/aquatic_http_private/Cargo.lock new file mode 100644 index 0000000..919c414 --- /dev/null +++ b/aquatic_http_private/Cargo.lock @@ -0,0 +1,1664 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" + +[[package]] +name = "aquatic-private" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "dotenv", + "socket2", + "sqlx", + "tokio", +] + +[[package]] +name = "async-trait" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atoi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5611d4977882c5af1c0f7a34d51b5d87f784f86912bb543986b014ea4995ef93" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cd109b3e93c9541dcce5b0219dcf89169dcc58c1bebed65082808324258afb" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "base64ct" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b4d9b1225d28d360ec6a231d65af1fd99a2a095154c8040689617290569c5c" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" + +[[package]] +name = "cpufeatures" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" + +[[package]] +name = "crossbeam-queue" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "crypto-bigint" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" +dependencies = [ + "generic-array", + "rand_core", + "subtle", +] + +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" +dependencies = [ + "const-oid", + "crypto-bigint", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +] + +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-intrusive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashlink" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "headers" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +dependencies = [ + "base64", + "bitflags", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha-1 0.10.0", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg 1.1.0", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "js-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.121" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" + +[[package]] +name = "libm" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" + +[[package]] +name = "lock_api" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +dependencies = [ + "autocfg 1.1.0", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + +[[package]] +name = "matchit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "mio" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4547ee5541c18742396ae2c895d0717d0f886d8823b8399cdaf7b07d63ad0480" +dependencies = [ + "autocfg 0.1.8", + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg 1.1.0", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg 1.1.0", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.2", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "paste" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" + +[[package]] +name = "pem-rfc7468" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e93a3b1cc0510b03020f33f21e62acdde3dcaef432edc95bea377fbd4c2cd4" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "116bee8279d783c0cf370efa1a94632f2108e5ef0bb32df31f051647810a4e2c" +dependencies = [ + "der", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" +dependencies = [ + "der", + "pem-rfc7468", + "pkcs1", + "spki", + "zeroize", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rsa" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c2603e2823634ab331437001b411b9ed11660fbc4066f3908c84a9439260d" +dependencies = [ + "byteorder", + "digest 0.9.0", + "lazy_static", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64", + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" +dependencies = [ + "der", +] + +[[package]] +name = "sqlformat" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc15591eb44ffb5816a4a70a7efd5dd87bfd3aa84c4c200401c4396140525826" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "195183bf6ff8328bb82c0511a83faf60aacf75840103388851db61d7a9854ae3" +dependencies = [ + "ahash", + "atoi", + "bitflags", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "digest 0.9.0", + "either", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-util", + "generic-array", + "hashlink", + "hex", + "indexmap", + "itoa", + "libc", + "log", + "memchr", + "num-bigint", + "once_cell", + "paste", + "percent-encoding", + "rand", + "rsa", + "rustls", + "sha-1 0.9.8", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki", + "webpki-roots", +] + +[[package]] +name = "sqlx-macros" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee35713129561f5e55c554bba1c378e2a7e67f81257b7311183de98c50e6f94" +dependencies = [ + "dotenv", + "either", + "heck", + "once_cell", + "proc-macro2", + "quote", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "stringprep" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot 0.12.0", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" + +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" +dependencies = [ + "cfg-if", + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" + +[[package]] +name = "web-sys" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "zeroize" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml new file mode 100644 index 0000000..2a99b58 --- /dev/null +++ b/aquatic_http_private/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "aquatic_http_private" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1" +axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] } +dotenv = "0.15" +socket2 = { version = "0.4", features = ["all"] } +sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" , "mysql" ] } +tokio = { version = "1", features = ["full"] } + diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md new file mode 100644 index 0000000..31419b6 --- /dev/null +++ b/aquatic_http_private/README.md @@ -0,0 +1,41 @@ +# aquatic_private + +## Setup + +Create user: + +```sql +CREATE DATABASE aquatic; +CREATE USER 'aquatic'@localhost IDENTIFIED BY 'aquatic'; +GRANT EXECUTE ON PROCEDURE aquatic.aquatic_announce_v1 TO 'aquatic'@localhost; +FLUSH PRIVILEGES; +``` + +Create stored procedure (`OR REPLACE` keeps privileges in place and is supported by MariaDB since 10.1.3): + +```sql +CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( + IN p_source_ip VARBINARY(16), + IN p_source_port SMALLINT, + IN p_user_agent TEXT, + IN p_user_token VARCHAR(255), + IN p_info_hash CHAR(40), + IN p_peer_id CHAR(40), + IN p_event VARCHAR(9), + IN p_uploaded BIGINT, + IN p_downloaded BIGINT, + OUT p_announce_allowed BOOLEAN, + OUT p_failure_reason TEXT, + OUT p_warning_message TEXT +) +MODIFIES SQL DATA +BEGIN + SELECT true INTO p_announce_allowed; +END +``` + +Create `.env` file: + +```sh +DATABASE_URL="mysql://aquatic:aquatic@localhost/aquatic" +``` diff --git a/aquatic_http_private/src/main.rs b/aquatic_http_private/src/main.rs new file mode 100644 index 0000000..0768d00 --- /dev/null +++ b/aquatic_http_private/src/main.rs @@ -0,0 +1,24 @@ +mod workers; +use dotenv::dotenv; + +fn main() -> anyhow::Result<()> { + dotenv().ok(); + + let mut handles = Vec::new(); + + for _ in 0..2 { + let handle = ::std::thread::Builder::new() + .name("socket".into()) + .spawn(move || workers::socket::run_socket_worker())?; + + handles.push(handle); + } + + for handle in handles { + handle + .join() + .map_err(|err| anyhow::anyhow!("thread join error: {:?}", err))??; + } + + Ok(()) +} diff --git a/aquatic_http_private/src/workers/mod.rs b/aquatic_http_private/src/workers/mod.rs new file mode 100644 index 0000000..d22cc84 --- /dev/null +++ b/aquatic_http_private/src/workers/mod.rs @@ -0,0 +1 @@ +pub mod socket; diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs new file mode 100644 index 0000000..c6f6f8d --- /dev/null +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -0,0 +1,102 @@ +use std::net::{IpAddr, Ipv4Addr}; + +use sqlx::{Executor, MySql, Pool}; + +pub struct DbAnnounceRequest { + source_ip: IpAddr, + source_port: u16, + user_agent: Option, + user_token: String, + info_hash: String, + peer_id: String, + event: String, + uploaded: u64, + downloaded: u64, +} + +#[derive(Debug, sqlx::FromRow)] +pub struct DbAnnounceResponse { + pub announce_allowed: bool, + pub failure_reason: Option, + pub warning_message: Option, +} + +pub async fn announce(pool: &Pool) -> Result { + let request = DbAnnounceRequest { + source_ip: IpAddr::V4(Ipv4Addr::LOCALHOST), + source_port: 1000, + user_agent: Some("rtorrent".into()), + user_token: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into(), + info_hash: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into(), + peer_id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into(), + event: "started".into(), + uploaded: 50, + downloaded: 100, + }; + + let announce_response = get_announce_response(&pool, request).await?; + + Ok(announce_response) +} + +async fn get_announce_response( + pool: &Pool, + request: DbAnnounceRequest, +) -> Result { + let source_ip_bytes: Vec = match request.source_ip { + IpAddr::V4(ip) => ip.octets().into(), + IpAddr::V6(ip) => ip.octets().into(), + }; + + let mut t = pool.begin().await?; + + t.execute("SET @p_announce_allowed = false;").await?; + t.execute("SET @p_failure_reason = NULL;").await?; + t.execute("SET @p_warning_message = NULL;").await?; + + let q = sqlx::query( + " + CALL aquatic_announce_v1( + ?, + ?, + ?, + ?, + ?, + ?, + ?, + ?, + ?, + @p_announce_allowed, + @p_failure_reason, + @p_warning_message + ); + ", + ) + .bind(source_ip_bytes) + .bind(request.source_port) + .bind(request.user_agent) + .bind(request.user_token) + .bind(request.info_hash) + .bind(request.peer_id) + .bind(request.event) + .bind(request.uploaded) + .bind(request.downloaded); + + t.execute(q).await?; + + let response = sqlx::query_as::<_, DbAnnounceResponse>( + " + SELECT + @p_announce_allowed as announce_allowed, + @p_failure_reason as failure_reason, + @p_warning_message as warning_message; + + ", + ) + .fetch_one(&mut t) + .await; + + t.commit().await?; + + response +} diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs new file mode 100644 index 0000000..ccc28ed --- /dev/null +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -0,0 +1,67 @@ +mod db; +mod routes; + +use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener}; + +use anyhow::Context; +use axum::{routing::get, Extension, Router}; +use sqlx::mysql::MySqlPoolOptions; + +pub fn run_socket_worker() -> anyhow::Result<()> { + let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 3000)); + + let tcp_listener = create_tcp_listener(addr, false)?; + + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()?; + + runtime.block_on(run_app(tcp_listener))?; + + Ok(()) +} + +async fn run_app(tcp_listener: TcpListener) -> anyhow::Result<()> { + let db_url = ::std::env::var("DATABASE_URL").unwrap(); + + let pool = MySqlPoolOptions::new() + .max_connections(5) + .connect(&db_url) + .await?; + + let app = Router::new() + .route("/:user_token/announce/", get(routes::announce)) + .layer(Extension(pool)); + + axum::Server::from_tcp(tcp_listener)? + .serve(app.into_make_service()) + .await?; + + Ok(()) +} + +fn create_tcp_listener(addr: SocketAddr, only_ipv6: bool) -> anyhow::Result { + let domain = if addr.is_ipv4() { + socket2::Domain::IPV4 + } else { + socket2::Domain::IPV6 + }; + + let socket = socket2::Socket::new(domain, socket2::Type::STREAM, Some(socket2::Protocol::TCP))?; + + if only_ipv6 { + socket.set_only_v6(true).with_context(|| "set only_ipv6")?; + } + + socket + .set_reuse_port(true) + .with_context(|| "set_reuse_port")?; + socket + .bind(&addr.into()) + .with_context(|| format!("bind to {}", addr))?; + socket + .listen(1024) + .with_context(|| format!("listen on {}", addr))?; + + Ok(socket.into()) +} diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs new file mode 100644 index 0000000..24b1d43 --- /dev/null +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -0,0 +1,21 @@ +use axum::{ + extract::{Path, RawQuery}, + headers::UserAgent, + http::StatusCode, + Extension, TypedHeader, +}; +use sqlx::mysql::MySqlPool; + +use super::db; + +pub async fn announce( + Extension(pool): Extension, + opt_user_agent: Option>, + Path(user_token): Path, + RawQuery(query): RawQuery, +) -> Result { + match db::announce(&pool).await { + Ok(r) => Ok(format!("{:?}", r)), + Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())), + } +} From b9c029b5edb3eec85c07c6393f02e35c24ab99ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 12:39:31 +0200 Subject: [PATCH 02/62] http_protocol: split request parsing by request type --- aquatic_http_protocol/src/request.rs | 233 ++++++++++++++++----------- 1 file changed, 137 insertions(+), 96 deletions(-) diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 3197fa7..133d1c6 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -57,6 +57,94 @@ impl AnnounceRequest { Ok(()) } + + pub fn from_query_string(query_string: &str) -> anyhow::Result { + // -- Parse key-value pairs + + let mut opt_info_hash= None; + let mut opt_peer_id = None; + let mut opt_port = None; + let mut opt_bytes_left = None; + let mut event = AnnounceEvent::default(); + let mut opt_numwant = None; + let mut opt_key = None; + + let query_string_bytes = query_string.as_bytes(); + + let mut ampersand_iter = ::memchr::memchr_iter(b'&', query_string_bytes); + let mut position = 0usize; + + for equal_sign_index in ::memchr::memchr_iter(b'=', query_string_bytes) { + let segment_end = ampersand_iter.next().unwrap_or_else(|| query_string.len()); + + let key = query_string + .get(position..equal_sign_index) + .with_context(|| format!("no key at {}..{}", position, equal_sign_index))?; + let value = query_string + .get(equal_sign_index + 1..segment_end) + .with_context(|| { + format!("no value at {}..{}", equal_sign_index + 1, segment_end) + })?; + + match key { + "info_hash" => { + let value = urldecode_20_bytes(value)?; + + opt_info_hash = Some(InfoHash(value)); + } + "peer_id" => { + let value = urldecode_20_bytes(value)?; + + opt_peer_id = Some(PeerId(value)); + } + "port" => { + opt_port = Some(value.parse::().with_context(|| "parse port")?); + } + "left" => { + opt_bytes_left = Some(value.parse::().with_context(|| "parse left")?); + } + "event" => { + event = value + .parse::() + .map_err(|err| anyhow::anyhow!("invalid event: {}", err))?; + } + "compact" => { + if value != "1" { + return Err(anyhow::anyhow!("compact set, but not to 1")); + } + } + "numwant" => { + opt_numwant = Some(value.parse::().with_context(|| "parse numwant")?); + } + "key" => { + if value.len() > 100 { + return Err(anyhow::anyhow!("'key' is too long")); + } + opt_key = Some(::urlencoding::decode(value)?.into()); + } + k => { + ::log::debug!("ignored unrecognized key: {}", k) + } + } + + if segment_end == query_string.len() { + break; + } else { + position = segment_end + 1; + } + } + + Ok(AnnounceRequest { + info_hash: opt_info_hash.with_context(|| "no info_hash")?, + peer_id: opt_peer_id.with_context(|| "no peer_id")?, + port: opt_port.with_context(|| "no port")?, + bytes_left: opt_bytes_left.with_context(|| "no left")?, + event, + compact: true, + numwant: opt_numwant, + key: opt_key, + }) + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -85,6 +173,53 @@ impl ScrapeRequest { Ok(()) } + + pub fn from_query_string(query_string: &str) -> anyhow::Result { + // -- Parse key-value pairs + + let mut info_hashes = Vec::new(); + + let query_string_bytes = query_string.as_bytes(); + + let mut ampersand_iter = ::memchr::memchr_iter(b'&', query_string_bytes); + let mut position = 0usize; + + for equal_sign_index in ::memchr::memchr_iter(b'=', query_string_bytes) { + let segment_end = ampersand_iter.next().unwrap_or_else(|| query_string.len()); + + let key = query_string + .get(position..equal_sign_index) + .with_context(|| format!("no key at {}..{}", position, equal_sign_index))?; + let value = query_string + .get(equal_sign_index + 1..segment_end) + .with_context(|| { + format!("no value at {}..{}", equal_sign_index + 1, segment_end) + })?; + + match key { + "info_hash" => { + let value = urldecode_20_bytes(value)?; + + info_hashes.push(InfoHash(value)); + } + k => { + ::log::debug!("ignored unrecognized key: {}", k) + } + } + + if segment_end == query_string.len() { + break; + } else { + position = segment_end + 1; + } + } + + if info_hashes.is_empty() { + return Err(anyhow::anyhow!("No info hashes sent")); + } + + Ok(ScrapeRequest { info_hashes }) + } } #[derive(Debug)] @@ -147,104 +282,10 @@ impl Request { let location = split_parts.next().with_context(|| "no location")?; let query_string = split_parts.next().with_context(|| "no query string")?; - // -- Parse key-value pairs - - let mut info_hashes = Vec::new(); - let mut opt_peer_id = None; - let mut opt_port = None; - let mut opt_bytes_left = None; - let mut event = AnnounceEvent::default(); - let mut opt_numwant = None; - let mut opt_key = None; - - let query_string_bytes = query_string.as_bytes(); - - let mut ampersand_iter = ::memchr::memchr_iter(b'&', query_string_bytes); - let mut position = 0usize; - - for equal_sign_index in ::memchr::memchr_iter(b'=', query_string_bytes) { - let segment_end = ampersand_iter.next().unwrap_or_else(|| query_string.len()); - - let key = query_string - .get(position..equal_sign_index) - .with_context(|| format!("no key at {}..{}", position, equal_sign_index))?; - let value = query_string - .get(equal_sign_index + 1..segment_end) - .with_context(|| { - format!("no value at {}..{}", equal_sign_index + 1, segment_end) - })?; - - match key { - "info_hash" => { - let value = urldecode_20_bytes(value)?; - - info_hashes.push(InfoHash(value)); - } - "peer_id" => { - let value = urldecode_20_bytes(value)?; - - opt_peer_id = Some(PeerId(value)); - } - "port" => { - opt_port = Some(value.parse::().with_context(|| "parse port")?); - } - "left" => { - opt_bytes_left = Some(value.parse::().with_context(|| "parse left")?); - } - "event" => { - event = value - .parse::() - .map_err(|err| anyhow::anyhow!("invalid event: {}", err))?; - } - "compact" => { - if value != "1" { - return Err(anyhow::anyhow!("compact set, but not to 1")); - } - } - "numwant" => { - opt_numwant = Some(value.parse::().with_context(|| "parse numwant")?); - } - "key" => { - if value.len() > 100 { - return Err(anyhow::anyhow!("'key' is too long")); - } - opt_key = Some(::urlencoding::decode(value)?.into()); - } - k => { - ::log::debug!("ignored unrecognized key: {}", k) - } - } - - if segment_end == query_string.len() { - break; - } else { - position = segment_end + 1; - } - } - - // -- Put together request - if location == "/announce" { - let request = AnnounceRequest { - info_hash: info_hashes.pop().with_context(|| "no info_hash")?, - peer_id: opt_peer_id.with_context(|| "no peer_id")?, - port: opt_port.with_context(|| "no port")?, - bytes_left: opt_bytes_left.with_context(|| "no left")?, - event, - compact: true, - numwant: opt_numwant, - key: opt_key, - }; - - Ok(Request::Announce(request)) + Ok(Request::Announce(AnnounceRequest::from_query_string(query_string)?)) } else { - if info_hashes.is_empty() { - return Err(anyhow::anyhow!("No info hashes sent")); - } - - let request = ScrapeRequest { info_hashes }; - - Ok(Request::Scrape(request)) + Ok(Request::Scrape(ScrapeRequest::from_query_string(query_string)?)) } } From 87223f7952a031ee409c415ff7f69c18878f89a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 13:31:51 +0200 Subject: [PATCH 03/62] http_protocol: add AnnounceEvent::as_str, run cargo fmt --- aquatic_http_protocol/src/common.rs | 11 +++++++++++ aquatic_http_protocol/src/request.rs | 10 +++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/aquatic_http_protocol/src/common.rs b/aquatic_http_protocol/src/common.rs index bf77550..91b6a5f 100644 --- a/aquatic_http_protocol/src/common.rs +++ b/aquatic_http_protocol/src/common.rs @@ -52,6 +52,17 @@ impl FromStr for AnnounceEvent { } } +impl AnnounceEvent { + pub fn as_str(&self) -> Option<&str> { + match self { + Self::Started => Some("started"), + Self::Stopped => Some("stopped"), + Self::Completed => Some("completed"), + Self::Empty => None, + } + } +} + #[cfg(test)] impl quickcheck::Arbitrary for InfoHash { fn arbitrary(g: &mut quickcheck::Gen) -> Self { diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 133d1c6..d61a242 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -61,7 +61,7 @@ impl AnnounceRequest { pub fn from_query_string(query_string: &str) -> anyhow::Result { // -- Parse key-value pairs - let mut opt_info_hash= None; + let mut opt_info_hash = None; let mut opt_peer_id = None; let mut opt_port = None; let mut opt_bytes_left = None; @@ -283,9 +283,13 @@ impl Request { let query_string = split_parts.next().with_context(|| "no query string")?; if location == "/announce" { - Ok(Request::Announce(AnnounceRequest::from_query_string(query_string)?)) + Ok(Request::Announce(AnnounceRequest::from_query_string( + query_string, + )?)) } else { - Ok(Request::Scrape(ScrapeRequest::from_query_string(query_string)?)) + Ok(Request::Scrape(ScrapeRequest::from_query_string( + query_string, + )?)) } } From dc943674f6d72971324c56a1915ee2c005e1fa17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 13:32:36 +0200 Subject: [PATCH 04/62] work on http_private, including parsing announce requests --- .gitignore | 1 + Cargo.lock | 2 + aquatic_http_private/Cargo.toml | 3 + aquatic_http_private/README.md | 10 +++- aquatic_http_private/src/workers/socket/db.rs | 55 ++++++++++--------- .../src/workers/socket/mod.rs | 4 +- .../src/workers/socket/routes.rs | 27 +++++++-- 7 files changed, 69 insertions(+), 33 deletions(-) diff --git a/.gitignore b/.gitignore index 3de5924..0446378 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ **/criterion/*/new .DS_Store +.env \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 3151194..63ee8fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,8 +144,10 @@ name = "aquatic_http_private" version = "0.1.0" dependencies = [ "anyhow", + "aquatic_http_protocol", "axum", "dotenv", + "hex", "socket2 0.4.4", "sqlx", "tokio", diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index 2a99b58..eeab0a5 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -4,9 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] +aquatic_http_protocol = "0.2.0" + anyhow = "1" axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] } dotenv = "0.15" +hex = "0.4" socket2 = { version = "0.4", features = ["all"] } sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" , "mysql" ] } tokio = { version = "1", features = ["full"] } diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index 31419b6..57652d0 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -16,7 +16,7 @@ Create stored procedure (`OR REPLACE` keeps privileges in place and is supported ```sql CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( IN p_source_ip VARBINARY(16), - IN p_source_port SMALLINT, + IN p_source_port SMALLINT UNSIGNED, IN p_user_agent TEXT, IN p_user_token VARCHAR(255), IN p_info_hash CHAR(40), @@ -39,3 +39,11 @@ Create `.env` file: ```sh DATABASE_URL="mysql://aquatic:aquatic@localhost/aquatic" ``` + +Run application: + +```sh +cargo run -p aquatic_http_private +``` + +Test by visiting `localhost:3000/abcd/announce/?info_hash=abcdeabcdeabcdeabcde&peer_id=abcdeabcdeabcdeabcde&port=1000&left=0` \ No newline at end of file diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index c6f6f8d..c5c72e4 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -1,7 +1,9 @@ -use std::net::{IpAddr, Ipv4Addr}; +use std::net::{IpAddr, SocketAddr}; +use aquatic_http_protocol::{common::AnnounceEvent, request::AnnounceRequest}; use sqlx::{Executor, MySql, Pool}; +#[derive(Debug)] pub struct DbAnnounceRequest { source_ip: IpAddr, source_port: u16, @@ -9,11 +11,32 @@ pub struct DbAnnounceRequest { user_token: String, info_hash: String, peer_id: String, - event: String, + event: AnnounceEvent, uploaded: u64, downloaded: u64, } +impl DbAnnounceRequest { + pub fn new( + source_addr: SocketAddr, + user_agent: Option, + user_token: String, // FIXME: length + request: AnnounceRequest, + ) -> Self { + Self { + source_ip: source_addr.ip(), + source_port: source_addr.port(), + user_agent, + user_token, + info_hash: hex::encode(request.info_hash.0), + peer_id: hex::encode(request.peer_id.0), + event: request.event, + uploaded: 0, // FIXME + downloaded: 0, // FIXME + } + } +} + #[derive(Debug, sqlx::FromRow)] pub struct DbAnnounceResponse { pub announce_allowed: bool, @@ -21,28 +44,10 @@ pub struct DbAnnounceResponse { pub warning_message: Option, } -pub async fn announce(pool: &Pool) -> Result { - let request = DbAnnounceRequest { - source_ip: IpAddr::V4(Ipv4Addr::LOCALHOST), - source_port: 1000, - user_agent: Some("rtorrent".into()), - user_token: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into(), - info_hash: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into(), - peer_id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into(), - event: "started".into(), - uploaded: 50, - downloaded: 100, - }; - - let announce_response = get_announce_response(&pool, request).await?; - - Ok(announce_response) -} - -async fn get_announce_response( +pub async fn get_announce_response( pool: &Pool, request: DbAnnounceRequest, -) -> Result { +) -> anyhow::Result { let source_ip_bytes: Vec = match request.source_ip { IpAddr::V4(ip) => ip.octets().into(), IpAddr::V6(ip) => ip.octets().into(), @@ -78,7 +83,7 @@ async fn get_announce_response( .bind(request.user_token) .bind(request.info_hash) .bind(request.peer_id) - .bind(request.event) + .bind(request.event.as_str()) .bind(request.uploaded) .bind(request.downloaded); @@ -94,9 +99,9 @@ async fn get_announce_response( ", ) .fetch_one(&mut t) - .await; + .await?; t.commit().await?; - response + Ok(response) } diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index ccc28ed..696d5b9 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -22,7 +22,7 @@ pub fn run_socket_worker() -> anyhow::Result<()> { } async fn run_app(tcp_listener: TcpListener) -> anyhow::Result<()> { - let db_url = ::std::env::var("DATABASE_URL").unwrap(); + let db_url = ::std::env::var("DATABASE_URL").expect("env var DATABASE_URL"); let pool = MySqlPoolOptions::new() .max_connections(5) @@ -34,7 +34,7 @@ async fn run_app(tcp_listener: TcpListener) -> anyhow::Result<()> { .layer(Extension(pool)); axum::Server::from_tcp(tcp_listener)? - .serve(app.into_make_service()) + .serve(app.into_make_service_with_connect_info::()) .await?; Ok(()) diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index 24b1d43..7652eaf 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -1,21 +1,38 @@ use axum::{ - extract::{Path, RawQuery}, + extract::{ConnectInfo, Path, RawQuery}, headers::UserAgent, http::StatusCode, Extension, TypedHeader, }; use sqlx::mysql::MySqlPool; +use std::net::SocketAddr; + +use aquatic_http_protocol::request::AnnounceRequest; use super::db; pub async fn announce( Extension(pool): Extension, + ConnectInfo(peer_addr): ConnectInfo, opt_user_agent: Option>, Path(user_token): Path, RawQuery(query): RawQuery, ) -> Result { - match db::announce(&pool).await { - Ok(r) => Ok(format!("{:?}", r)), - Err(err) => Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())), - } + let request = AnnounceRequest::from_query_string(&query.unwrap_or_else(|| "".into())) + .map_err(anyhow_error)?; + + let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned()); + + let db_announce_request = + db::DbAnnounceRequest::new(peer_addr, opt_user_agent, user_token, request); + + let db_announce_result = db::get_announce_response(&pool, db_announce_request) + .await + .map_err(anyhow_error)?; + + Ok(format!("{:?}", db_announce_result)) +} + +fn anyhow_error(err: anyhow::Error) -> (StatusCode, String) { + (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) } From a93789128ca5b78c5dff780607e6d71c3ded0a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 13:43:18 +0200 Subject: [PATCH 05/62] http_protocol: add AnnounceRequest uploaded and downloaded fields --- aquatic_http_protocol/src/request.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index d61a242..8dc5b6d 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -11,6 +11,8 @@ pub struct AnnounceRequest { pub info_hash: InfoHash, pub peer_id: PeerId, pub port: u16, + pub bytes_uploaded: usize, + pub bytes_downloaded: usize, pub bytes_left: usize, pub event: AnnounceEvent, pub compact: bool, @@ -65,6 +67,8 @@ impl AnnounceRequest { let mut opt_peer_id = None; let mut opt_port = None; let mut opt_bytes_left = None; + let mut opt_bytes_uploaded = None; + let mut opt_bytes_downloaded = None; let mut event = AnnounceEvent::default(); let mut opt_numwant = None; let mut opt_key = None; @@ -103,6 +107,12 @@ impl AnnounceRequest { "left" => { opt_bytes_left = Some(value.parse::().with_context(|| "parse left")?); } + "uploaded" => { + opt_bytes_uploaded = Some(value.parse::().with_context(|| "parse uploaded")?); + } + "downloaded" => { + opt_bytes_downloaded = Some(value.parse::().with_context(|| "parse downloaded")?); + } "event" => { event = value .parse::() @@ -138,6 +148,8 @@ impl AnnounceRequest { info_hash: opt_info_hash.with_context(|| "no info_hash")?, peer_id: opt_peer_id.with_context(|| "no peer_id")?, port: opt_port.with_context(|| "no port")?, + bytes_uploaded: opt_bytes_uploaded.with_context(|| "no uploaded")?, + bytes_downloaded: opt_bytes_downloaded.with_context(|| "no downloaded")?, bytes_left: opt_bytes_left.with_context(|| "no left")?, event, compact: true, @@ -324,7 +336,9 @@ mod tests { info_hash: InfoHash(REFERENCE_INFO_HASH), peer_id: PeerId(REFERENCE_PEER_ID), port: 12345, - bytes_left: 1, + bytes_uploaded: 1, + bytes_downloaded: 2, + bytes_left: 3, event: AnnounceEvent::Started, compact: true, numwant: Some(0), @@ -370,6 +384,8 @@ mod tests { info_hash: Arbitrary::arbitrary(g), peer_id: Arbitrary::arbitrary(g), port: Arbitrary::arbitrary(g), + bytes_uploaded: Arbitrary::arbitrary(g), + bytes_downloaded: Arbitrary::arbitrary(g), bytes_left: Arbitrary::arbitrary(g), event: Arbitrary::arbitrary(g), compact: true, From 82cad25fa8a20d7f18a8baf693816e95cf6dfc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 13:44:49 +0200 Subject: [PATCH 06/62] http_private: set announce request uploaded & downloaded --- aquatic_http_private/src/workers/socket/db.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index c5c72e4..c507789 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -31,8 +31,8 @@ impl DbAnnounceRequest { info_hash: hex::encode(request.info_hash.0), peer_id: hex::encode(request.peer_id.0), event: request.event, - uploaded: 0, // FIXME - downloaded: 0, // FIXME + uploaded: request.bytes_uploaded as u64, + downloaded: request.bytes_downloaded as u64, } } } From 4091f51bd8f72551906c80f5c7b18d3fa48fecdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 13:55:10 +0200 Subject: [PATCH 07/62] http_private: add p_left, make BIGINTs UNSIGNED --- aquatic_http_private/README.md | 5 +++-- aquatic_http_private/src/workers/socket/db.rs | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index 57652d0..22aa65c 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -22,8 +22,9 @@ CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( IN p_info_hash CHAR(40), IN p_peer_id CHAR(40), IN p_event VARCHAR(9), - IN p_uploaded BIGINT, - IN p_downloaded BIGINT, + IN p_uploaded BIGINT UNSIGNED, + IN p_downloaded BIGINT UNSIGNED, + IN p_left BIGINT UNSIGNED, OUT p_announce_allowed BOOLEAN, OUT p_failure_reason TEXT, OUT p_warning_message TEXT diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index c507789..74039cb 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -14,6 +14,7 @@ pub struct DbAnnounceRequest { event: AnnounceEvent, uploaded: u64, downloaded: u64, + left: u64, } impl DbAnnounceRequest { @@ -33,6 +34,7 @@ impl DbAnnounceRequest { event: request.event, uploaded: request.bytes_uploaded as u64, downloaded: request.bytes_downloaded as u64, + left: request.bytes_left as u64, } } } @@ -71,6 +73,7 @@ pub async fn get_announce_response( ?, ?, ?, + ?, @p_announce_allowed, @p_failure_reason, @p_warning_message @@ -85,7 +88,8 @@ pub async fn get_announce_response( .bind(request.peer_id) .bind(request.event.as_str()) .bind(request.uploaded) - .bind(request.downloaded); + .bind(request.downloaded) + .bind(request.left); t.execute(q).await?; From b54fb7f1db52ed5c301c25ba22adf89120a7a5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 13:56:13 +0200 Subject: [PATCH 08/62] http_protocol: cargo fmt --- aquatic_http_protocol/src/request.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 8dc5b6d..7f29cf7 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -108,10 +108,12 @@ impl AnnounceRequest { opt_bytes_left = Some(value.parse::().with_context(|| "parse left")?); } "uploaded" => { - opt_bytes_uploaded = Some(value.parse::().with_context(|| "parse uploaded")?); + opt_bytes_uploaded = + Some(value.parse::().with_context(|| "parse uploaded")?); } "downloaded" => { - opt_bytes_downloaded = Some(value.parse::().with_context(|| "parse downloaded")?); + opt_bytes_downloaded = + Some(value.parse::().with_context(|| "parse downloaded")?); } "event" => { event = value From 6e97bff93fe272c75566c6fb2926606c4da1ed01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 14:21:44 +0200 Subject: [PATCH 09/62] Update TODO --- TODO.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/TODO.md b/TODO.md index 24186ca..644d3dd 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,15 @@ ## High priority +* aquatic_http_private + * test passing data between runtimes + * stored procedure + * should source ip be canonical? + * handle/document lack of NOT NULL + * event can be null + * test ip format + * site will likely want num_seeders and num_leechers for all torrents.. + ## Medium priority * Use thin LTO? From 088daa72ff1a8af7f3d1f2bb30c8db052d384a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 14:35:40 +0200 Subject: [PATCH 10/62] http_private: add config, launch with cli helpers --- Cargo.lock | 5 + aquatic_http_private/Cargo.toml | 11 ++ aquatic_http_private/src/config.rs | 121 ++++++++++++++++++ aquatic_http_private/src/lib.rs | 41 ++++++ aquatic_http_private/src/main.rs | 32 ++--- aquatic_http_private/src/workers/mod.rs | 1 + aquatic_http_private/src/workers/request.rs | 5 + .../src/workers/socket/mod.rs | 14 +- 8 files changed, 200 insertions(+), 30 deletions(-) create mode 100644 aquatic_http_private/src/config.rs create mode 100644 aquatic_http_private/src/lib.rs create mode 100644 aquatic_http_private/src/workers/request.rs diff --git a/Cargo.lock b/Cargo.lock index 63ee8fd..3326978 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,10 +144,15 @@ name = "aquatic_http_private" version = "0.1.0" dependencies = [ "anyhow", + "aquatic_cli_helpers", + "aquatic_common", "aquatic_http_protocol", + "aquatic_toml_config", "axum", "dotenv", "hex", + "mimalloc", + "serde", "socket2 0.4.4", "sqlx", "tokio", diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index eeab0a5..a2665fd 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -3,13 +3,24 @@ name = "aquatic_http_private" version = "0.1.0" edition = "2021" +[lib] +name = "aquatic_http_private" + +[[bin]] +name = "aquatic_http_private" + [dependencies] +aquatic_cli_helpers = "0.2.0" +aquatic_common = "0.2.0" aquatic_http_protocol = "0.2.0" +aquatic_toml_config = "0.2.0" anyhow = "1" axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] } dotenv = "0.15" hex = "0.4" +mimalloc = { version = "0.1", default-features = false } +serde = { version = "1", features = ["derive"] } socket2 = { version = "0.4", features = ["all"] } sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" , "mysql" ] } tokio = { version = "1", features = ["full"] } diff --git a/aquatic_http_private/src/config.rs b/aquatic_http_private/src/config.rs new file mode 100644 index 0000000..bad3d72 --- /dev/null +++ b/aquatic_http_private/src/config.rs @@ -0,0 +1,121 @@ +use std::{net::SocketAddr, path::PathBuf}; + +use aquatic_common::privileges::PrivilegeConfig; +use aquatic_toml_config::TomlConfig; +use serde::Deserialize; + +use aquatic_cli_helpers::LogLevel; + +/// aquatic_http_private configuration +#[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)] +#[serde(default)] +pub struct Config { + /// Socket workers receive requests from the socket, parse them and send + /// them on to the request workers. They then receive responses from the + /// request workers, encode them and send them back over the socket. + pub socket_workers: usize, + /// Request workers receive a number of requests from socket workers, + /// generate responses and send them back to the socket workers. + pub request_workers: usize, + pub log_level: LogLevel, + pub network: NetworkConfig, + pub protocol: ProtocolConfig, + pub cleaning: CleaningConfig, + pub privileges: PrivilegeConfig, +} + +impl Default for Config { + fn default() -> Self { + Self { + socket_workers: 1, + request_workers: 1, + log_level: LogLevel::default(), + network: NetworkConfig::default(), + protocol: ProtocolConfig::default(), + cleaning: CleaningConfig::default(), + privileges: PrivilegeConfig::default(), + } + } +} + +impl aquatic_cli_helpers::Config for Config { + fn get_log_level(&self) -> Option { + Some(self.log_level) + } +} + +#[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)] +#[serde(default)] +pub struct NetworkConfig { + /// Bind to this address + pub address: SocketAddr, + /// Path to TLS certificate (DER-encoded X.509) + pub tls_certificate_path: PathBuf, + /// Path to TLS private key (DER-encoded ASN.1 in PKCS#8 or PKCS#1 format) + pub tls_private_key_path: PathBuf, + /// Keep connections alive after sending a response + pub keep_alive: bool, +} + +impl Default for NetworkConfig { + fn default() -> Self { + Self { + address: SocketAddr::from(([0, 0, 0, 0], 3000)), + tls_certificate_path: "".into(), + tls_private_key_path: "".into(), + keep_alive: false, + } + } +} + +#[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)] +#[serde(default)] +pub struct ProtocolConfig { + /// Maximum number of torrents to accept in scrape request + pub max_scrape_torrents: usize, + /// Maximum number of requested peers to accept in announce request + pub max_peers: usize, + /// Ask peers to announce this often (seconds) + pub peer_announce_interval: usize, +} + +impl Default for ProtocolConfig { + fn default() -> Self { + Self { + max_scrape_torrents: 100, + max_peers: 50, + peer_announce_interval: 300, + } + } +} + +#[derive(Clone, Debug, PartialEq, TomlConfig, Deserialize)] +#[serde(default)] +pub struct CleaningConfig { + /// Clean peers this often (seconds) + pub torrent_cleaning_interval: u64, + /// Clean connections this often (seconds) + pub connection_cleaning_interval: u64, + /// Remove peers that have not announced for this long (seconds) + pub max_peer_age: u64, + /// Remove connections that haven't seen valid requests for this long (seconds) + pub max_connection_idle: u64, +} + +impl Default for CleaningConfig { + fn default() -> Self { + Self { + torrent_cleaning_interval: 30, + connection_cleaning_interval: 60, + max_peer_age: 360, + max_connection_idle: 180, + } + } +} + +#[cfg(test)] +mod tests { + use super::Config; + + ::aquatic_toml_config::gen_serialize_deserialize_test!(Config); +} diff --git a/aquatic_http_private/src/lib.rs b/aquatic_http_private/src/lib.rs new file mode 100644 index 0000000..f0ce764 --- /dev/null +++ b/aquatic_http_private/src/lib.rs @@ -0,0 +1,41 @@ +pub mod config; +mod workers; + +use dotenv::dotenv; + +pub const APP_NAME: &str = "aquatic_http_private: private HTTP/TLS BitTorrent tracker"; +pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub fn run(config: config::Config) -> anyhow::Result<()> { + dotenv().ok(); + + let mut handles = Vec::new(); + + for _ in 0..config.socket_workers { + let config = config.clone(); + + let handle = ::std::thread::Builder::new() + .name("socket".into()) + .spawn(move || workers::socket::run_socket_worker(config))?; + + handles.push(handle); + } + + for _ in 0..config.request_workers { + let config = config.clone(); + + let handle = ::std::thread::Builder::new() + .name("request".into()) + .spawn(move || workers::request::run_request_worker(config))?; + + handles.push(handle); + } + + for handle in handles { + handle + .join() + .map_err(|err| anyhow::anyhow!("thread join error: {:?}", err))??; + } + + Ok(()) +} diff --git a/aquatic_http_private/src/main.rs b/aquatic_http_private/src/main.rs index 0768d00..c26aaeb 100644 --- a/aquatic_http_private/src/main.rs +++ b/aquatic_http_private/src/main.rs @@ -1,24 +1,14 @@ -mod workers; -use dotenv::dotenv; +use aquatic_cli_helpers::run_app_with_cli_and_config; +use aquatic_http_private::config::Config; -fn main() -> anyhow::Result<()> { - dotenv().ok(); +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - let mut handles = Vec::new(); - - for _ in 0..2 { - let handle = ::std::thread::Builder::new() - .name("socket".into()) - .spawn(move || workers::socket::run_socket_worker())?; - - handles.push(handle); - } - - for handle in handles { - handle - .join() - .map_err(|err| anyhow::anyhow!("thread join error: {:?}", err))??; - } - - Ok(()) +fn main() { + run_app_with_cli_and_config::( + aquatic_http_private::APP_NAME, + aquatic_http_private::APP_VERSION, + aquatic_http_private::run, + None, + ) } diff --git a/aquatic_http_private/src/workers/mod.rs b/aquatic_http_private/src/workers/mod.rs index d22cc84..63fc0ec 100644 --- a/aquatic_http_private/src/workers/mod.rs +++ b/aquatic_http_private/src/workers/mod.rs @@ -1 +1,2 @@ +pub mod request; pub mod socket; diff --git a/aquatic_http_private/src/workers/request.rs b/aquatic_http_private/src/workers/request.rs new file mode 100644 index 0000000..068f293 --- /dev/null +++ b/aquatic_http_private/src/workers/request.rs @@ -0,0 +1,5 @@ +use crate::config::Config; + +pub fn run_request_worker(config: Config) -> anyhow::Result<()> { + Ok(()) +} diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 696d5b9..f986816 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -1,16 +1,16 @@ mod db; mod routes; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener}; +use std::net::{SocketAddr, TcpListener}; use anyhow::Context; use axum::{routing::get, Extension, Router}; use sqlx::mysql::MySqlPoolOptions; -pub fn run_socket_worker() -> anyhow::Result<()> { - let addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 3000)); +use crate::config::Config; - let tcp_listener = create_tcp_listener(addr, false)?; +pub fn run_socket_worker(config: Config) -> anyhow::Result<()> { + let tcp_listener = create_tcp_listener(config.network.address)?; let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() @@ -40,7 +40,7 @@ async fn run_app(tcp_listener: TcpListener) -> anyhow::Result<()> { Ok(()) } -fn create_tcp_listener(addr: SocketAddr, only_ipv6: bool) -> anyhow::Result { +fn create_tcp_listener(addr: SocketAddr) -> anyhow::Result { let domain = if addr.is_ipv4() { socket2::Domain::IPV4 } else { @@ -49,10 +49,6 @@ fn create_tcp_listener(addr: SocketAddr, only_ipv6: bool) -> anyhow::Result Date: Sat, 2 Apr 2022 15:43:28 +0200 Subject: [PATCH 11/62] http_protocol: derive Copy for AnnounceEvent --- aquatic_http_protocol/src/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aquatic_http_protocol/src/common.rs b/aquatic_http_protocol/src/common.rs index 91b6a5f..bfb48b5 100644 --- a/aquatic_http_protocol/src/common.rs +++ b/aquatic_http_protocol/src/common.rs @@ -24,7 +24,7 @@ pub struct InfoHash( pub [u8; 20], ); -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum AnnounceEvent { Started, Stopped, From 0fb572556fc6878fc47d6b6f9fd329cfb7fee69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 15:43:44 +0200 Subject: [PATCH 12/62] WIP: http_private: work on channel types --- Cargo.lock | 1 + aquatic_http_private/Cargo.toml | 1 + aquatic_http_private/src/workers/common.rs | 11 +++ aquatic_http_private/src/workers/mod.rs | 1 + aquatic_http_private/src/workers/socket/db.rs | 85 ++++++++++++++----- .../src/workers/socket/mod.rs | 2 +- .../src/workers/socket/routes.rs | 15 ++-- 7 files changed, 85 insertions(+), 31 deletions(-) create mode 100644 aquatic_http_private/src/workers/common.rs diff --git a/Cargo.lock b/Cargo.lock index 3326978..5df294d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,6 +151,7 @@ dependencies = [ "axum", "dotenv", "hex", + "log", "mimalloc", "serde", "socket2 0.4.4", diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index a2665fd..272fed8 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -19,6 +19,7 @@ anyhow = "1" axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] } dotenv = "0.15" hex = "0.4" +log = "0.4" mimalloc = { version = "0.1", default-features = false } serde = { version = "1", features = ["derive"] } socket2 = { version = "0.4", features = ["all"] } diff --git a/aquatic_http_private/src/workers/common.rs b/aquatic_http_private/src/workers/common.rs new file mode 100644 index 0000000..58db3cd --- /dev/null +++ b/aquatic_http_private/src/workers/common.rs @@ -0,0 +1,11 @@ +use aquatic_common::CanonicalSocketAddr; +use aquatic_http_protocol::response::AnnounceResponse; +use tokio::sync::oneshot::Sender; + +use super::socket::db::ValidatedAnnounceRequest; + +pub struct ChannelAnnounceRequest { + request: ValidatedAnnounceRequest, + source_addr: CanonicalSocketAddr, + response_sender: Sender, +} \ No newline at end of file diff --git a/aquatic_http_private/src/workers/mod.rs b/aquatic_http_private/src/workers/mod.rs index 63fc0ec..978429f 100644 --- a/aquatic_http_private/src/workers/mod.rs +++ b/aquatic_http_private/src/workers/mod.rs @@ -1,2 +1,3 @@ +pub mod common; pub mod request; pub mod socket; diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index 74039cb..4c4f630 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -1,10 +1,19 @@ use std::net::{IpAddr, SocketAddr}; -use aquatic_http_protocol::{common::AnnounceEvent, request::AnnounceRequest}; +use aquatic_http_protocol::{common::AnnounceEvent, request::AnnounceRequest, response::FailureResponse}; use sqlx::{Executor, MySql, Pool}; #[derive(Debug)] -pub struct DbAnnounceRequest { +pub struct ValidatedAnnounceRequest(AnnounceRequest); + +impl Into for ValidatedAnnounceRequest { + fn into(self) -> AnnounceRequest { + self.0 + } +} + +#[derive(Debug)] +struct AnnounceProcedureParameters { source_ip: IpAddr, source_port: u16, user_agent: Option, @@ -17,12 +26,12 @@ pub struct DbAnnounceRequest { left: u64, } -impl DbAnnounceRequest { - pub fn new( +impl AnnounceProcedureParameters { + fn new( source_addr: SocketAddr, user_agent: Option, user_token: String, // FIXME: length - request: AnnounceRequest, + request: &AnnounceRequest, ) -> Self { Self { source_ip: source_addr.ip(), @@ -40,17 +49,47 @@ impl DbAnnounceRequest { } #[derive(Debug, sqlx::FromRow)] -pub struct DbAnnounceResponse { - pub announce_allowed: bool, - pub failure_reason: Option, - pub warning_message: Option, +struct AnnounceProcedureResults { + announce_allowed: bool, + failure_reason: Option, + warning_message: Option, } -pub async fn get_announce_response( +pub async fn validate_announce_request( pool: &Pool, - request: DbAnnounceRequest, -) -> anyhow::Result { - let source_ip_bytes: Vec = match request.source_ip { + source_addr: SocketAddr, + user_agent: Option, + user_token: String, + request: AnnounceRequest, +) -> Result { + let parameters = AnnounceProcedureParameters::new( + source_addr, + user_agent, + user_token, + &request, + ); + + match call_announce_procedure(pool, parameters).await { + Ok(results) => { + if results.announce_allowed { + Ok(ValidatedAnnounceRequest(request)) + } else { + Err(FailureResponse::new(results.failure_reason.unwrap_or_else(|| "Not allowed".into()))) + } + } + Err(err) => { + ::log::error!("announce procedure error: {:#}", err); + + Err(FailureResponse::new("Internal error")) + } + } +} + +async fn call_announce_procedure( + pool: &Pool, + parameters: AnnounceProcedureParameters, +) -> anyhow::Result { + let source_ip_bytes: Vec = match parameters.source_ip { IpAddr::V4(ip) => ip.octets().into(), IpAddr::V6(ip) => ip.octets().into(), }; @@ -81,19 +120,19 @@ pub async fn get_announce_response( ", ) .bind(source_ip_bytes) - .bind(request.source_port) - .bind(request.user_agent) - .bind(request.user_token) - .bind(request.info_hash) - .bind(request.peer_id) - .bind(request.event.as_str()) - .bind(request.uploaded) - .bind(request.downloaded) - .bind(request.left); + .bind(parameters.source_port) + .bind(parameters.user_agent) + .bind(parameters.user_token) + .bind(parameters.info_hash) + .bind(parameters.peer_id) + .bind(parameters.event.as_str()) + .bind(parameters.uploaded) + .bind(parameters.downloaded) + .bind(parameters.left); t.execute(q).await?; - let response = sqlx::query_as::<_, DbAnnounceResponse>( + let response = sqlx::query_as::<_, AnnounceProcedureResults>( " SELECT @p_announce_allowed as announce_allowed, diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index f986816..7d5d0cd 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -1,4 +1,4 @@ -mod db; +pub mod db; mod routes; use std::net::{SocketAddr, TcpListener}; diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index 7652eaf..8e49872 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -7,7 +7,7 @@ use axum::{ use sqlx::mysql::MySqlPool; use std::net::SocketAddr; -use aquatic_http_protocol::request::AnnounceRequest; +use aquatic_http_protocol::{request::AnnounceRequest, response::FailureResponse}; use super::db; @@ -23,16 +23,17 @@ pub async fn announce( let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned()); - let db_announce_request = - db::DbAnnounceRequest::new(peer_addr, opt_user_agent, user_token, request); + let validated_request = db::validate_announce_request(&pool, peer_addr, opt_user_agent, user_token, request).await.map_err(failure_response)?; - let db_announce_result = db::get_announce_response(&pool, db_announce_request) - .await - .map_err(anyhow_error)?; + // TODO: send request to request worker, await oneshot channel response - Ok(format!("{:?}", db_announce_result)) + Ok(format!("{:?}", validated_request)) } fn anyhow_error(err: anyhow::Error) -> (StatusCode, String) { (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) } + +fn failure_response(response: FailureResponse) -> (StatusCode, String) { + (StatusCode::OK, format!("{:?}", response)) +} From 7d3ff2e9e65171a5464acd033e94bd0db61ff49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 16:05:54 +0200 Subject: [PATCH 13/62] http_protocol: expose write on response subtypes --- aquatic_http_protocol/src/response.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index e14e661..68b9eb2 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -54,7 +54,7 @@ pub struct AnnounceResponse { } impl AnnounceResponse { - fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize; bytes_written += output.write(b"d8:completei")?; @@ -106,7 +106,7 @@ pub struct ScrapeResponse { } impl ScrapeResponse { - fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize; bytes_written += output.write(b"d5:filesd")?; @@ -142,7 +142,7 @@ impl FailureResponse { } } - fn write(&self, output: &mut W) -> ::std::io::Result { + pub fn write(&self, output: &mut W) -> ::std::io::Result { let mut bytes_written = 0usize; let reason_bytes = self.failure_reason.as_bytes(); From b0f89edd30a97113dad8d33ae385986ea8dab35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sat, 2 Apr 2022 16:06:16 +0200 Subject: [PATCH 14/62] http_private: more work on announce route and channels --- aquatic_http_private/src/workers/common.rs | 8 +-- aquatic_http_private/src/workers/socket/db.rs | 18 ++++--- .../src/workers/socket/routes.rs | 49 ++++++++++++++----- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/aquatic_http_private/src/workers/common.rs b/aquatic_http_private/src/workers/common.rs index 58db3cd..ae73ace 100644 --- a/aquatic_http_private/src/workers/common.rs +++ b/aquatic_http_private/src/workers/common.rs @@ -5,7 +5,7 @@ use tokio::sync::oneshot::Sender; use super::socket::db::ValidatedAnnounceRequest; pub struct ChannelAnnounceRequest { - request: ValidatedAnnounceRequest, - source_addr: CanonicalSocketAddr, - response_sender: Sender, -} \ No newline at end of file + pub request: ValidatedAnnounceRequest, + pub source_addr: CanonicalSocketAddr, + pub response_sender: Sender, +} diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index 4c4f630..b2b094e 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -1,6 +1,8 @@ use std::net::{IpAddr, SocketAddr}; -use aquatic_http_protocol::{common::AnnounceEvent, request::AnnounceRequest, response::FailureResponse}; +use aquatic_http_protocol::{ + common::AnnounceEvent, request::AnnounceRequest, response::FailureResponse, +}; use sqlx::{Executor, MySql, Pool}; #[derive(Debug)] @@ -62,19 +64,19 @@ pub async fn validate_announce_request( user_token: String, request: AnnounceRequest, ) -> Result { - let parameters = AnnounceProcedureParameters::new( - source_addr, - user_agent, - user_token, - &request, - ); + let parameters = + AnnounceProcedureParameters::new(source_addr, user_agent, user_token, &request); match call_announce_procedure(pool, parameters).await { Ok(results) => { if results.announce_allowed { Ok(ValidatedAnnounceRequest(request)) } else { - Err(FailureResponse::new(results.failure_reason.unwrap_or_else(|| "Not allowed".into()))) + Err(FailureResponse::new( + results + .failure_reason + .unwrap_or_else(|| "Not allowed".into()), + )) } } Err(err) => { diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index 8e49872..a18c23c 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -1,13 +1,21 @@ +use aquatic_common::CanonicalSocketAddr; use axum::{ extract::{ConnectInfo, Path, RawQuery}, headers::UserAgent, http::StatusCode, + response::IntoResponse, Extension, TypedHeader, }; use sqlx::mysql::MySqlPool; use std::net::SocketAddr; +use tokio::sync::oneshot; -use aquatic_http_protocol::{request::AnnounceRequest, response::FailureResponse}; +use aquatic_http_protocol::{ + request::AnnounceRequest, + response::{AnnounceResponse, FailureResponse, Response}, +}; + +use crate::workers::common::ChannelAnnounceRequest; use super::db; @@ -17,23 +25,42 @@ pub async fn announce( opt_user_agent: Option>, Path(user_token): Path, RawQuery(query): RawQuery, -) -> Result { +) -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { let request = AnnounceRequest::from_query_string(&query.unwrap_or_else(|| "".into())) - .map_err(anyhow_error)?; + .map_err(|err| build_response(Response::Failure(FailureResponse::new("Internal error"))))?; let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned()); - let validated_request = db::validate_announce_request(&pool, peer_addr, opt_user_agent, user_token, request).await.map_err(failure_response)?; + let validated_request = + db::validate_announce_request(&pool, peer_addr, opt_user_agent, user_token, request) + .await + .map_err(|r| build_response(Response::Failure(r)))?; - // TODO: send request to request worker, await oneshot channel response + let (response_sender, response_receiver) = oneshot::channel(); - Ok(format!("{:?}", validated_request)) + let canonical_socket_addr = CanonicalSocketAddr::new(peer_addr); + + let channel_request = ChannelAnnounceRequest { + request: validated_request, + source_addr: canonical_socket_addr, + response_sender, + }; + + // TODO: send request to request worker + + let response = response_receiver.await.map_err(|err| { + ::log::error!("channel response sender closed: {}", err); + + build_response(Response::Failure(FailureResponse::new("Internal error"))) + })?; + + Ok(build_response(Response::Announce(response))) } -fn anyhow_error(err: anyhow::Error) -> (StatusCode, String) { - (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()) -} +fn build_response(response: Response) -> (StatusCode, impl IntoResponse) { + let mut response_bytes = Vec::with_capacity(512); -fn failure_response(response: FailureResponse) -> (StatusCode, String) { - (StatusCode::OK, format!("{:?}", response)) + response.write(&mut response_bytes); + + (StatusCode::OK, response_bytes) } From 96e128bb9099fab7c4f80dd38cfc1be9aecf041a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:36:35 +0200 Subject: [PATCH 15/62] http_private: get basic announce route working --- aquatic_http_private/src/common.rs | 48 +++++++++++ aquatic_http_private/src/config.rs | 2 + aquatic_http_private/src/lib.rs | 21 ++++- aquatic_http_private/src/workers/common.rs | 5 +- aquatic_http_private/src/workers/request.rs | 37 ++++++++- .../src/workers/socket/mod.rs | 24 ++++-- .../src/workers/socket/routes.rs | 80 +++++++++++++------ 7 files changed, 181 insertions(+), 36 deletions(-) create mode 100644 aquatic_http_private/src/common.rs diff --git a/aquatic_http_private/src/common.rs b/aquatic_http_private/src/common.rs new file mode 100644 index 0000000..6b00a47 --- /dev/null +++ b/aquatic_http_private/src/common.rs @@ -0,0 +1,48 @@ +use tokio::sync::{mpsc, oneshot}; + +use aquatic_common::CanonicalSocketAddr; +use aquatic_http_protocol::{common::InfoHash, response::Response}; + +use crate::{ + config::Config, + workers::{common::ChannelAnnounceRequest, socket::db::ValidatedAnnounceRequest}, +}; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct RequestWorkerIndex(pub usize); + +impl RequestWorkerIndex { + pub fn from_info_hash(config: &Config, info_hash: InfoHash) -> Self { + Self(info_hash.0[0] as usize % config.request_workers) + } +} + +pub struct ChannelRequestSender(Vec>); + +impl ChannelRequestSender { + pub fn new(senders: Vec>) -> Self { + Self(senders) + } + + pub async fn send_to( + &self, + index: RequestWorkerIndex, + request: ValidatedAnnounceRequest, + source_addr: CanonicalSocketAddr, + ) -> anyhow::Result> { + let (response_sender, response_receiver) = oneshot::channel(); + + let request = ChannelAnnounceRequest { + request, + source_addr, + response_sender, + }; + + match self.0[index.0].send(request).await { + Ok(()) => Ok(response_receiver), + Err(err) => { + Err(anyhow::Error::new(err).context("error sending ChannelAnnounceRequest")) + } + } + } +} diff --git a/aquatic_http_private/src/config.rs b/aquatic_http_private/src/config.rs index bad3d72..713ea8c 100644 --- a/aquatic_http_private/src/config.rs +++ b/aquatic_http_private/src/config.rs @@ -17,6 +17,7 @@ pub struct Config { /// Request workers receive a number of requests from socket workers, /// generate responses and send them back to the socket workers. pub request_workers: usize, + pub worker_channel_size: usize, pub log_level: LogLevel, pub network: NetworkConfig, pub protocol: ProtocolConfig, @@ -29,6 +30,7 @@ impl Default for Config { Self { socket_workers: 1, request_workers: 1, + worker_channel_size: 128, log_level: LogLevel::default(), network: NetworkConfig::default(), protocol: ProtocolConfig::default(), diff --git a/aquatic_http_private/src/lib.rs b/aquatic_http_private/src/lib.rs index f0ce764..23053d1 100644 --- a/aquatic_http_private/src/lib.rs +++ b/aquatic_http_private/src/lib.rs @@ -1,7 +1,12 @@ +mod common; pub mod config; mod workers; +use std::collections::VecDeque; + +use common::ChannelRequestSender; use dotenv::dotenv; +use tokio::sync::mpsc::channel; pub const APP_NAME: &str = "aquatic_http_private: private HTTP/TLS BitTorrent tracker"; pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -9,24 +14,36 @@ pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); pub fn run(config: config::Config) -> anyhow::Result<()> { dotenv().ok(); + let mut request_senders = Vec::new(); + let mut request_receivers = VecDeque::new(); + + for _ in 0..config.request_workers { + let (request_sender, request_receiver) = channel(config.worker_channel_size); + + request_senders.push(request_sender); + request_receivers.push_back(request_receiver); + } + let mut handles = Vec::new(); for _ in 0..config.socket_workers { let config = config.clone(); + let request_sender = ChannelRequestSender::new(request_senders.clone()); let handle = ::std::thread::Builder::new() .name("socket".into()) - .spawn(move || workers::socket::run_socket_worker(config))?; + .spawn(move || workers::socket::run_socket_worker(config, request_sender))?; handles.push(handle); } for _ in 0..config.request_workers { let config = config.clone(); + let request_receiver = request_receivers.pop_front().unwrap(); let handle = ::std::thread::Builder::new() .name("request".into()) - .spawn(move || workers::request::run_request_worker(config))?; + .spawn(move || workers::request::run_request_worker(config, request_receiver))?; handles.push(handle); } diff --git a/aquatic_http_private/src/workers/common.rs b/aquatic_http_private/src/workers/common.rs index ae73ace..558bf07 100644 --- a/aquatic_http_private/src/workers/common.rs +++ b/aquatic_http_private/src/workers/common.rs @@ -1,11 +1,12 @@ use aquatic_common::CanonicalSocketAddr; -use aquatic_http_protocol::response::AnnounceResponse; +use aquatic_http_protocol::response::Response; use tokio::sync::oneshot::Sender; use super::socket::db::ValidatedAnnounceRequest; +#[derive(Debug)] pub struct ChannelAnnounceRequest { pub request: ValidatedAnnounceRequest, pub source_addr: CanonicalSocketAddr, - pub response_sender: Sender, + pub response_sender: Sender, } diff --git a/aquatic_http_private/src/workers/request.rs b/aquatic_http_private/src/workers/request.rs index 068f293..8627706 100644 --- a/aquatic_http_private/src/workers/request.rs +++ b/aquatic_http_private/src/workers/request.rs @@ -1,5 +1,40 @@ +use tokio::sync::mpsc::Receiver; + +use aquatic_http_protocol::response::{FailureResponse, Response}; + use crate::config::Config; -pub fn run_request_worker(config: Config) -> anyhow::Result<()> { +use super::common::ChannelAnnounceRequest; + +pub fn run_request_worker( + config: Config, + request_receiver: Receiver, +) -> anyhow::Result<()> { + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()?; + + runtime.block_on(run_inner(config, request_receiver))?; + Ok(()) } + +async fn run_inner( + config: Config, + mut request_receiver: Receiver, +) -> anyhow::Result<()> { + loop { + let request = request_receiver + .recv() + .await + .ok_or_else(|| anyhow::anyhow!("request channel closed"))?; + + println!("{:?}", request); + + let _ = request + .response_sender + .send(Response::Failure(FailureResponse::new( + "successful actually", + ))); + } +} diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 7d5d0cd..10fcf6c 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -1,27 +1,37 @@ pub mod db; mod routes; -use std::net::{SocketAddr, TcpListener}; +use std::{ + net::{SocketAddr, TcpListener}, + sync::Arc, +}; use anyhow::Context; use axum::{routing::get, Extension, Router}; use sqlx::mysql::MySqlPoolOptions; -use crate::config::Config; +use crate::{common::ChannelRequestSender, config::Config}; -pub fn run_socket_worker(config: Config) -> anyhow::Result<()> { +pub fn run_socket_worker( + config: Config, + request_sender: ChannelRequestSender, +) -> anyhow::Result<()> { let tcp_listener = create_tcp_listener(config.network.address)?; let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() .build()?; - runtime.block_on(run_app(tcp_listener))?; + runtime.block_on(run_app(config, tcp_listener, request_sender))?; Ok(()) } -async fn run_app(tcp_listener: TcpListener) -> anyhow::Result<()> { +async fn run_app( + config: Config, + tcp_listener: TcpListener, + request_sender: ChannelRequestSender, +) -> anyhow::Result<()> { let db_url = ::std::env::var("DATABASE_URL").expect("env var DATABASE_URL"); let pool = MySqlPoolOptions::new() @@ -31,7 +41,9 @@ async fn run_app(tcp_listener: TcpListener) -> anyhow::Result<()> { let app = Router::new() .route("/:user_token/announce/", get(routes::announce)) - .layer(Extension(pool)); + .layer(Extension(Arc::new(config))) + .layer(Extension(pool)) + .layer(Extension(Arc::new(request_sender))); axum::Server::from_tcp(tcp_listener)? .serve(app.into_make_service_with_connect_info::()) diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index a18c23c..320c4a5 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -7,60 +7,90 @@ use axum::{ Extension, TypedHeader, }; use sqlx::mysql::MySqlPool; -use std::net::SocketAddr; -use tokio::sync::oneshot; +use std::{borrow::Cow, net::SocketAddr, sync::Arc}; use aquatic_http_protocol::{ request::AnnounceRequest, - response::{AnnounceResponse, FailureResponse, Response}, + response::{FailureResponse, Response}, }; -use crate::workers::common::ChannelAnnounceRequest; +use crate::{ + common::{ChannelRequestSender, RequestWorkerIndex}, + config::Config, +}; use super::db; pub async fn announce( + Extension(config): Extension>, Extension(pool): Extension, + Extension(request_sender): Extension>, ConnectInfo(peer_addr): ConnectInfo, opt_user_agent: Option>, Path(user_token): Path, RawQuery(query): RawQuery, -) -> Result<(StatusCode, impl IntoResponse), (StatusCode, impl IntoResponse)> { - let request = AnnounceRequest::from_query_string(&query.unwrap_or_else(|| "".into())) - .map_err(|err| build_response(Response::Failure(FailureResponse::new("Internal error"))))?; +) -> Result { + let query = query.ok_or_else(|| create_failure_response("Empty query string"))?; + let request = AnnounceRequest::from_query_string(&query) + .map_err(|_| create_failure_response("Malformed request"))?; + + let request_worker_index = RequestWorkerIndex::from_info_hash(&config, request.info_hash); let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned()); let validated_request = db::validate_announce_request(&pool, peer_addr, opt_user_agent, user_token, request) .await - .map_err(|r| build_response(Response::Failure(r)))?; - - let (response_sender, response_receiver) = oneshot::channel(); + .map_err(|r| create_response(Response::Failure(r)))?; let canonical_socket_addr = CanonicalSocketAddr::new(peer_addr); - let channel_request = ChannelAnnounceRequest { - request: validated_request, - source_addr: canonical_socket_addr, - response_sender, - }; - - // TODO: send request to request worker + let response_receiver = request_sender + .send_to( + request_worker_index, + validated_request, + canonical_socket_addr, + ) + .await + .map_err(|err| internal_error(format!("Sending request over channel failed: {:#}", err)))?; let response = response_receiver.await.map_err(|err| { - ::log::error!("channel response sender closed: {}", err); - - build_response(Response::Failure(FailureResponse::new("Internal error"))) + internal_error(format!("Receiving response over channel failed: {:#}", err)) })?; - Ok(build_response(Response::Announce(response))) + Ok(create_response(response)) } -fn build_response(response: Response) -> (StatusCode, impl IntoResponse) { - let mut response_bytes = Vec::with_capacity(512); +fn create_response(response: Response) -> axum::response::Response { + let mut response_bytes = Vec::with_capacity(64); - response.write(&mut response_bytes); + response.write(&mut response_bytes).unwrap(); - (StatusCode::OK, response_bytes) + ( + StatusCode::OK, + [("Content-type", "text/plain; charset=utf-8")], + response_bytes, + ) + .into_response() +} + +fn create_failure_response>>(reason: R) -> axum::response::Response { + let mut response_bytes = Vec::with_capacity(32); + + FailureResponse::new(reason) + .write(&mut response_bytes) + .unwrap(); + + ( + StatusCode::OK, + [("Content-type", "text/plain; charset=utf-8")], + response_bytes, + ) + .into_response() +} + +fn internal_error(error: String) -> axum::response::Response { + ::log::error!("{}", error); + + create_failure_response("Internal error") } From 5d4f30bb7bd26bc4cdfabf7f6e58330f3519f774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:39:06 +0200 Subject: [PATCH 16/62] http_private: use CanonicalSocketAddr when calling DB --- aquatic_http_private/src/workers/socket/db.rs | 11 ++++++----- aquatic_http_private/src/workers/socket/routes.rs | 14 +++++--------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index b2b094e..f7c3c03 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -1,5 +1,6 @@ -use std::net::{IpAddr, SocketAddr}; +use std::net::IpAddr; +use aquatic_common::CanonicalSocketAddr; use aquatic_http_protocol::{ common::AnnounceEvent, request::AnnounceRequest, response::FailureResponse, }; @@ -30,14 +31,14 @@ struct AnnounceProcedureParameters { impl AnnounceProcedureParameters { fn new( - source_addr: SocketAddr, + source_addr: CanonicalSocketAddr, user_agent: Option, user_token: String, // FIXME: length request: &AnnounceRequest, ) -> Self { Self { - source_ip: source_addr.ip(), - source_port: source_addr.port(), + source_ip: source_addr.get().ip(), + source_port: source_addr.get().port(), user_agent, user_token, info_hash: hex::encode(request.info_hash.0), @@ -59,7 +60,7 @@ struct AnnounceProcedureResults { pub async fn validate_announce_request( pool: &Pool, - source_addr: SocketAddr, + source_addr: CanonicalSocketAddr, user_agent: Option, user_token: String, request: AnnounceRequest, diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index 320c4a5..923ff4e 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -25,7 +25,7 @@ pub async fn announce( Extension(config): Extension>, Extension(pool): Extension, Extension(request_sender): Extension>, - ConnectInfo(peer_addr): ConnectInfo, + ConnectInfo(source_addr): ConnectInfo, opt_user_agent: Option>, Path(user_token): Path, RawQuery(query): RawQuery, @@ -38,19 +38,15 @@ pub async fn announce( let request_worker_index = RequestWorkerIndex::from_info_hash(&config, request.info_hash); let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned()); + let source_addr = CanonicalSocketAddr::new(source_addr); + let validated_request = - db::validate_announce_request(&pool, peer_addr, opt_user_agent, user_token, request) + db::validate_announce_request(&pool, source_addr, opt_user_agent, user_token, request) .await .map_err(|r| create_response(Response::Failure(r)))?; - let canonical_socket_addr = CanonicalSocketAddr::new(peer_addr); - let response_receiver = request_sender - .send_to( - request_worker_index, - validated_request, - canonical_socket_addr, - ) + .send_to(request_worker_index, validated_request, source_addr) .await .map_err(|err| internal_error(format!("Sending request over channel failed: {:#}", err)))?; From 30d06937fc9aafb614fe32eba29853d0bc5676da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:43:38 +0200 Subject: [PATCH 17/62] http_private: disable keep_alive --- aquatic_http_private/src/config.rs | 3 --- aquatic_http_private/src/workers/socket/mod.rs | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/aquatic_http_private/src/config.rs b/aquatic_http_private/src/config.rs index 713ea8c..d595376 100644 --- a/aquatic_http_private/src/config.rs +++ b/aquatic_http_private/src/config.rs @@ -55,8 +55,6 @@ pub struct NetworkConfig { pub tls_certificate_path: PathBuf, /// Path to TLS private key (DER-encoded ASN.1 in PKCS#8 or PKCS#1 format) pub tls_private_key_path: PathBuf, - /// Keep connections alive after sending a response - pub keep_alive: bool, } impl Default for NetworkConfig { @@ -65,7 +63,6 @@ impl Default for NetworkConfig { address: SocketAddr::from(([0, 0, 0, 0], 3000)), tls_certificate_path: "".into(), tls_private_key_path: "".into(), - keep_alive: false, } } } diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 10fcf6c..0f009f5 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -46,6 +46,7 @@ async fn run_app( .layer(Extension(Arc::new(request_sender))); axum::Server::from_tcp(tcp_listener)? + .http1_keepalive(false) .serve(app.into_make_service_with_connect_info::()) .await?; From 8478a2b052fc938701243195f8895aa90f4fa708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:45:23 +0200 Subject: [PATCH 18/62] http_private: handle lacking DATABASE_URL env var better --- aquatic_http_private/src/workers/socket/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 0f009f5..52ecbc9 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -32,7 +32,8 @@ async fn run_app( tcp_listener: TcpListener, request_sender: ChannelRequestSender, ) -> anyhow::Result<()> { - let db_url = ::std::env::var("DATABASE_URL").expect("env var DATABASE_URL"); + let db_url = + ::std::env::var("DATABASE_URL").with_context(|| "Retrieve env var DATABASE_URL")?; let pool = MySqlPoolOptions::new() .max_connections(5) From c424ffb0777d6d55783aada7a7cd3d87054e2a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:51:07 +0200 Subject: [PATCH 19/62] http_private: move all code in workers::common to common --- aquatic_http_private/src/common.rs | 12 ++++++++---- aquatic_http_private/src/workers/common.rs | 12 ------------ aquatic_http_private/src/workers/mod.rs | 1 - aquatic_http_private/src/workers/request.rs | 3 +-- 4 files changed, 9 insertions(+), 19 deletions(-) delete mode 100644 aquatic_http_private/src/workers/common.rs diff --git a/aquatic_http_private/src/common.rs b/aquatic_http_private/src/common.rs index 6b00a47..092d09a 100644 --- a/aquatic_http_private/src/common.rs +++ b/aquatic_http_private/src/common.rs @@ -3,10 +3,14 @@ use tokio::sync::{mpsc, oneshot}; use aquatic_common::CanonicalSocketAddr; use aquatic_http_protocol::{common::InfoHash, response::Response}; -use crate::{ - config::Config, - workers::{common::ChannelAnnounceRequest, socket::db::ValidatedAnnounceRequest}, -}; +use crate::{config::Config, workers::socket::db::ValidatedAnnounceRequest}; + +#[derive(Debug)] +pub struct ChannelAnnounceRequest { + pub request: ValidatedAnnounceRequest, + pub source_addr: CanonicalSocketAddr, + pub response_sender: oneshot::Sender, +} #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct RequestWorkerIndex(pub usize); diff --git a/aquatic_http_private/src/workers/common.rs b/aquatic_http_private/src/workers/common.rs deleted file mode 100644 index 558bf07..0000000 --- a/aquatic_http_private/src/workers/common.rs +++ /dev/null @@ -1,12 +0,0 @@ -use aquatic_common::CanonicalSocketAddr; -use aquatic_http_protocol::response::Response; -use tokio::sync::oneshot::Sender; - -use super::socket::db::ValidatedAnnounceRequest; - -#[derive(Debug)] -pub struct ChannelAnnounceRequest { - pub request: ValidatedAnnounceRequest, - pub source_addr: CanonicalSocketAddr, - pub response_sender: Sender, -} diff --git a/aquatic_http_private/src/workers/mod.rs b/aquatic_http_private/src/workers/mod.rs index 978429f..63fc0ec 100644 --- a/aquatic_http_private/src/workers/mod.rs +++ b/aquatic_http_private/src/workers/mod.rs @@ -1,3 +1,2 @@ -pub mod common; pub mod request; pub mod socket; diff --git a/aquatic_http_private/src/workers/request.rs b/aquatic_http_private/src/workers/request.rs index 8627706..2fcd8b0 100644 --- a/aquatic_http_private/src/workers/request.rs +++ b/aquatic_http_private/src/workers/request.rs @@ -2,10 +2,9 @@ use tokio::sync::mpsc::Receiver; use aquatic_http_protocol::response::{FailureResponse, Response}; +use crate::common::ChannelAnnounceRequest; use crate::config::Config; -use super::common::ChannelAnnounceRequest; - pub fn run_request_worker( config: Config, request_receiver: Receiver, From 4154cc3c2ae8726328672a39ffc5afb4b83bc261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:53:14 +0200 Subject: [PATCH 20/62] http_private: change url format to /announce/:user_token/ --- aquatic_http_private/README.md | 2 +- aquatic_http_private/src/workers/socket/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index 22aa65c..904897e 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -47,4 +47,4 @@ Run application: cargo run -p aquatic_http_private ``` -Test by visiting `localhost:3000/abcd/announce/?info_hash=abcdeabcdeabcdeabcde&peer_id=abcdeabcdeabcdeabcde&port=1000&left=0` \ No newline at end of file +Test by visiting `localhost:3000/announce/abcd/?info_hash=abcdeabcdeabcdeabcde&peer_id=abcdeabcdeabcdeabcde&port=1000&left=0` \ No newline at end of file diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 52ecbc9..5f38a85 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -41,7 +41,7 @@ async fn run_app( .await?; let app = Router::new() - .route("/:user_token/announce/", get(routes::announce)) + .route("/announce/:user_token/", get(routes::announce)) .layer(Extension(Arc::new(config))) .layer(Extension(pool)) .layer(Extension(Arc::new(request_sender))); From 44f4474fb22cea4abc47489f1be90497728f1fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 00:56:54 +0200 Subject: [PATCH 21/62] Update TODO --- TODO.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 644d3dd..4c3eec9 100644 --- a/TODO.md +++ b/TODO.md @@ -3,9 +3,8 @@ ## High priority * aquatic_http_private - * test passing data between runtimes + * utf8 responses * stored procedure - * should source ip be canonical? * handle/document lack of NOT NULL * event can be null * test ip format From 70d79b1871eb3b3ed182e87f6359b06f3173dee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 01:07:16 +0200 Subject: [PATCH 22/62] http: add AnnounceResponse.warning_message; set in http_private --- aquatic_http/src/workers/request.rs | 2 ++ aquatic_http_private/src/workers/socket/db.rs | 4 ++-- aquatic_http_private/src/workers/socket/routes.rs | 8 ++++++-- .../benches/bench_announce_response_to_bytes.rs | 1 + aquatic_http_protocol/src/response.rs | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 4 deletions(-) diff --git a/aquatic_http/src/workers/request.rs b/aquatic_http/src/workers/request.rs index 4dd36aa..8ac677e 100644 --- a/aquatic_http/src/workers/request.rs +++ b/aquatic_http/src/workers/request.rs @@ -337,6 +337,7 @@ pub fn handle_announce_request( announce_interval: config.protocol.peer_announce_interval, peers: ResponsePeerListV4(response_peers), peers6: ResponsePeerListV6(vec![]), + warning_message: None, }; response @@ -366,6 +367,7 @@ pub fn handle_announce_request( announce_interval: config.protocol.peer_announce_interval, peers: ResponsePeerListV4(vec![]), peers6: ResponsePeerListV6(response_peers), + warning_message: None, }; response diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index f7c3c03..ffa6b3a 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -64,14 +64,14 @@ pub async fn validate_announce_request( user_agent: Option, user_token: String, request: AnnounceRequest, -) -> Result { +) -> Result<(ValidatedAnnounceRequest, Option), FailureResponse> { let parameters = AnnounceProcedureParameters::new(source_addr, user_agent, user_token, &request); match call_announce_procedure(pool, parameters).await { Ok(results) => { if results.announce_allowed { - Ok(ValidatedAnnounceRequest(request)) + Ok((ValidatedAnnounceRequest(request), results.warning_message)) } else { Err(FailureResponse::new( results diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index 923ff4e..bfc081c 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -40,7 +40,7 @@ pub async fn announce( let source_addr = CanonicalSocketAddr::new(source_addr); - let validated_request = + let (validated_request, opt_warning_message) = db::validate_announce_request(&pool, source_addr, opt_user_agent, user_token, request) .await .map_err(|r| create_response(Response::Failure(r)))?; @@ -50,10 +50,14 @@ pub async fn announce( .await .map_err(|err| internal_error(format!("Sending request over channel failed: {:#}", err)))?; - let response = response_receiver.await.map_err(|err| { + let mut response = response_receiver.await.map_err(|err| { internal_error(format!("Receiving response over channel failed: {:#}", err)) })?; + if let Response::Announce(ref mut r) = response { + r.warning_message = opt_warning_message; + } + Ok(create_response(response)) } diff --git a/aquatic_http_protocol/benches/bench_announce_response_to_bytes.rs b/aquatic_http_protocol/benches/bench_announce_response_to_bytes.rs index 03a8008..b871cf0 100644 --- a/aquatic_http_protocol/benches/bench_announce_response_to_bytes.rs +++ b/aquatic_http_protocol/benches/bench_announce_response_to_bytes.rs @@ -21,6 +21,7 @@ pub fn bench(c: &mut Criterion) { incomplete: 500, peers: ResponsePeerListV4(peers), peers6: ResponsePeerListV6(Vec::new()), + warning_message: None, }; let response = Response::Announce(announce_response); diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index 68b9eb2..0eeb7f7 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -51,6 +51,8 @@ pub struct AnnounceResponse { pub peers: ResponsePeerListV4, #[serde(default)] pub peers6: ResponsePeerListV6, + #[serde(rename = "warning message")] + pub warning_message: Option, } impl AnnounceResponse { @@ -95,6 +97,17 @@ impl AnnounceResponse { } bytes_written += output.write(b"e")?; + if let Some(ref warning_message) = self.warning_message { + let message_bytes = warning_message.as_bytes(); + + bytes_written += output.write(b"d15:warning message")?; + bytes_written += + output.write(itoa::Buffer::new().format(message_bytes.len()).as_bytes())?; + bytes_written += output.write(b":")?; + bytes_written += output.write(message_bytes)?; + bytes_written += output.write(b"e")?; + } + Ok(bytes_written) } } @@ -232,6 +245,7 @@ impl quickcheck::Arbitrary for AnnounceResponse { incomplete: usize::arbitrary(g), peers: ResponsePeerListV4::arbitrary(g), peers6: ResponsePeerListV6::arbitrary(g), + warning_message: quickcheck::Arbitrary::arbitrary(g), } } } From f1e81a528843eecd3464a240c2f05c4fde2fff6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 01:09:42 +0200 Subject: [PATCH 23/62] http_private: increase response byte vector capacities --- aquatic_http_private/src/workers/socket/routes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index bfc081c..481728a 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -62,7 +62,7 @@ pub async fn announce( } fn create_response(response: Response) -> axum::response::Response { - let mut response_bytes = Vec::with_capacity(64); + let mut response_bytes = Vec::with_capacity(128); response.write(&mut response_bytes).unwrap(); @@ -75,7 +75,7 @@ fn create_response(response: Response) -> axum::response::Response { } fn create_failure_response>>(reason: R) -> axum::response::Response { - let mut response_bytes = Vec::with_capacity(32); + let mut response_bytes = Vec::with_capacity(64); FailureResponse::new(reason) .write(&mut response_bytes) From 1b2009ba6095b2c294e222537c74842f2f09725d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 01:42:46 +0200 Subject: [PATCH 24/62] http_private: do more work on request worker --- aquatic_http_private/src/workers/request.rs | 171 +++++++++++++++++++- 1 file changed, 163 insertions(+), 8 deletions(-) diff --git a/aquatic_http_private/src/workers/request.rs b/aquatic_http_private/src/workers/request.rs index 2fcd8b0..4698d4d 100644 --- a/aquatic_http_private/src/workers/request.rs +++ b/aquatic_http_private/src/workers/request.rs @@ -1,10 +1,136 @@ -use tokio::sync::mpsc::Receiver; +use std::cell::RefCell; +use std::net::{Ipv4Addr, Ipv6Addr}; +use std::rc::Rc; +use std::time::Instant; -use aquatic_http_protocol::response::{FailureResponse, Response}; +use tokio::sync::mpsc::Receiver; +use tokio::task::LocalSet; +use tokio::time; + +use aquatic_common::{AmortizedIndexMap, CanonicalSocketAddr, ValidUntil}; +use aquatic_http_protocol::common::{AnnounceEvent, InfoHash, PeerId}; +use aquatic_http_protocol::request::AnnounceRequest; +use aquatic_http_protocol::response::{FailureResponse, Response, ResponsePeer}; use crate::common::ChannelAnnounceRequest; use crate::config::Config; +pub trait Ip: ::std::fmt::Debug + Copy + Eq + ::std::hash::Hash {} + +impl Ip for Ipv4Addr {} +impl Ip for Ipv6Addr {} + +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum PeerStatus { + Seeding, + Leeching, + Stopped, +} + +impl PeerStatus { + /// Determine peer status from announce event and number of bytes left. + /// + /// Likely, the last branch will be taken most of the time. + #[inline] + pub fn from_event_and_bytes_left(event: AnnounceEvent, opt_bytes_left: Option) -> Self { + if let AnnounceEvent::Stopped = event { + Self::Stopped + } else if let Some(0) = opt_bytes_left { + Self::Seeding + } else { + Self::Leeching + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Peer { + pub ip_address: I, + pub port: u16, + pub status: PeerStatus, + pub valid_until: ValidUntil, +} + +impl Peer { + pub fn to_response_peer(&self) -> ResponsePeer { + ResponsePeer { + ip_address: self.ip_address, + port: self.port, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PeerMapKey { + pub peer_id: PeerId, + pub ip: I, +} + +pub type PeerMap = AmortizedIndexMap, Peer>; + +pub struct TorrentData { + pub peers: PeerMap, + pub num_seeders: usize, + pub num_leechers: usize, +} + +impl Default for TorrentData { + #[inline] + fn default() -> Self { + Self { + peers: Default::default(), + num_seeders: 0, + num_leechers: 0, + } + } +} + +pub type TorrentMap = AmortizedIndexMap>; + +#[derive(Default)] +pub struct TorrentMaps { + pub ipv4: TorrentMap, + pub ipv6: TorrentMap, +} + +impl TorrentMaps { + pub fn clean(&mut self) { + Self::clean_torrent_map(&mut self.ipv4); + Self::clean_torrent_map(&mut self.ipv6); + } + + fn clean_torrent_map(torrent_map: &mut TorrentMap) { + let now = Instant::now(); + + torrent_map.retain(|_, torrent_data| { + let num_seeders = &mut torrent_data.num_seeders; + let num_leechers = &mut torrent_data.num_leechers; + + torrent_data.peers.retain(|_, peer| { + let keep = peer.valid_until.0 >= now; + + if !keep { + match peer.status { + PeerStatus::Seeding => { + *num_seeders -= 1; + } + PeerStatus::Leeching => { + *num_leechers -= 1; + } + _ => (), + }; + } + + keep + }); + + !torrent_data.peers.is_empty() + }); + + torrent_map.shrink_to_fit(); + } +} + pub fn run_request_worker( config: Config, request_receiver: Receiver, @@ -22,18 +148,47 @@ async fn run_inner( config: Config, mut request_receiver: Receiver, ) -> anyhow::Result<()> { + let torrents = Rc::new(RefCell::new(TorrentMaps::default())); + + LocalSet::new().spawn_local(periodically_clean_torrents( + config.clone(), + torrents.clone(), + )); + loop { let request = request_receiver .recv() .await .ok_or_else(|| anyhow::anyhow!("request channel closed"))?; - println!("{:?}", request); + let response = handle_announce_request( + &config, + &torrents, + request.source_addr, + request.request.into(), + ); - let _ = request - .response_sender - .send(Response::Failure(FailureResponse::new( - "successful actually", - ))); + let _ = request.response_sender.send(response); + } +} + +fn handle_announce_request( + config: &Config, + torrents: &Rc>, + source_addr: CanonicalSocketAddr, + request: AnnounceRequest, +) -> Response { + Response::Failure(FailureResponse::new("actually successful")) +} + +async fn periodically_clean_torrents(config: Config, torrents: Rc>) { + let mut interval = time::interval(time::Duration::from_secs( + config.cleaning.torrent_cleaning_interval, + )); + + loop { + interval.tick().await; + + torrents.borrow_mut().clean(); } } From e228f5a4c28f97551105bccd7481eb59218451ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 01:44:29 +0200 Subject: [PATCH 25/62] http_private: make TorrentMap cleaning logic more readable --- aquatic_http_private/src/workers/request.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aquatic_http_private/src/workers/request.rs b/aquatic_http_private/src/workers/request.rs index 4698d4d..be09c0d 100644 --- a/aquatic_http_private/src/workers/request.rs +++ b/aquatic_http_private/src/workers/request.rs @@ -107,9 +107,9 @@ impl TorrentMaps { let num_leechers = &mut torrent_data.num_leechers; torrent_data.peers.retain(|_, peer| { - let keep = peer.valid_until.0 >= now; - - if !keep { + if peer.valid_until.0 >= now { + true + } else { match peer.status { PeerStatus::Seeding => { *num_seeders -= 1; @@ -119,9 +119,9 @@ impl TorrentMaps { } _ => (), }; - } - keep + false + } }); !torrent_data.peers.is_empty() From eeaae29fa8d7985c06f99ed69acc2cc08a372de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 16:26:41 +0200 Subject: [PATCH 26/62] http_private: handle announce requests in request worker --- Cargo.lock | 1 + aquatic_http_private/Cargo.toml | 1 + .../workers/{request.rs => request/common.rs} | 78 +------ .../src/workers/request/mod.rs | 210 ++++++++++++++++++ 4 files changed, 215 insertions(+), 75 deletions(-) rename aquatic_http_private/src/workers/{request.rs => request/common.rs} (59%) create mode 100644 aquatic_http_private/src/workers/request/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 5df294d..a1ba986 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,6 +153,7 @@ dependencies = [ "hex", "log", "mimalloc", + "rand", "serde", "socket2 0.4.4", "sqlx", diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index 272fed8..56189a9 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -21,6 +21,7 @@ dotenv = "0.15" hex = "0.4" log = "0.4" mimalloc = { version = "0.1", default-features = false } +rand = { version = "0.8", features = ["small_rng"] } serde = { version = "1", features = ["derive"] } socket2 = { version = "0.4", features = ["all"] } sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" , "mysql" ] } diff --git a/aquatic_http_private/src/workers/request.rs b/aquatic_http_private/src/workers/request/common.rs similarity index 59% rename from aquatic_http_private/src/workers/request.rs rename to aquatic_http_private/src/workers/request/common.rs index be09c0d..abbcbc3 100644 --- a/aquatic_http_private/src/workers/request.rs +++ b/aquatic_http_private/src/workers/request/common.rs @@ -1,19 +1,9 @@ -use std::cell::RefCell; use std::net::{Ipv4Addr, Ipv6Addr}; -use std::rc::Rc; use std::time::Instant; -use tokio::sync::mpsc::Receiver; -use tokio::task::LocalSet; -use tokio::time; - -use aquatic_common::{AmortizedIndexMap, CanonicalSocketAddr, ValidUntil}; +use aquatic_common::{AmortizedIndexMap, ValidUntil}; use aquatic_http_protocol::common::{AnnounceEvent, InfoHash, PeerId}; -use aquatic_http_protocol::request::AnnounceRequest; -use aquatic_http_protocol::response::{FailureResponse, Response, ResponsePeer}; - -use crate::common::ChannelAnnounceRequest; -use crate::config::Config; +use aquatic_http_protocol::response::ResponsePeer; pub trait Ip: ::std::fmt::Debug + Copy + Eq + ::std::hash::Hash {} @@ -63,7 +53,7 @@ impl Peer { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct PeerMapKey { pub peer_id: PeerId, - pub ip: I, + pub ip_address: I, } pub type PeerMap = AmortizedIndexMap, Peer>; @@ -130,65 +120,3 @@ impl TorrentMaps { torrent_map.shrink_to_fit(); } } - -pub fn run_request_worker( - config: Config, - request_receiver: Receiver, -) -> anyhow::Result<()> { - let runtime = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build()?; - - runtime.block_on(run_inner(config, request_receiver))?; - - Ok(()) -} - -async fn run_inner( - config: Config, - mut request_receiver: Receiver, -) -> anyhow::Result<()> { - let torrents = Rc::new(RefCell::new(TorrentMaps::default())); - - LocalSet::new().spawn_local(periodically_clean_torrents( - config.clone(), - torrents.clone(), - )); - - loop { - let request = request_receiver - .recv() - .await - .ok_or_else(|| anyhow::anyhow!("request channel closed"))?; - - let response = handle_announce_request( - &config, - &torrents, - request.source_addr, - request.request.into(), - ); - - let _ = request.response_sender.send(response); - } -} - -fn handle_announce_request( - config: &Config, - torrents: &Rc>, - source_addr: CanonicalSocketAddr, - request: AnnounceRequest, -) -> Response { - Response::Failure(FailureResponse::new("actually successful")) -} - -async fn periodically_clean_torrents(config: Config, torrents: Rc>) { - let mut interval = time::interval(time::Duration::from_secs( - config.cleaning.torrent_cleaning_interval, - )); - - loop { - interval.tick().await; - - torrents.borrow_mut().clean(); - } -} diff --git a/aquatic_http_private/src/workers/request/mod.rs b/aquatic_http_private/src/workers/request/mod.rs new file mode 100644 index 0000000..358ead6 --- /dev/null +++ b/aquatic_http_private/src/workers/request/mod.rs @@ -0,0 +1,210 @@ +mod common; + +use std::cell::RefCell; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::rc::Rc; + +use aquatic_http_protocol::request::AnnounceRequest; +use rand::prelude::SmallRng; +use rand::SeedableRng; +use tokio::sync::mpsc::Receiver; +use tokio::task::LocalSet; +use tokio::time; + +use aquatic_common::{extract_response_peers, CanonicalSocketAddr, ValidUntil}; +use aquatic_http_protocol::response::{ + AnnounceResponse, Response, ResponsePeer, ResponsePeerListV4, ResponsePeerListV6, +}; + +use crate::common::ChannelAnnounceRequest; +use crate::config::Config; + +use common::*; + +pub fn run_request_worker( + config: Config, + request_receiver: Receiver, +) -> anyhow::Result<()> { + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()?; + + runtime.block_on(run_inner(config, request_receiver))?; + + Ok(()) +} + +async fn run_inner( + config: Config, + mut request_receiver: Receiver, +) -> anyhow::Result<()> { + let torrents = Rc::new(RefCell::new(TorrentMaps::default())); + let mut rng = SmallRng::from_entropy(); + + LocalSet::new().spawn_local(periodically_clean_torrents( + config.clone(), + torrents.clone(), + )); + + loop { + let request = request_receiver + .recv() + .await + .ok_or_else(|| anyhow::anyhow!("request channel closed"))?; + + let valid_until = ValidUntil::new(config.cleaning.max_peer_age); + + let response = handle_announce_request( + &config, + &mut rng, + &mut torrents.borrow_mut(), + valid_until, + request.source_addr, + request.request.into(), + ); + + let _ = request.response_sender.send(Response::Announce(response)); + } +} + +async fn periodically_clean_torrents(config: Config, torrents: Rc>) { + let mut interval = time::interval(time::Duration::from_secs( + config.cleaning.torrent_cleaning_interval, + )); + + loop { + interval.tick().await; + + torrents.borrow_mut().clean(); + } +} + +fn handle_announce_request( + config: &Config, + rng: &mut SmallRng, + torrent_maps: &mut TorrentMaps, + valid_until: ValidUntil, + source_addr: CanonicalSocketAddr, + request: AnnounceRequest, +) -> AnnounceResponse { + match source_addr.get().ip() { + IpAddr::V4(source_ip) => { + let torrent_data: &mut TorrentData = + torrent_maps.ipv4.entry(request.info_hash).or_default(); + + let (seeders, leechers, response_peers) = upsert_peer_and_get_response_peers( + config, + rng, + torrent_data, + source_ip, + request, + valid_until, + ); + + let response = AnnounceResponse { + complete: seeders, + incomplete: leechers, + announce_interval: config.protocol.peer_announce_interval, + peers: ResponsePeerListV4(response_peers), + peers6: ResponsePeerListV6(vec![]), + warning_message: None, + }; + + response + } + IpAddr::V6(source_ip) => { + let torrent_data: &mut TorrentData = + torrent_maps.ipv6.entry(request.info_hash).or_default(); + + let (seeders, leechers, response_peers) = upsert_peer_and_get_response_peers( + config, + rng, + torrent_data, + source_ip, + request, + valid_until, + ); + + let response = AnnounceResponse { + complete: seeders, + incomplete: leechers, + announce_interval: config.protocol.peer_announce_interval, + peers: ResponsePeerListV4(vec![]), + peers6: ResponsePeerListV6(response_peers), + warning_message: None, + }; + + response + } + } +} + +/// Insert/update peer. Return num_seeders, num_leechers and response peers +pub fn upsert_peer_and_get_response_peers( + config: &Config, + rng: &mut SmallRng, + torrent_data: &mut TorrentData, + source_ip: I, + request: AnnounceRequest, + valid_until: ValidUntil, +) -> (usize, usize, Vec>) { + // Insert/update/remove peer who sent this request + + let peer_status = + PeerStatus::from_event_and_bytes_left(request.event, Some(request.bytes_left)); + + let peer = Peer { + ip_address: source_ip, + port: request.port, + status: peer_status, + valid_until, + }; + + let peer_map_key = PeerMapKey { + peer_id: request.peer_id, + ip_address: source_ip, + }; + + let opt_removed_peer = match peer_status { + PeerStatus::Leeching => { + torrent_data.num_leechers += 1; + + torrent_data.peers.insert(peer_map_key.clone(), peer) + } + PeerStatus::Seeding => { + torrent_data.num_seeders += 1; + + torrent_data.peers.insert(peer_map_key.clone(), peer) + } + PeerStatus::Stopped => torrent_data.peers.remove(&peer_map_key), + }; + + match opt_removed_peer.map(|peer| peer.status) { + Some(PeerStatus::Leeching) => { + torrent_data.num_leechers -= 1; + } + Some(PeerStatus::Seeding) => { + torrent_data.num_seeders -= 1; + } + _ => {} + } + + let max_num_peers_to_take = match request.numwant { + Some(0) | None => config.protocol.max_peers, + Some(numwant) => numwant.min(config.protocol.max_peers), + }; + + let response_peers: Vec> = extract_response_peers( + rng, + &torrent_data.peers, + max_num_peers_to_take, + peer_map_key, + Peer::to_response_peer, + ); + + ( + torrent_data.num_seeders, + torrent_data.num_leechers, + response_peers, + ) +} From 11cba4eb122de7a52f4670e5d1d6e3b530190d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 16:31:45 +0200 Subject: [PATCH 27/62] Add scripts/run-aquatic-http-private.sh --- scripts/run-aquatic-http-private.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 scripts/run-aquatic-http-private.sh diff --git a/scripts/run-aquatic-http-private.sh b/scripts/run-aquatic-http-private.sh new file mode 100755 index 0000000..5f7d9d8 --- /dev/null +++ b/scripts/run-aquatic-http-private.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +. ./scripts/env-native-cpu-without-avx-512 + +cargo run --release --bin aquatic_http_private -- $@ From fa5e609f11d2b4443183ebeadbcd00c5ea825f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 16:49:22 +0200 Subject: [PATCH 28/62] http_private: remove connection cleaning config vars --- aquatic_http_private/src/config.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/aquatic_http_private/src/config.rs b/aquatic_http_private/src/config.rs index d595376..3d38aef 100644 --- a/aquatic_http_private/src/config.rs +++ b/aquatic_http_private/src/config.rs @@ -93,21 +93,15 @@ impl Default for ProtocolConfig { pub struct CleaningConfig { /// Clean peers this often (seconds) pub torrent_cleaning_interval: u64, - /// Clean connections this often (seconds) - pub connection_cleaning_interval: u64, /// Remove peers that have not announced for this long (seconds) pub max_peer_age: u64, - /// Remove connections that haven't seen valid requests for this long (seconds) - pub max_connection_idle: u64, } impl Default for CleaningConfig { fn default() -> Self { Self { torrent_cleaning_interval: 30, - connection_cleaning_interval: 60, max_peer_age: 360, - max_connection_idle: 180, } } } From 85d89f53ca60fc3556fbcd9c148279a3870709e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 16:57:25 +0200 Subject: [PATCH 29/62] Add workspace patch with fix for membarrier compilation error --- Cargo.lock | 3 +-- Cargo.toml | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1ba986..968236c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1560,8 +1560,7 @@ checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" [[package]] name = "membarrier" version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925b0811d7e5fb2b666b5906c5047b7ec23aab78edc4d51b7b0f82dc5c955b1c" +source = "git+https://github.com/glommer/membarrier-rs.git?branch=issue-22#a79ea2d9b6e976b83b7fd709073cf977b1e47581" dependencies = [ "cfg-if", "kernel32-sys", diff --git a/Cargo.toml b/Cargo.toml index 76433b5..c72e55f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,8 @@ aquatic_ws_load_test = { path = "aquatic_ws_load_test" } aquatic_ws = { path = "aquatic_ws" } aquatic_ws_protocol = { path = "aquatic_ws_protocol" } +membarrier = { git = "https://github.com/glommer/membarrier-rs.git", branch = "issue-22" } + [profile.release] debug = true lto = true From 07bb75c298724b802411bd151e0cb6d6f5c911ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 16:59:01 +0200 Subject: [PATCH 30/62] http load test: add missing AnnounceRequest fields --- aquatic_http_load_test/src/utils.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aquatic_http_load_test/src/utils.rs b/aquatic_http_load_test/src/utils.rs index 774f276..bf4c341 100644 --- a/aquatic_http_load_test/src/utils.rs +++ b/aquatic_http_load_test/src/utils.rs @@ -48,6 +48,8 @@ fn create_announce_request(config: &Config, state: &LoadTestState, rng: &mut imp numwant: None, compact: true, port: rng.gen(), + bytes_uploaded: 0, + bytes_downloaded: 0, }) } From e790727bc0dd00d3006658d4cf784e9789a58a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 18:36:37 +0200 Subject: [PATCH 31/62] aquatic_common: add feature gated fn create_rustls_config --- aquatic_common/Cargo.toml | 7 +++++- aquatic_common/src/lib.rs | 2 ++ aquatic_common/src/rustls_config.rs | 35 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 aquatic_common/src/rustls_config.rs diff --git a/aquatic_common/Cargo.toml b/aquatic_common/Cargo.toml index 1a1790f..4f2b994 100644 --- a/aquatic_common/Cargo.toml +++ b/aquatic_common/Cargo.toml @@ -13,6 +13,7 @@ name = "aquatic_common" [features] cpu-pinning = ["hwloc", "libc"] +rustls-config = ["rustls", "rustls-pemfile"] [dependencies] aquatic_toml_config = "0.2.0" @@ -30,4 +31,8 @@ serde = { version = "1", features = ["derive"] } # cpu-pinning hwloc = { version = "0.5", optional = true } -libc = { version = "0.2", optional = true } \ No newline at end of file +libc = { version = "0.2", optional = true } + +# rustls-config +rustls = { version = "0.20", optional = true } +rustls-pemfile = { version = "0.3", optional = true } \ No newline at end of file diff --git a/aquatic_common/src/lib.rs b/aquatic_common/src/lib.rs index 6995382..687a547 100644 --- a/aquatic_common/src/lib.rs +++ b/aquatic_common/src/lib.rs @@ -8,6 +8,8 @@ pub mod access_list; #[cfg(feature = "cpu-pinning")] pub mod cpu_pinning; pub mod privileges; +#[cfg(feature = "rustls-config")] +pub mod rustls_config; /// Amortized IndexMap using AHash hasher pub type AmortizedIndexMap = indexmap_amortized::IndexMap; diff --git a/aquatic_common/src/rustls_config.rs b/aquatic_common/src/rustls_config.rs new file mode 100644 index 0000000..b852ec1 --- /dev/null +++ b/aquatic_common/src/rustls_config.rs @@ -0,0 +1,35 @@ +use std::{fs::File, io::BufReader, path::Path}; + +pub type RustlsConfig = rustls::ServerConfig; + +pub fn create_rustls_config( + tls_certificate_path: &Path, + tls_private_key_path: &Path, +) -> anyhow::Result { + let certs = { + let f = File::open(tls_certificate_path)?; + let mut f = BufReader::new(f); + + rustls_pemfile::certs(&mut f)? + .into_iter() + .map(|bytes| rustls::Certificate(bytes)) + .collect() + }; + + let private_key = { + let f = File::open(tls_private_key_path)?; + let mut f = BufReader::new(f); + + rustls_pemfile::pkcs8_private_keys(&mut f)? + .first() + .map(|bytes| rustls::PrivateKey(bytes.clone())) + .ok_or(anyhow::anyhow!("No private keys in file"))? + }; + + let tls_config = rustls::ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(certs, private_key)?; + + Ok(tls_config) +} From c21ed97cb24e91519dd2e39524722bd271fe5a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:07:55 +0200 Subject: [PATCH 32/62] http_private: get tls working --- Cargo.lock | 19 ++- aquatic_http_private/Cargo.toml | 7 +- aquatic_http_private/src/lib.rs | 17 +- .../src/workers/socket/mod.rs | 26 ++- .../src/workers/socket/tls.rs | 151 ++++++++++++++++++ 5 files changed, 211 insertions(+), 9 deletions(-) create mode 100644 aquatic_http_private/src/workers/socket/tls.rs diff --git a/Cargo.lock b/Cargo.lock index 968236c..399cb3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,6 +83,8 @@ dependencies = [ "log", "privdrop", "rand", + "rustls 0.20.4", + "rustls-pemfile", "serde", ] @@ -150,14 +152,18 @@ dependencies = [ "aquatic_toml_config", "axum", "dotenv", + "futures-util", "hex", + "hyper", "log", "mimalloc", "rand", + "rustls 0.20.4", "serde", "socket2 0.4.4", "sqlx", "tokio", + "tokio-rustls 0.23.3", ] [[package]] @@ -2619,7 +2625,7 @@ checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6" dependencies = [ "once_cell", "tokio", - "tokio-rustls", + "tokio-rustls 0.22.0", ] [[package]] @@ -2797,6 +2803,17 @@ dependencies = [ "webpki 0.21.4", ] +[[package]] +name = "tokio-rustls" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" +dependencies = [ + "rustls 0.20.4", + "tokio", + "webpki 0.22.0", +] + [[package]] name = "tokio-stream" version = "0.1.8" diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index 56189a9..bad6901 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -11,19 +11,22 @@ name = "aquatic_http_private" [dependencies] aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" +aquatic_common = { version = "0.2.0", features = ["rustls-config"] } aquatic_http_protocol = "0.2.0" aquatic_toml_config = "0.2.0" anyhow = "1" axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] } dotenv = "0.15" +futures-util = { version = "0.3", default-features = false } hex = "0.4" +hyper = "0.14" log = "0.4" mimalloc = { version = "0.1", default-features = false } rand = { version = "0.8", features = ["small_rng"] } +rustls = "0.20" serde = { version = "1", features = ["derive"] } socket2 = { version = "0.4", features = ["all"] } sqlx = { version = "0.5", features = [ "runtime-tokio-rustls" , "mysql" ] } tokio = { version = "1", features = ["full"] } - +tokio-rustls = "0.23" diff --git a/aquatic_http_private/src/lib.rs b/aquatic_http_private/src/lib.rs index 23053d1..8e9d7a7 100644 --- a/aquatic_http_private/src/lib.rs +++ b/aquatic_http_private/src/lib.rs @@ -2,18 +2,26 @@ mod common; pub mod config; mod workers; -use std::collections::VecDeque; +use std::{collections::VecDeque, sync::Arc}; +use aquatic_common::rustls_config::create_rustls_config; use common::ChannelRequestSender; use dotenv::dotenv; use tokio::sync::mpsc::channel; +use config::Config; + pub const APP_NAME: &str = "aquatic_http_private: private HTTP/TLS BitTorrent tracker"; pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub fn run(config: config::Config) -> anyhow::Result<()> { +pub fn run(config: Config) -> anyhow::Result<()> { dotenv().ok(); + let tls_config = Arc::new(create_rustls_config( + &config.network.tls_certificate_path, + &config.network.tls_private_key_path, + )?); + let mut request_senders = Vec::new(); let mut request_receivers = VecDeque::new(); @@ -28,11 +36,14 @@ pub fn run(config: config::Config) -> anyhow::Result<()> { for _ in 0..config.socket_workers { let config = config.clone(); + let tls_config = tls_config.clone(); let request_sender = ChannelRequestSender::new(request_senders.clone()); let handle = ::std::thread::Builder::new() .name("socket".into()) - .spawn(move || workers::socket::run_socket_worker(config, request_sender))?; + .spawn(move || { + workers::socket::run_socket_worker(config, tls_config, request_sender) + })?; handles.push(handle); } diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 5f38a85..d94e3f8 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -1,5 +1,6 @@ pub mod db; mod routes; +mod tls; use std::{ net::{SocketAddr, TcpListener}, @@ -7,13 +8,23 @@ use std::{ }; use anyhow::Context; -use axum::{routing::get, Extension, Router}; +use aquatic_common::rustls_config::RustlsConfig; +use axum::{extract::connect_info::Connected, routing::get, Extension, Router}; +use hyper::server::conn::AddrIncoming; use sqlx::mysql::MySqlPoolOptions; +use self::tls::{TlsAcceptor, TlsStream}; use crate::{common::ChannelRequestSender, config::Config}; +impl<'a> Connected<&'a tls::TlsStream> for SocketAddr { + fn connect_info(target: &'a TlsStream) -> Self { + target.get_remote_addr() + } +} + pub fn run_socket_worker( config: Config, + tls_config: Arc, request_sender: ChannelRequestSender, ) -> anyhow::Result<()> { let tcp_listener = create_tcp_listener(config.network.address)?; @@ -22,19 +33,25 @@ pub fn run_socket_worker( .enable_all() .build()?; - runtime.block_on(run_app(config, tcp_listener, request_sender))?; + runtime.block_on(run_app(config, tls_config, tcp_listener, request_sender))?; Ok(()) } async fn run_app( config: Config, + tls_config: Arc, tcp_listener: TcpListener, request_sender: ChannelRequestSender, ) -> anyhow::Result<()> { let db_url = ::std::env::var("DATABASE_URL").with_context(|| "Retrieve env var DATABASE_URL")?; + let tls_acceptor = TlsAcceptor::new( + tls_config, + AddrIncoming::from_listener(tokio::net::TcpListener::from_std(tcp_listener)?)?, + ); + let pool = MySqlPoolOptions::new() .max_connections(5) .connect(&db_url) @@ -46,7 +63,7 @@ async fn run_app( .layer(Extension(pool)) .layer(Extension(Arc::new(request_sender))); - axum::Server::from_tcp(tcp_listener)? + axum::Server::builder(tls_acceptor) .http1_keepalive(false) .serve(app.into_make_service_with_connect_info::()) .await?; @@ -66,6 +83,9 @@ fn create_tcp_listener(addr: SocketAddr) -> anyhow::Result { socket .set_reuse_port(true) .with_context(|| "set_reuse_port")?; + socket + .set_nonblocking(true) + .with_context(|| "set_nonblocking")?; socket .bind(&addr.into()) .with_context(|| format!("bind to {}", addr))?; diff --git a/aquatic_http_private/src/workers/socket/tls.rs b/aquatic_http_private/src/workers/socket/tls.rs new file mode 100644 index 0000000..3828b29 --- /dev/null +++ b/aquatic_http_private/src/workers/socket/tls.rs @@ -0,0 +1,151 @@ +//! hyper/rustls integration +//! +//! hyper will automatically use HTTP/2 if a client starts talking HTTP/2, +//! otherwise HTTP/1.1 will be used. +//! +//! Based on https://github.com/rustls/hyper-rustls/blob/9b7b1220f74de9b249ce2b8f8b922fd00074c53b/examples/server.rs + +// ISC License (ISC) +// Copyright (c) 2016, Joseph Birr-Pixton +// +// Permission to use, copy, modify, and/or distribute this software for +// any purpose with or without fee is hereby granted, provided that the +// above copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +// DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +// PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +// THIS SOFTWARE. + +use core::task::{Context, Poll}; +use futures_util::ready; +use hyper::server::accept::Accept; +use hyper::server::conn::{AddrIncoming, AddrStream}; +use std::future::Future; +use std::io; +use std::net::SocketAddr; +use std::pin::Pin; +use std::sync::Arc; +use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; +use tokio_rustls::rustls::ServerConfig; + +enum State { + Handshaking(tokio_rustls::Accept, SocketAddr), + Streaming(tokio_rustls::server::TlsStream), +} + +// tokio_rustls::server::TlsStream doesn't expose constructor methods, +// so we have to TlsAcceptor::accept and handshake to have access to it +// TlsStream implements AsyncRead/AsyncWrite handshaking tokio_rustls::Accept first +pub struct TlsStream { + state: State, +} + +impl TlsStream { + fn new(stream: AddrStream, config: Arc) -> TlsStream { + let remote_addr = stream.remote_addr(); + let accept = tokio_rustls::TlsAcceptor::from(config).accept(stream); + + TlsStream { + state: State::Handshaking(accept, remote_addr), + } + } + + pub fn get_remote_addr(&self) -> SocketAddr { + match &self.state { + State::Handshaking(_, remote_addr) => *remote_addr, + State::Streaming(stream) => stream.get_ref().0.remote_addr(), + } + } +} + +impl AsyncRead for TlsStream { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context, + buf: &mut ReadBuf, + ) -> Poll> { + let pin = self.get_mut(); + match pin.state { + State::Handshaking(ref mut accept, ref mut socket_addr) => { + match ready!(Pin::new(accept).poll(cx)) { + Ok(mut stream) => { + *socket_addr = stream.get_ref().0.remote_addr(); + let result = Pin::new(&mut stream).poll_read(cx, buf); + pin.state = State::Streaming(stream); + result + } + Err(err) => Poll::Ready(Err(err)), + } + } + State::Streaming(ref mut stream) => Pin::new(stream).poll_read(cx, buf), + } + } +} + +impl AsyncWrite for TlsStream { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + let pin = self.get_mut(); + match pin.state { + State::Handshaking(ref mut accept, _) => match ready!(Pin::new(accept).poll(cx)) { + Ok(mut stream) => { + let result = Pin::new(&mut stream).poll_write(cx, buf); + pin.state = State::Streaming(stream); + result + } + Err(err) => Poll::Ready(Err(err)), + }, + State::Streaming(ref mut stream) => Pin::new(stream).poll_write(cx, buf), + } + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.state { + State::Handshaking(_, _) => Poll::Ready(Ok(())), + State::Streaming(ref mut stream) => Pin::new(stream).poll_flush(cx), + } + } + + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.state { + State::Handshaking(_, _) => Poll::Ready(Ok(())), + State::Streaming(ref mut stream) => Pin::new(stream).poll_shutdown(cx), + } + } +} + +pub struct TlsAcceptor { + config: Arc, + incoming: AddrIncoming, +} + +impl TlsAcceptor { + pub fn new(config: Arc, incoming: AddrIncoming) -> TlsAcceptor { + TlsAcceptor { config, incoming } + } +} + +impl Accept for TlsAcceptor { + type Conn = TlsStream; + type Error = io::Error; + + fn poll_accept( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll>> { + let pin = self.get_mut(); + match ready!(Pin::new(&mut pin.incoming).poll_accept(cx)) { + Some(Ok(sock)) => Poll::Ready(Some(Ok(TlsStream::new(sock, pin.config.clone())))), + Some(Err(e)) => Poll::Ready(Some(Err(e))), + None => Poll::Ready(None), + } + } +} From 05faa10f4b479850b3892ed1e02336a99e527071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:08:20 +0200 Subject: [PATCH 33/62] http load test: on response deserialize failure, print headers too --- aquatic_http_load_test/src/network.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/aquatic_http_load_test/src/network.rs b/aquatic_http_load_test/src/network.rs index fdae866..eb0a8b4 100644 --- a/aquatic_http_load_test/src/network.rs +++ b/aquatic_http_load_test/src/network.rs @@ -213,9 +213,7 @@ impl Connection { } if let Some(body_start_index) = opt_body_start_index { - let interesting_bytes = &interesting_bytes[body_start_index..]; - - match Response::from_bytes(interesting_bytes) { + match Response::from_bytes(&interesting_bytes[body_start_index..]) { Ok(response) => { match response { Response::Announce(_) => { From b2a3c034b0932100b5a7d081247804988bb02655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:17:57 +0200 Subject: [PATCH 34/62] http_protocol: allow announce/scrape url suffix; use in load test --- aquatic_http_load_test/src/config.rs | 3 +++ aquatic_http_load_test/src/network.rs | 2 +- aquatic_http_protocol/src/request.rs | 18 +++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/aquatic_http_load_test/src/config.rs b/aquatic_http_load_test/src/config.rs index 6f88e79..a581e89 100644 --- a/aquatic_http_load_test/src/config.rs +++ b/aquatic_http_load_test/src/config.rs @@ -18,6 +18,8 @@ pub struct Config { /// opened as quickly as possible, which is useful when the tracker /// does not keep connections alive. pub connection_creation_interval_ms: u64, + /// Announce/scrape url suffix. Use `/my_token/` to get `/announce/my_token/` + pub url_suffix: String, pub duration: usize, pub torrents: TorrentConfig, #[cfg(feature = "cpu-pinning")] @@ -56,6 +58,7 @@ impl Default for Config { num_workers: 1, num_connections: 128, connection_creation_interval_ms: 10, + url_suffix: "".into(), duration: 0, torrents: TorrentConfig::default(), #[cfg(feature = "cpu-pinning")] diff --git a/aquatic_http_load_test/src/network.rs b/aquatic_http_load_test/src/network.rs index eb0a8b4..a8fc57a 100644 --- a/aquatic_http_load_test/src/network.rs +++ b/aquatic_http_load_test/src/network.rs @@ -135,7 +135,7 @@ impl Connection { let request = create_random_request(&self.config, &self.load_test_state, &mut self.rng); - request.write(&mut self.tls.writer())?; + request.write(&mut self.tls.writer(), self.config.url_suffix.as_bytes())?; self.queued_responses += 1; self.send_new_request = false; diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 7f29cf7..1934575 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -22,8 +22,10 @@ pub struct AnnounceRequest { } impl AnnounceRequest { - fn write(&self, output: &mut W) -> ::std::io::Result<()> { - output.write_all(b"GET /announce?info_hash=")?; + fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { + output.write_all(b"GET /announce")?; + output.write_all(url_suffix)?; + output.write_all(b"?info_hash=")?; urlencode_20_bytes(self.info_hash.0, output)?; output.write_all(b"&peer_id=")?; @@ -167,8 +169,10 @@ pub struct ScrapeRequest { } impl ScrapeRequest { - fn write(&self, output: &mut W) -> ::std::io::Result<()> { + fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { output.write_all(b"GET /scrape?")?; + output.write_all(url_suffix)?; + output.write_all(b"?")?; let mut first = true; @@ -307,10 +311,10 @@ impl Request { } } - pub fn write(&self, output: &mut W) -> ::std::io::Result<()> { + pub fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { match self { - Self::Announce(r) => r.write(output), - Self::Scrape(r) => r.write(output), + Self::Announce(r) => r.write(output, url_suffix), + Self::Scrape(r) => r.write(output, url_suffix), } } } @@ -436,7 +440,7 @@ mod tests { let mut bytes = Vec::new(); - request.write(&mut bytes).unwrap(); + request.write(&mut bytes, &[]).unwrap(); let parsed_request = Request::from_bytes(&bytes[..]).unwrap(); From 26cd34f10af4eef8e57a8d05d28ea8078ceb976e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:20:17 +0200 Subject: [PATCH 35/62] http_private: add config field db_connections_per_worker --- aquatic_http_private/src/config.rs | 2 ++ aquatic_http_private/src/workers/socket/mod.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/aquatic_http_private/src/config.rs b/aquatic_http_private/src/config.rs index 3d38aef..ce558a0 100644 --- a/aquatic_http_private/src/config.rs +++ b/aquatic_http_private/src/config.rs @@ -18,6 +18,7 @@ pub struct Config { /// generate responses and send them back to the socket workers. pub request_workers: usize, pub worker_channel_size: usize, + pub db_connections_per_worker: u32, pub log_level: LogLevel, pub network: NetworkConfig, pub protocol: ProtocolConfig, @@ -31,6 +32,7 @@ impl Default for Config { socket_workers: 1, request_workers: 1, worker_channel_size: 128, + db_connections_per_worker: 1, log_level: LogLevel::default(), network: NetworkConfig::default(), protocol: ProtocolConfig::default(), diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index d94e3f8..9659874 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -53,7 +53,7 @@ async fn run_app( ); let pool = MySqlPoolOptions::new() - .max_connections(5) + .max_connections(config.db_connections_per_worker) .connect(&db_url) .await?; From bf4b32748bd4425c162916cda1a9c0c4e0299a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:30:43 +0200 Subject: [PATCH 36/62] http_private: add keep_alive options --- aquatic_http_private/src/config.rs | 2 ++ aquatic_http_private/src/workers/socket/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/aquatic_http_private/src/config.rs b/aquatic_http_private/src/config.rs index ce558a0..094c15e 100644 --- a/aquatic_http_private/src/config.rs +++ b/aquatic_http_private/src/config.rs @@ -57,6 +57,7 @@ pub struct NetworkConfig { pub tls_certificate_path: PathBuf, /// Path to TLS private key (DER-encoded ASN.1 in PKCS#8 or PKCS#1 format) pub tls_private_key_path: PathBuf, + pub keep_alive: bool, } impl Default for NetworkConfig { @@ -65,6 +66,7 @@ impl Default for NetworkConfig { address: SocketAddr::from(([0, 0, 0, 0], 3000)), tls_certificate_path: "".into(), tls_private_key_path: "".into(), + keep_alive: true, } } } diff --git a/aquatic_http_private/src/workers/socket/mod.rs b/aquatic_http_private/src/workers/socket/mod.rs index 9659874..2b142c7 100644 --- a/aquatic_http_private/src/workers/socket/mod.rs +++ b/aquatic_http_private/src/workers/socket/mod.rs @@ -59,12 +59,12 @@ async fn run_app( let app = Router::new() .route("/announce/:user_token/", get(routes::announce)) - .layer(Extension(Arc::new(config))) + .layer(Extension(Arc::new(config.clone()))) .layer(Extension(pool)) .layer(Extension(Arc::new(request_sender))); axum::Server::builder(tls_acceptor) - .http1_keepalive(false) + .http1_keepalive(config.network.keep_alive) .serve(app.into_make_service_with_connect_info::()) .await?; From 610057a23158a268b1216aa900575f7b6b24e60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:43:44 +0200 Subject: [PATCH 37/62] http: use create_rustls_config from aquatic_common --- aquatic_http/Cargo.toml | 2 +- aquatic_http/src/common.rs | 2 -- aquatic_http/src/lib.rs | 43 +++++------------------------- aquatic_http/src/workers/socket.rs | 5 ++-- 4 files changed, 11 insertions(+), 41 deletions(-) diff --git a/aquatic_http/Cargo.toml b/aquatic_http/Cargo.toml index 86b4b5a..1cd7f3f 100644 --- a/aquatic_http/Cargo.toml +++ b/aquatic_http/Cargo.toml @@ -20,7 +20,7 @@ cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" +aquatic_common = { version = "0.2.0", features = ["rustls-config"] } aquatic_http_protocol = "0.2.0" aquatic_toml_config = "0.2.0" diff --git a/aquatic_http/src/common.rs b/aquatic_http/src/common.rs index 5bfa9b1..8088f03 100644 --- a/aquatic_http/src/common.rs +++ b/aquatic_http/src/common.rs @@ -10,8 +10,6 @@ use aquatic_http_protocol::{ response::{AnnounceResponse, ScrapeResponse}, }; -pub type TlsConfig = futures_rustls::rustls::ServerConfig; - #[derive(Copy, Clone, Debug)] pub struct ConsumerId(pub usize); diff --git a/aquatic_http/src/lib.rs b/aquatic_http/src/lib.rs index b484a53..0f92da5 100644 --- a/aquatic_http/src/lib.rs +++ b/aquatic_http/src/lib.rs @@ -2,15 +2,12 @@ use aquatic_common::cpu_pinning::{pin_current_if_configured_to, WorkerIndex}; use aquatic_common::{ access_list::update_access_list, privileges::drop_privileges_after_socket_binding, + rustls_config::create_rustls_config, }; -use common::{State, TlsConfig}; +use common::State; use glommio::{channels::channel_mesh::MeshBuilder, prelude::*}; use signal_hook::{consts::SIGUSR1, iterator::Signals}; -use std::{ - fs::File, - io::BufReader, - sync::{atomic::AtomicUsize, Arc}, -}; +use std::sync::{atomic::AtomicUsize, Arc}; use crate::config::Config; @@ -64,7 +61,10 @@ pub fn run_inner(config: Config, state: State) -> anyhow::Result<()> { let num_bound_sockets = Arc::new(AtomicUsize::new(0)); - let tls_config = Arc::new(create_tls_config(&config).unwrap()); + let tls_config = Arc::new(create_rustls_config( + &config.network.tls_certificate_path, + &config.network.tls_private_key_path, + )?); let mut executors = Vec::new(); @@ -151,32 +151,3 @@ pub fn run_inner(config: Config, state: State) -> anyhow::Result<()> { Ok(()) } - -fn create_tls_config(config: &Config) -> anyhow::Result { - let certs = { - let f = File::open(&config.network.tls_certificate_path)?; - let mut f = BufReader::new(f); - - rustls_pemfile::certs(&mut f)? - .into_iter() - .map(|bytes| futures_rustls::rustls::Certificate(bytes)) - .collect() - }; - - let private_key = { - let f = File::open(&config.network.tls_private_key_path)?; - let mut f = BufReader::new(f); - - rustls_pemfile::pkcs8_private_keys(&mut f)? - .first() - .map(|bytes| futures_rustls::rustls::PrivateKey(bytes.clone())) - .ok_or(anyhow::anyhow!("No private keys in file"))? - }; - - let tls_config = futures_rustls::rustls::ServerConfig::builder() - .with_safe_defaults() - .with_no_client_auth() - .with_single_cert(certs, private_key)?; - - Ok(tls_config) -} diff --git a/aquatic_http/src/workers/socket.rs b/aquatic_http/src/workers/socket.rs index 56e91bd..3992551 100644 --- a/aquatic_http/src/workers/socket.rs +++ b/aquatic_http/src/workers/socket.rs @@ -7,6 +7,7 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache}; +use aquatic_common::rustls_config::RustlsConfig; use aquatic_common::CanonicalSocketAddr; use aquatic_http_protocol::common::InfoHash; use aquatic_http_protocol::request::{Request, RequestParseError, ScrapeRequest}; @@ -54,7 +55,7 @@ struct ConnectionReference { pub async fn run_socket_worker( config: Config, state: State, - tls_config: Arc, + tls_config: Arc, request_mesh_builder: MeshBuilder, response_mesh_builder: MeshBuilder, num_bound_sockets: Arc, @@ -195,7 +196,7 @@ impl Connection { response_receiver: LocalReceiver, response_consumer_id: ConsumerId, connection_id: ConnectionId, - tls_config: Arc, + tls_config: Arc, connection_slab: Rc>>, stream: TcpStream, ) -> anyhow::Result<()> { From 58ac5e7fe8a8e3f3430e9d908bbb52ab67c67e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:46:05 +0200 Subject: [PATCH 38/62] ws: use create_rustls_config from aquatic_common --- aquatic_ws/Cargo.toml | 2 +- aquatic_ws/src/common.rs | 2 -- aquatic_ws/src/lib.rs | 37 +++++--------------------------- aquatic_ws/src/workers/socket.rs | 5 +++-- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/aquatic_ws/Cargo.toml b/aquatic_ws/Cargo.toml index af02221..c1e1b70 100644 --- a/aquatic_ws/Cargo.toml +++ b/aquatic_ws/Cargo.toml @@ -21,7 +21,7 @@ cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" +aquatic_common = { version = "0.2.0", features = ["rustls-config"] } aquatic_toml_config = "0.2.0" aquatic_ws_protocol = "0.2.0" diff --git a/aquatic_ws/src/common.rs b/aquatic_ws/src/common.rs index 2d2f834..006ceb8 100644 --- a/aquatic_ws/src/common.rs +++ b/aquatic_ws/src/common.rs @@ -5,8 +5,6 @@ use aquatic_common::CanonicalSocketAddr; pub use aquatic_common::ValidUntil; -pub type TlsConfig = futures_rustls::rustls::ServerConfig; - #[derive(Default, Clone)] pub struct State { pub access_list: Arc, diff --git a/aquatic_ws/src/lib.rs b/aquatic_ws/src/lib.rs index 9e3deab..ad8028d 100644 --- a/aquatic_ws/src/lib.rs +++ b/aquatic_ws/src/lib.rs @@ -2,10 +2,9 @@ pub mod common; pub mod config; pub mod workers; -use std::fs::File; -use std::io::BufReader; use std::sync::{atomic::AtomicUsize, Arc}; +use aquatic_common::rustls_config::create_rustls_config; use glommio::{channels::channel_mesh::MeshBuilder, prelude::*}; use signal_hook::{consts::SIGUSR1, iterator::Signals}; @@ -63,7 +62,10 @@ fn run_workers(config: Config, state: State) -> anyhow::Result<()> { let num_bound_sockets = Arc::new(AtomicUsize::new(0)); - let tls_config = Arc::new(create_tls_config(&config).unwrap()); + let tls_config = Arc::new(create_rustls_config( + &config.network.tls_certificate_path, + &config.network.tls_private_key_path, + )?); let mut executors = Vec::new(); @@ -150,32 +152,3 @@ fn run_workers(config: Config, state: State) -> anyhow::Result<()> { Ok(()) } - -fn create_tls_config(config: &Config) -> anyhow::Result { - let certs = { - let f = File::open(&config.network.tls_certificate_path)?; - let mut f = BufReader::new(f); - - rustls_pemfile::certs(&mut f)? - .into_iter() - .map(|bytes| rustls::Certificate(bytes)) - .collect() - }; - - let private_key = { - let f = File::open(&config.network.tls_private_key_path)?; - let mut f = BufReader::new(f); - - rustls_pemfile::pkcs8_private_keys(&mut f)? - .first() - .map(|bytes| rustls::PrivateKey(bytes.clone())) - .ok_or(anyhow::anyhow!("No private keys in file"))? - }; - - let tls_config = rustls::ServerConfig::builder() - .with_safe_defaults() - .with_no_client_auth() - .with_single_cert(certs, private_key)?; - - Ok(tls_config) -} diff --git a/aquatic_ws/src/workers/socket.rs b/aquatic_ws/src/workers/socket.rs index 4557f78..7c121d4 100644 --- a/aquatic_ws/src/workers/socket.rs +++ b/aquatic_ws/src/workers/socket.rs @@ -8,6 +8,7 @@ use std::sync::Arc; use std::time::{Duration, Instant}; use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache}; +use aquatic_common::rustls_config::RustlsConfig; use aquatic_common::CanonicalSocketAddr; use aquatic_ws_protocol::*; use async_tungstenite::WebSocketStream; @@ -49,7 +50,7 @@ struct ConnectionReference { pub async fn run_socket_worker( config: Config, state: State, - tls_config: Arc, + tls_config: Arc, in_message_mesh_builder: MeshBuilder<(ConnectionMeta, InMessage), Partial>, out_message_mesh_builder: MeshBuilder<(ConnectionMeta, OutMessage), Partial>, num_bound_sockets: Arc, @@ -214,7 +215,7 @@ async fn run_connection( out_message_receiver: LocalReceiver<(ConnectionMeta, OutMessage)>, out_message_consumer_id: ConsumerId, connection_id: ConnectionId, - tls_config: Arc, + tls_config: Arc, stream: TcpStream, ) -> anyhow::Result<()> { let peer_addr = stream From 5e79df8e7ea37f8c07dc205c01356e1a355f313f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 19:52:33 +0200 Subject: [PATCH 39/62] Update TODO --- TODO.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/TODO.md b/TODO.md index 4c3eec9..bb4135b 100644 --- a/TODO.md +++ b/TODO.md @@ -3,13 +3,17 @@ ## High priority * aquatic_http_private - * utf8 responses + * Test that responses are actually valid UTF-8 * stored procedure * handle/document lack of NOT NULL * event can be null * test ip format * site will likely want num_seeders and num_leechers for all torrents.. +* aquatic_http_protocol + * Implement axum IntoResponse behind feature gate + * don't require compact=1? + ## Medium priority * Use thin LTO? @@ -34,8 +38,6 @@ * add flag to print parsed config when starting * aquatic_udp - * look at proper cpu pinning (check that one thread gets bound per core) - * then consider so_attach_reuseport_cbpf * what poll event capacity is actually needed? * stagger connection cleaning intervals? * load test @@ -43,11 +45,9 @@ with probability 0.2 * aquatic_ws - * glommio - * proper cpu set pinning - * general - * large amount of temporary allocations in serialize_20_bytes, pretty many in deserialize_20_bytes + * large amount of temporary allocations in serialize_20_bytes, pretty many in deserialize_20_bytes +* so_attach_reuseport_cbpf * extract response peers: extract "one extra" to compensate for removal, of sender if present in selection? From 98e7e5cc139d64ecca10b603c9d2fc2664838a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 20:20:51 +0200 Subject: [PATCH 40/62] http_protocol: implement axum IntoResponse, use in http_private --- Cargo.lock | 1 + TODO.md | 1 - aquatic_http_private/Cargo.toml | 2 +- .../src/workers/socket/routes.rs | 47 +++------------- aquatic_http_protocol/Cargo.toml | 4 ++ aquatic_http_protocol/src/response.rs | 56 +++++++++++++++++++ 6 files changed, 70 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 399cb3a..9189991 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,6 +171,7 @@ name = "aquatic_http_protocol" version = "0.2.0" dependencies = [ "anyhow", + "axum", "bendy", "criterion", "hex", diff --git a/TODO.md b/TODO.md index bb4135b..5b6f9b6 100644 --- a/TODO.md +++ b/TODO.md @@ -11,7 +11,6 @@ * site will likely want num_seeders and num_leechers for all torrents.. * aquatic_http_protocol - * Implement axum IntoResponse behind feature gate * don't require compact=1? ## Medium priority diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index bad6901..2970534 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -12,7 +12,7 @@ name = "aquatic_http_private" [dependencies] aquatic_cli_helpers = "0.2.0" aquatic_common = { version = "0.2.0", features = ["rustls-config"] } -aquatic_http_protocol = "0.2.0" +aquatic_http_protocol = { version = "0.2.0", features = ["with-axum"] } aquatic_toml_config = "0.2.0" anyhow = "1" diff --git a/aquatic_http_private/src/workers/socket/routes.rs b/aquatic_http_private/src/workers/socket/routes.rs index 481728a..8fd139b 100644 --- a/aquatic_http_private/src/workers/socket/routes.rs +++ b/aquatic_http_private/src/workers/socket/routes.rs @@ -2,12 +2,10 @@ use aquatic_common::CanonicalSocketAddr; use axum::{ extract::{ConnectInfo, Path, RawQuery}, headers::UserAgent, - http::StatusCode, - response::IntoResponse, Extension, TypedHeader, }; use sqlx::mysql::MySqlPool; -use std::{borrow::Cow, net::SocketAddr, sync::Arc}; +use std::{net::SocketAddr, sync::Arc}; use aquatic_http_protocol::{ request::AnnounceRequest, @@ -29,11 +27,11 @@ pub async fn announce( opt_user_agent: Option>, Path(user_token): Path, RawQuery(query): RawQuery, -) -> Result { - let query = query.ok_or_else(|| create_failure_response("Empty query string"))?; +) -> Result { + let query = query.ok_or_else(|| FailureResponse::new("Empty query string"))?; let request = AnnounceRequest::from_query_string(&query) - .map_err(|_| create_failure_response("Malformed request"))?; + .map_err(|_| FailureResponse::new("Malformed request"))?; let request_worker_index = RequestWorkerIndex::from_info_hash(&config, request.info_hash); let opt_user_agent = opt_user_agent.map(|header| header.as_str().to_owned()); @@ -42,8 +40,7 @@ pub async fn announce( let (validated_request, opt_warning_message) = db::validate_announce_request(&pool, source_addr, opt_user_agent, user_token, request) - .await - .map_err(|r| create_response(Response::Failure(r)))?; + .await?; let response_receiver = request_sender .send_to(request_worker_index, validated_request, source_addr) @@ -58,39 +55,11 @@ pub async fn announce( r.warning_message = opt_warning_message; } - Ok(create_response(response)) + Ok(response) } -fn create_response(response: Response) -> axum::response::Response { - let mut response_bytes = Vec::with_capacity(128); - - response.write(&mut response_bytes).unwrap(); - - ( - StatusCode::OK, - [("Content-type", "text/plain; charset=utf-8")], - response_bytes, - ) - .into_response() -} - -fn create_failure_response>>(reason: R) -> axum::response::Response { - let mut response_bytes = Vec::with_capacity(64); - - FailureResponse::new(reason) - .write(&mut response_bytes) - .unwrap(); - - ( - StatusCode::OK, - [("Content-type", "text/plain; charset=utf-8")], - response_bytes, - ) - .into_response() -} - -fn internal_error(error: String) -> axum::response::Response { +fn internal_error(error: String) -> FailureResponse { ::log::error!("{}", error); - create_failure_response("Internal error") + FailureResponse::new("Internal error") } diff --git a/aquatic_http_protocol/Cargo.toml b/aquatic_http_protocol/Cargo.toml index 440ea54..0b31222 100644 --- a/aquatic_http_protocol/Cargo.toml +++ b/aquatic_http_protocol/Cargo.toml @@ -22,8 +22,12 @@ name = "bench_announce_response_to_bytes" path = "benches/bench_announce_response_to_bytes.rs" harness = false +[features] +with-axum = ["axum"] + [dependencies] anyhow = "1" +axum = { version = "0.5", optional = true, default-features = false } hex = { version = "0.4", default-features = false } httparse = "1" itoa = "1" diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index 0eeb7f7..baf511f 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -112,6 +112,21 @@ impl AnnounceResponse { } } +#[cfg(feature = "with-axum")] +impl axum::response::IntoResponse for AnnounceResponse { + fn into_response(self) -> axum::response::Response { + let mut response_bytes = Vec::with_capacity(128); + + self.write(&mut response_bytes).unwrap(); + + ( + [("Content-type", "text/plain; charset=utf-8")], + response_bytes, + ) + .into_response() + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ScrapeResponse { /// BTreeMap instead of HashMap since keys need to be serialized in order @@ -142,6 +157,21 @@ impl ScrapeResponse { } } +#[cfg(feature = "with-axum")] +impl axum::response::IntoResponse for ScrapeResponse { + fn into_response(self) -> axum::response::Response { + let mut response_bytes = Vec::with_capacity(128); + + self.write(&mut response_bytes).unwrap(); + + ( + [("Content-type", "text/plain; charset=utf-8")], + response_bytes, + ) + .into_response() + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FailureResponse { #[serde(rename = "failure reason")] @@ -170,6 +200,21 @@ impl FailureResponse { } } +#[cfg(feature = "with-axum")] +impl axum::response::IntoResponse for FailureResponse { + fn into_response(self) -> axum::response::Response { + let mut response_bytes = Vec::with_capacity(64); + + self.write(&mut response_bytes).unwrap(); + + ( + [("Content-type", "text/plain; charset=utf-8")], + response_bytes, + ) + .into_response() + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum Response { @@ -191,6 +236,17 @@ impl Response { } } +#[cfg(feature = "with-axum")] +impl axum::response::IntoResponse for Response { + fn into_response(self) -> axum::response::Response { + match self { + Self::Announce(r) => r.into_response(), + Self::Scrape(r) => r.into_response(), + Self::Failure(r) => r.into_response(), + } + } +} + #[cfg(test)] impl quickcheck::Arbitrary for ResponsePeer { fn arbitrary(g: &mut quickcheck::Gen) -> Self { From 77c83d21a87ca1fc5dc49df0ffe13fe930d77746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Sun, 3 Apr 2022 20:31:57 +0200 Subject: [PATCH 41/62] Update aquatic_http_private/README.md --- aquatic_http_private/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index 904897e..25a53c3 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -1,4 +1,6 @@ -# aquatic_private +# aquatic_http_private + +Work in progress. ## Setup @@ -17,7 +19,7 @@ Create stored procedure (`OR REPLACE` keeps privileges in place and is supported CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( IN p_source_ip VARBINARY(16), IN p_source_port SMALLINT UNSIGNED, - IN p_user_agent TEXT, + IN p_user_agent TEXT, -- Can be NULL IN p_user_token VARCHAR(255), IN p_info_hash CHAR(40), IN p_peer_id CHAR(40), @@ -25,9 +27,9 @@ CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( IN p_uploaded BIGINT UNSIGNED, IN p_downloaded BIGINT UNSIGNED, IN p_left BIGINT UNSIGNED, - OUT p_announce_allowed BOOLEAN, - OUT p_failure_reason TEXT, - OUT p_warning_message TEXT + OUT p_announce_allowed BOOLEAN, -- false if not set + OUT p_failure_reason TEXT, -- NULL if not set + OUT p_warning_message TEXT -- NULL if not set ) MODIFIES SQL DATA BEGIN @@ -44,7 +46,5 @@ DATABASE_URL="mysql://aquatic:aquatic@localhost/aquatic" Run application: ```sh -cargo run -p aquatic_http_private -``` - -Test by visiting `localhost:3000/announce/abcd/?info_hash=abcdeabcdeabcdeabcde&peer_id=abcdeabcdeabcdeabcde&port=1000&left=0` \ No newline at end of file +cargo run --release -p aquatic_http_private +``` \ No newline at end of file From 9fd1306b2ee063baa84a6d64e273a45bef0cc0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:04:21 +0200 Subject: [PATCH 42/62] Update http_private README --- aquatic_http_private/README.md | 80 ++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index 25a53c3..e08ca46 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -1,50 +1,96 @@ # aquatic_http_private +HTTP (over TLS) BitTorrent tracker that calls a mysql stored procedure to +determine if requests can proceed. + Work in progress. -## Setup +## Usage -Create user: +### Database setup + +* Create database (you will typically skip this step and use your own database): ```sql -CREATE DATABASE aquatic; -CREATE USER 'aquatic'@localhost IDENTIFIED BY 'aquatic'; -GRANT EXECUTE ON PROCEDURE aquatic.aquatic_announce_v1 TO 'aquatic'@localhost; -FLUSH PRIVILEGES; +CREATE DATABASE aquatic_db; ``` -Create stored procedure (`OR REPLACE` keeps privileges in place and is supported by MariaDB since 10.1.3): +* Create aquatic user (use a better password): ```sql +CREATE USER 'aquatic'@localhost IDENTIFIED BY 'aquatic_password'; +``` + +* Create stored procedure `aquatic_announce_v1`: + +```sql +-- Create stored procedure called by aquatic for each announce request. +-- +-- Set output parameter p_announce_allowed determines to true to allow announce. CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( + -- Canonical source ip address (IPv4/IPv6) IN p_source_ip VARBINARY(16), + -- Source port (not port where peer says it will accept BitTorrent requests) IN p_source_port SMALLINT UNSIGNED, - IN p_user_agent TEXT, -- Can be NULL + -- User agent (can be NULL) + IN p_user_agent TEXT, + -- User token extracted from announce url ('/announce/USER_TOKEN/) IN p_user_token VARCHAR(255), + -- Hex-encoded info hash IN p_info_hash CHAR(40), + -- Peer ID IN p_peer_id CHAR(40), + -- Event (started/stopped/completed) (can be NULL) IN p_event VARCHAR(9), + -- Bytes uploaded. Passed directly from request. IN p_uploaded BIGINT UNSIGNED, + -- Bytes downloaded. Passed directly from request. IN p_downloaded BIGINT UNSIGNED, + -- Bytes left IN p_left BIGINT UNSIGNED, - OUT p_announce_allowed BOOLEAN, -- false if not set - OUT p_failure_reason TEXT, -- NULL if not set - OUT p_warning_message TEXT -- NULL if not set + -- Return true to send annonunce response. Defaults to false if not set. + OUT p_announce_allowed BOOLEAN, + -- Optional failure reason. Defaults to NULL if not set. + OUT p_failure_reason TEXT, + -- Optional warning message. Defaults to NULL if not set. + OUT p_warning_message TEXT ) MODIFIES SQL DATA BEGIN + -- Replace with your custom code SELECT true INTO p_announce_allowed; END ``` -Create `.env` file: +* Give aquatic user permission to call stored procedure: -```sh -DATABASE_URL="mysql://aquatic:aquatic@localhost/aquatic" +```sql +GRANT EXECUTE ON PROCEDURE aquatic_db.aquatic_announce_v1 TO 'aquatic'@localhost; +FLUSH PRIVILEGES; ``` -Run application: +`CREATE OR REPLACE PROCEDURE` command, which leaves privileges in place, +requires MariaDB 10.1.3 or later. If your database does not support it, +each time you want to replace the procedure, you need to drop it, then +create it using `CREATE PROCEDURE` and grant execution privileges again. + +### Tracker setup + +* Install rust compiler and cmake + +* Create `.env` file with database credentials: ```sh -cargo run --release -p aquatic_http_private -``` \ No newline at end of file +DATABASE_URL="mysql://aquatic:aquatic_password@localhost/aquatic_db" +``` + +* Build and run tracker: + +```sh +# Build +cargo build --release -p aquatic_http_private +# Generate config file (remember to set paths to TLS cert and key) +./target/release/aquatic_http_private -p > http-private-config.toml +# Run tracker +./target/release/aquatic_http_private -c http-private-config.toml +``` From 1cdd5bde5b17b67cb521d4e898d1cb12c7157d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:15:27 +0200 Subject: [PATCH 43/62] http_private: stored procedure: use VARBINARY(20) for peer_id --- aquatic_http_private/README.md | 4 ++-- aquatic_http_private/src/workers/socket/db.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index e08ca46..1301fb7 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -38,8 +38,8 @@ CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( IN p_user_token VARCHAR(255), -- Hex-encoded info hash IN p_info_hash CHAR(40), - -- Peer ID - IN p_peer_id CHAR(40), + -- Peer ID. VARBINARY since it can be any bytes according to spec. + IN p_peer_id VARBINARY(20), -- Event (started/stopped/completed) (can be NULL) IN p_event VARCHAR(9), -- Bytes uploaded. Passed directly from request. diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index ffa6b3a..71c6909 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -2,7 +2,7 @@ use std::net::IpAddr; use aquatic_common::CanonicalSocketAddr; use aquatic_http_protocol::{ - common::AnnounceEvent, request::AnnounceRequest, response::FailureResponse, + common::{AnnounceEvent, PeerId}, request::AnnounceRequest, response::FailureResponse, }; use sqlx::{Executor, MySql, Pool}; @@ -22,7 +22,7 @@ struct AnnounceProcedureParameters { user_agent: Option, user_token: String, info_hash: String, - peer_id: String, + peer_id: PeerId, event: AnnounceEvent, uploaded: u64, downloaded: u64, @@ -42,7 +42,7 @@ impl AnnounceProcedureParameters { user_agent, user_token, info_hash: hex::encode(request.info_hash.0), - peer_id: hex::encode(request.peer_id.0), + peer_id: request.peer_id, event: request.event, uploaded: request.bytes_uploaded as u64, downloaded: request.bytes_downloaded as u64, @@ -127,7 +127,7 @@ async fn call_announce_procedure( .bind(parameters.user_agent) .bind(parameters.user_token) .bind(parameters.info_hash) - .bind(parameters.peer_id) + .bind(¶meters.peer_id.0[..]) .bind(parameters.event.as_str()) .bind(parameters.uploaded) .bind(parameters.downloaded) From 92b62e73cae81b2ff8c64d7c48b58114b0c7aae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:20:43 +0200 Subject: [PATCH 44/62] http_protocol: in AnnounceRequest::write, send uploaded & downloaded --- aquatic_http_protocol/src/request.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 1934575..bffc664 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -34,7 +34,13 @@ impl AnnounceRequest { output.write_all(b"&port=")?; output.write_all(itoa::Buffer::new().format(self.port).as_bytes())?; - output.write_all(b"&uploaded=0&downloaded=0&left=")?; + output.write_all(b"&uploaded=")?; + output.write_all(itoa::Buffer::new().format(self.bytes_uploaded).as_bytes())?; + + output.write_all(b"&downloaded=")?; + output.write_all(itoa::Buffer::new().format(self.bytes_downloaded).as_bytes())?; + + output.write_all(b"&left=")?; output.write_all(itoa::Buffer::new().format(self.bytes_left).as_bytes())?; match self.event { From 6eb1375e4e6dccfd6a70d75ac74f8c7fc572b2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:28:48 +0200 Subject: [PATCH 45/62] http_protocol: skip serializing AnnounceResponse.warning_message if None --- aquatic_http_protocol/src/response.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index baf511f..36cdc30 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -51,7 +51,7 @@ pub struct AnnounceResponse { pub peers: ResponsePeerListV4, #[serde(default)] pub peers6: ResponsePeerListV6, - #[serde(rename = "warning message")] + #[serde(rename = "warning message", skip_serializing_if = "Option::is_none")] pub warning_message: Option, } From b604bd4b0a647743c9071d480bdf6f87214372a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:42:09 +0200 Subject: [PATCH 46/62] http_private: remove AnnounceProcedureParameters struct --- aquatic_http_private/src/workers/socket/db.rs | 71 +++++-------------- 1 file changed, 17 insertions(+), 54 deletions(-) diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index 71c6909..6e7de4d 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -1,9 +1,7 @@ use std::net::IpAddr; use aquatic_common::CanonicalSocketAddr; -use aquatic_http_protocol::{ - common::{AnnounceEvent, PeerId}, request::AnnounceRequest, response::FailureResponse, -}; +use aquatic_http_protocol::{request::AnnounceRequest, response::FailureResponse}; use sqlx::{Executor, MySql, Pool}; #[derive(Debug)] @@ -15,42 +13,6 @@ impl Into for ValidatedAnnounceRequest { } } -#[derive(Debug)] -struct AnnounceProcedureParameters { - source_ip: IpAddr, - source_port: u16, - user_agent: Option, - user_token: String, - info_hash: String, - peer_id: PeerId, - event: AnnounceEvent, - uploaded: u64, - downloaded: u64, - left: u64, -} - -impl AnnounceProcedureParameters { - fn new( - source_addr: CanonicalSocketAddr, - user_agent: Option, - user_token: String, // FIXME: length - request: &AnnounceRequest, - ) -> Self { - Self { - source_ip: source_addr.get().ip(), - source_port: source_addr.get().port(), - user_agent, - user_token, - info_hash: hex::encode(request.info_hash.0), - peer_id: request.peer_id, - event: request.event, - uploaded: request.bytes_uploaded as u64, - downloaded: request.bytes_downloaded as u64, - left: request.bytes_left as u64, - } - } -} - #[derive(Debug, sqlx::FromRow)] struct AnnounceProcedureResults { announce_allowed: bool, @@ -65,10 +27,7 @@ pub async fn validate_announce_request( user_token: String, request: AnnounceRequest, ) -> Result<(ValidatedAnnounceRequest, Option), FailureResponse> { - let parameters = - AnnounceProcedureParameters::new(source_addr, user_agent, user_token, &request); - - match call_announce_procedure(pool, parameters).await { + match call_announce_procedure(pool, source_addr, user_agent, user_token, &request).await { Ok(results) => { if results.announce_allowed { Ok((ValidatedAnnounceRequest(request), results.warning_message)) @@ -90,9 +49,13 @@ pub async fn validate_announce_request( async fn call_announce_procedure( pool: &Pool, - parameters: AnnounceProcedureParameters, + source_addr: CanonicalSocketAddr, + user_agent: Option, + user_token: String, // FIXME: length + request: &AnnounceRequest, ) -> anyhow::Result { - let source_ip_bytes: Vec = match parameters.source_ip { + let source_addr = source_addr.get(); + let source_ip_bytes: Vec = match source_addr.ip() { IpAddr::V4(ip) => ip.octets().into(), IpAddr::V6(ip) => ip.octets().into(), }; @@ -123,15 +86,15 @@ async fn call_announce_procedure( ", ) .bind(source_ip_bytes) - .bind(parameters.source_port) - .bind(parameters.user_agent) - .bind(parameters.user_token) - .bind(parameters.info_hash) - .bind(¶meters.peer_id.0[..]) - .bind(parameters.event.as_str()) - .bind(parameters.uploaded) - .bind(parameters.downloaded) - .bind(parameters.left); + .bind(source_addr.port()) + .bind(user_agent) + .bind(user_token) + .bind(hex::encode(request.info_hash.0)) + .bind(&request.peer_id.0[..]) + .bind(request.event.as_str()) + .bind(request.bytes_uploaded as u64) + .bind(request.bytes_downloaded as u64) + .bind(request.bytes_left as u64); t.execute(q).await?; From 4d7ea257b8cd102044ad32653674a6d454417ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:47:49 +0200 Subject: [PATCH 47/62] http_private: do less separate queries when calling stored procedure --- aquatic_http_private/src/workers/socket/db.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index 6e7de4d..c66ba72 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -62,9 +62,15 @@ async fn call_announce_procedure( let mut t = pool.begin().await?; - t.execute("SET @p_announce_allowed = false;").await?; - t.execute("SET @p_failure_reason = NULL;").await?; - t.execute("SET @p_warning_message = NULL;").await?; + t.execute( + " + SET + @p_announce_allowed = false, + @p_failure_reason = NULL, + @p_warning_message = NULL; + ", + ) + .await?; let q = sqlx::query( " From fc159aa0a046ea63c5a415afe6db5547f9baddac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 10:55:24 +0200 Subject: [PATCH 48/62] http_private: make call_announce_procedure cleaner --- aquatic_http_private/src/workers/socket/db.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/aquatic_http_private/src/workers/socket/db.rs b/aquatic_http_private/src/workers/socket/db.rs index c66ba72..89b7396 100644 --- a/aquatic_http_private/src/workers/socket/db.rs +++ b/aquatic_http_private/src/workers/socket/db.rs @@ -54,12 +54,6 @@ async fn call_announce_procedure( user_token: String, // FIXME: length request: &AnnounceRequest, ) -> anyhow::Result { - let source_addr = source_addr.get(); - let source_ip_bytes: Vec = match source_addr.ip() { - IpAddr::V4(ip) => ip.octets().into(), - IpAddr::V6(ip) => ip.octets().into(), - }; - let mut t = pool.begin().await?; t.execute( @@ -91,8 +85,11 @@ async fn call_announce_procedure( ); ", ) - .bind(source_ip_bytes) - .bind(source_addr.port()) + .bind(match source_addr.get().ip() { + IpAddr::V4(ip) => Vec::from(ip.octets()), + IpAddr::V6(ip) => Vec::from(ip.octets()), + }) + .bind(source_addr.get().port()) .bind(user_agent) .bind(user_token) .bind(hex::encode(request.info_hash.0)) From 68fda1be4591c2faaa439fa71a4cad0cd54b9f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 11:00:25 +0200 Subject: [PATCH 49/62] http_protocol: fix failing test_announce_request_from_bytes --- aquatic_http_protocol/src/request.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index bffc664..0e9d2c0 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -331,7 +331,7 @@ mod tests { use super::*; - static ANNOUNCE_REQUEST_PATH: &str = "/announce?info_hash=%04%0bkV%3f%5cr%14%a6%b7%98%adC%c3%c9.%40%24%00%b9&peer_id=-ABC940-5ert69muw5t8&port=12345&uploaded=0&downloaded=0&left=1&numwant=0&key=4ab4b877&compact=1&supportcrypto=1&event=started"; + static ANNOUNCE_REQUEST_PATH: &str = "/announce?info_hash=%04%0bkV%3f%5cr%14%a6%b7%98%adC%c3%c9.%40%24%00%b9&peer_id=-ABC940-5ert69muw5t8&port=12345&uploaded=1&downloaded=2&left=3&numwant=0&key=4ab4b877&compact=1&supportcrypto=1&event=started"; static SCRAPE_REQUEST_PATH: &str = "/scrape?info_hash=%04%0bkV%3f%5cr%14%a6%b7%98%adC%c3%c9.%40%24%00%b9"; static REFERENCE_INFO_HASH: [u8; 20] = [ From db6f6e027c49845618bb37cbc69b6e82229721bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 11:50:42 +0200 Subject: [PATCH 50/62] http_protocol: fix AnnounceResponse::warning_message serialization --- aquatic_http_protocol/src/response.rs | 26 +++++++++++++++++++------- aquatic_http_protocol/src/utils.rs | 11 +++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index 36cdc30..49ea2cf 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -51,7 +51,12 @@ pub struct AnnounceResponse { pub peers: ResponsePeerListV4, #[serde(default)] pub peers6: ResponsePeerListV6, - #[serde(rename = "warning message", skip_serializing_if = "Option::is_none")] + // Serialize as string if Some, otherwise skip + #[serde( + rename = "warning message", + skip_serializing_if = "Option::is_none", + serialize_with = "serialize_optional_string" + )] pub warning_message: Option, } @@ -95,19 +100,19 @@ impl AnnounceResponse { bytes_written += output.write(&u128::from(peer.ip_address).to_be_bytes())?; bytes_written += output.write(&peer.port.to_be_bytes())?; } - bytes_written += output.write(b"e")?; if let Some(ref warning_message) = self.warning_message { let message_bytes = warning_message.as_bytes(); - bytes_written += output.write(b"d15:warning message")?; + bytes_written += output.write(b"15:warning message")?; bytes_written += output.write(itoa::Buffer::new().format(message_bytes.len()).as_bytes())?; bytes_written += output.write(b":")?; bytes_written += output.write(message_bytes)?; - bytes_written += output.write(b"e")?; } + bytes_written += output.write(b"e")?; + Ok(bytes_written) } } @@ -334,11 +339,18 @@ mod tests { fn test_announce_response_to_bytes(response: AnnounceResponse) -> bool { let reference = bendy::serde::to_bytes(&Response::Announce(response.clone())).unwrap(); - let mut output = Vec::new(); + let mut hand_written = Vec::new(); - response.write(&mut output).unwrap(); + response.write(&mut hand_written).unwrap(); - output == reference + let success = hand_written == reference; + + if !success { + println!("reference: {}", String::from_utf8_lossy(&reference)); + println!("hand_written: {}", String::from_utf8_lossy(&hand_written)); + } + + success } #[quickcheck] diff --git a/aquatic_http_protocol/src/utils.rs b/aquatic_http_protocol/src/utils.rs index 070e2bb..618eb02 100644 --- a/aquatic_http_protocol/src/utils.rs +++ b/aquatic_http_protocol/src/utils.rs @@ -57,6 +57,17 @@ pub fn urldecode_20_bytes(value: &str) -> anyhow::Result<[u8; 20]> { Ok(out_arr) } +#[inline] +pub fn serialize_optional_string(v: &Option, serializer: S) -> Result +where + S: Serializer, +{ + match v { + Some(s) => serializer.serialize_str(s.as_str()), + None => Err(serde::ser::Error::custom("use skip_serializing_if")), + } +} + #[inline] pub fn serialize_20_bytes(bytes: &[u8; 20], serializer: S) -> Result where From 5da1c304a35c8ab93960f48cac211d4f12689931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 11:57:40 +0200 Subject: [PATCH 51/62] http_protocol: fix ScrapeRequest::write issue --- aquatic_http_protocol/src/request.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 0e9d2c0..1566b0a 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -176,7 +176,7 @@ pub struct ScrapeRequest { impl ScrapeRequest { fn write(&self, output: &mut W, url_suffix: &[u8]) -> ::std::io::Result<()> { - output.write_all(b"GET /scrape?")?; + output.write_all(b"GET /scrape")?; output.write_all(url_suffix)?; output.write_all(b"?")?; From 61569d0f31464675936ec92671c8aaa02bfe5038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:06:27 +0200 Subject: [PATCH 52/62] http_protocol: remove charset=utf-8 from response content type We send bencode bytes. They should possibly not be sent as text at all --- aquatic_http_protocol/src/response.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index 49ea2cf..d11c448 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -125,7 +125,7 @@ impl axum::response::IntoResponse for AnnounceResponse { self.write(&mut response_bytes).unwrap(); ( - [("Content-type", "text/plain; charset=utf-8")], + [("Content-type", "text/plain")], response_bytes, ) .into_response() @@ -170,7 +170,7 @@ impl axum::response::IntoResponse for ScrapeResponse { self.write(&mut response_bytes).unwrap(); ( - [("Content-type", "text/plain; charset=utf-8")], + [("Content-type", "text/plain")], response_bytes, ) .into_response() @@ -213,7 +213,7 @@ impl axum::response::IntoResponse for FailureResponse { self.write(&mut response_bytes).unwrap(); ( - [("Content-type", "text/plain; charset=utf-8")], + [("Content-type", "text/plain")], response_bytes, ) .into_response() From 71c070cf98f6fe18d1e64aa0621bdd3d5e42fb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:07:34 +0200 Subject: [PATCH 53/62] Update TODO --- TODO.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 5b6f9b6..aa6de05 100644 --- a/TODO.md +++ b/TODO.md @@ -3,10 +3,8 @@ ## High priority * aquatic_http_private - * Test that responses are actually valid UTF-8 + * Consider not setting Content-type: text/plain for responses and send vec as default octet stream instead * stored procedure - * handle/document lack of NOT NULL - * event can be null * test ip format * site will likely want num_seeders and num_leechers for all torrents.. From 9f8f80a17bde1891b840f5f51b6c34b4a59ab025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:16:13 +0200 Subject: [PATCH 54/62] http protocol: remove AnnounceRequest::compact, fail parsing if set to 0 --- TODO.md | 3 --- aquatic_http_load_test/src/utils.rs | 1 - aquatic_http_protocol/src/request.rs | 7 ------- 3 files changed, 11 deletions(-) diff --git a/TODO.md b/TODO.md index aa6de05..a4e62ec 100644 --- a/TODO.md +++ b/TODO.md @@ -8,9 +8,6 @@ * test ip format * site will likely want num_seeders and num_leechers for all torrents.. -* aquatic_http_protocol - * don't require compact=1? - ## Medium priority * Use thin LTO? diff --git a/aquatic_http_load_test/src/utils.rs b/aquatic_http_load_test/src/utils.rs index bf4c341..c6d9e54 100644 --- a/aquatic_http_load_test/src/utils.rs +++ b/aquatic_http_load_test/src/utils.rs @@ -46,7 +46,6 @@ fn create_announce_request(config: &Config, state: &LoadTestState, rng: &mut imp event, key: None, numwant: None, - compact: true, port: rng.gen(), bytes_uploaded: 0, bytes_downloaded: 0, diff --git a/aquatic_http_protocol/src/request.rs b/aquatic_http_protocol/src/request.rs index 1566b0a..22fe7ed 100644 --- a/aquatic_http_protocol/src/request.rs +++ b/aquatic_http_protocol/src/request.rs @@ -15,7 +15,6 @@ pub struct AnnounceRequest { pub bytes_downloaded: usize, pub bytes_left: usize, pub event: AnnounceEvent, - pub compact: bool, /// Number of response peers wanted pub numwant: Option, pub key: Option>, @@ -50,9 +49,6 @@ impl AnnounceRequest { AnnounceEvent::Empty => (), }; - output.write_all(b"&compact=")?; - output.write_all(itoa::Buffer::new().format(self.compact as u8).as_bytes())?; - if let Some(numwant) = self.numwant { output.write_all(b"&numwant=")?; output.write_all(itoa::Buffer::new().format(numwant).as_bytes())?; @@ -162,7 +158,6 @@ impl AnnounceRequest { bytes_downloaded: opt_bytes_downloaded.with_context(|| "no downloaded")?, bytes_left: opt_bytes_left.with_context(|| "no left")?, event, - compact: true, numwant: opt_numwant, key: opt_key, }) @@ -352,7 +347,6 @@ mod tests { bytes_downloaded: 2, bytes_left: 3, event: AnnounceEvent::Started, - compact: true, numwant: Some(0), key: Some("4ab4b877".into()), }) @@ -400,7 +394,6 @@ mod tests { bytes_downloaded: Arbitrary::arbitrary(g), bytes_left: Arbitrary::arbitrary(g), event: Arbitrary::arbitrary(g), - compact: true, numwant: Arbitrary::arbitrary(g), key: key.map(|key| key.into()), } From 44b50204e2ecd3740a8ebb7d98e6c8cbb4a5d8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:32:42 +0200 Subject: [PATCH 55/62] Switch to thin LTO; add Cargo profile release-debug --- Cargo.toml | 13 ++++++++----- TODO.md | 2 -- scripts/run-aquatic-http-private.sh | 2 +- scripts/run-aquatic-http.sh | 2 +- scripts/run-aquatic-udp.sh | 2 +- scripts/run-aquatic-ws.sh | 2 +- scripts/run-aquatic.sh | 2 +- scripts/run-load-test-http.sh | 2 +- scripts/run-load-test-udp.sh | 2 +- scripts/run-load-test-ws.sh | 2 +- 10 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c72e55f..2ef5517 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,13 +40,16 @@ aquatic_ws_protocol = { path = "aquatic_ws_protocol" } membarrier = { git = "https://github.com/glommer/membarrier-rs.git", branch = "issue-22" } [profile.release] -debug = true -lto = true +debug = false +lto = "thin" +opt-level = 3 [profile.test] -opt-level = 3 +inherits = "release-debug" [profile.bench] +inherits = "release-debug" + +[profile.release-debug] +inherits = "release" debug = true -opt-level = 3 -lto = true diff --git a/TODO.md b/TODO.md index a4e62ec..e82210f 100644 --- a/TODO.md +++ b/TODO.md @@ -10,8 +10,6 @@ ## Medium priority -* Use thin LTO? -* Add release-debug profile? * quit whole program if any thread panics * config: fail on unrecognized keys? * Run cargo-deny in CI diff --git a/scripts/run-aquatic-http-private.sh b/scripts/run-aquatic-http-private.sh index 5f7d9d8..0a9ed31 100755 --- a/scripts/run-aquatic-http-private.sh +++ b/scripts/run-aquatic-http-private.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_http_private -- $@ +cargo run --profile "release-debug" --bin aquatic_http_private -- $@ diff --git a/scripts/run-aquatic-http.sh b/scripts/run-aquatic-http.sh index 495a259..e693fca 100755 --- a/scripts/run-aquatic-http.sh +++ b/scripts/run-aquatic-http.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_http -- $@ +cargo run --profile "release-debug" --bin aquatic_http -- $@ diff --git a/scripts/run-aquatic-udp.sh b/scripts/run-aquatic-udp.sh index 256322f..0814661 100755 --- a/scripts/run-aquatic-udp.sh +++ b/scripts/run-aquatic-udp.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_udp -- $@ +cargo run --profile "release-debug" --bin aquatic_udp -- $@ diff --git a/scripts/run-aquatic-ws.sh b/scripts/run-aquatic-ws.sh index 40be253..297c71d 100755 --- a/scripts/run-aquatic-ws.sh +++ b/scripts/run-aquatic-ws.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_ws -- $@ +cargo run --profile "release-debug" --bin aquatic_ws -- $@ diff --git a/scripts/run-aquatic.sh b/scripts/run-aquatic.sh index fac0706..1ce91c4 100755 --- a/scripts/run-aquatic.sh +++ b/scripts/run-aquatic.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic -- $@ +cargo run --profile "release-debug" --bin aquatic -- $@ diff --git a/scripts/run-load-test-http.sh b/scripts/run-load-test-http.sh index 86edc66..58bfe4e 100755 --- a/scripts/run-load-test-http.sh +++ b/scripts/run-load-test-http.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_http_load_test -- $@ \ No newline at end of file +cargo run --profile "release-debug" --bin aquatic_http_load_test -- $@ \ No newline at end of file diff --git a/scripts/run-load-test-udp.sh b/scripts/run-load-test-udp.sh index 3946878..b307628 100755 --- a/scripts/run-load-test-udp.sh +++ b/scripts/run-load-test-udp.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_udp_load_test -- $@ +cargo run --profile "release-debug" --bin aquatic_udp_load_test -- $@ diff --git a/scripts/run-load-test-ws.sh b/scripts/run-load-test-ws.sh index 823c195..79dd720 100755 --- a/scripts/run-load-test-ws.sh +++ b/scripts/run-load-test-ws.sh @@ -2,4 +2,4 @@ . ./scripts/env-native-cpu-without-avx-512 -cargo run --release --bin aquatic_ws_load_test -- $@ \ No newline at end of file +cargo run --profile "release-debug" --bin aquatic_ws_load_test -- $@ \ No newline at end of file From c18a59b0cbbc90d86a3197db59520b946b0080e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:46:42 +0200 Subject: [PATCH 56/62] Use proper workspace path declarations, remove workspace patch section --- Cargo.toml | 17 ----------------- aquatic/Cargo.toml | 8 ++++---- aquatic_cli_helpers/Cargo.toml | 2 +- aquatic_common/Cargo.toml | 2 +- aquatic_http/Cargo.toml | 8 ++++---- aquatic_http_load_test/Cargo.toml | 8 ++++---- aquatic_http_private/Cargo.toml | 8 ++++---- aquatic_udp/Cargo.toml | 8 ++++---- aquatic_udp_bench/Cargo.toml | 10 +++++----- aquatic_udp_load_test/Cargo.toml | 8 ++++---- aquatic_ws/Cargo.toml | 8 ++++---- aquatic_ws_load_test/Cargo.toml | 10 +++++----- 12 files changed, 40 insertions(+), 57 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2ef5517..0ee9fc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,23 +20,6 @@ members = [ ] [patch.crates-io] -aquatic = { path = "aquatic" } -aquatic_cli_helpers = { path = "aquatic_cli_helpers" } -aquatic_common = { path = "aquatic_common" } -aquatic_http_load_test = { path = "aquatic_http_load_test" } -aquatic_http = { path = "aquatic_http" } -aquatic_http_private = { path = "aquatic_http_private" } -aquatic_http_protocol = { path = "aquatic_http_protocol" } -aquatic_toml_config_derive = { path = "aquatic_toml_config_derive" } -aquatic_toml_config = { path = "aquatic_toml_config" } -aquatic_udp_bench = { path = "aquatic_udp_bench" } -aquatic_udp_load_test = { path = "aquatic_udp_load_test" } -aquatic_udp = { path = "aquatic_udp" } -aquatic_udp_protocol = { path = "aquatic_udp_protocol" } -aquatic_ws_load_test = { path = "aquatic_ws_load_test" } -aquatic_ws = { path = "aquatic_ws" } -aquatic_ws_protocol = { path = "aquatic_ws_protocol" } - membarrier = { git = "https://github.com/glommer/membarrier-rs.git", branch = "issue-22" } [profile.release] diff --git a/aquatic/Cargo.toml b/aquatic/Cargo.toml index f58064d..2fbe263 100644 --- a/aquatic/Cargo.toml +++ b/aquatic/Cargo.toml @@ -13,8 +13,8 @@ readme = "../README.md" name = "aquatic" [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_http = "0.2.0" -aquatic_udp = "0.2.0" -aquatic_ws = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_http = { version = "0.2.0", path = "../aquatic_http" } +aquatic_udp = { version = "0.2.0", path = "../aquatic_udp" } +aquatic_ws = { version = "0.2.0", path = "../aquatic_ws" } mimalloc = { version = "0.1", default-features = false } diff --git a/aquatic_cli_helpers/Cargo.toml b/aquatic_cli_helpers/Cargo.toml index 64f7a74..7e93b6c 100644 --- a/aquatic_cli_helpers/Cargo.toml +++ b/aquatic_cli_helpers/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/greatest-ape/aquatic" readme = "../README.md" [dependencies] -aquatic_toml_config = "0.2.0" +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } anyhow = "1" git-testament = "0.2" diff --git a/aquatic_common/Cargo.toml b/aquatic_common/Cargo.toml index 4f2b994..bb12b7f 100644 --- a/aquatic_common/Cargo.toml +++ b/aquatic_common/Cargo.toml @@ -16,7 +16,7 @@ cpu-pinning = ["hwloc", "libc"] rustls-config = ["rustls", "rustls-pemfile"] [dependencies] -aquatic_toml_config = "0.2.0" +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } ahash = "0.7" anyhow = "1" diff --git a/aquatic_http/Cargo.toml b/aquatic_http/Cargo.toml index 1cd7f3f..c654787 100644 --- a/aquatic_http/Cargo.toml +++ b/aquatic_http/Cargo.toml @@ -19,10 +19,10 @@ name = "aquatic_http" cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = { version = "0.2.0", features = ["rustls-config"] } -aquatic_http_protocol = "0.2.0" -aquatic_toml_config = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls-config"] } +aquatic_http_protocol = { version = "0.2.0", path = "../aquatic_http_protocol" } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } anyhow = "1" cfg-if = "1" diff --git a/aquatic_http_load_test/Cargo.toml b/aquatic_http_load_test/Cargo.toml index 18200ce..ca4f073 100644 --- a/aquatic_http_load_test/Cargo.toml +++ b/aquatic_http_load_test/Cargo.toml @@ -16,10 +16,10 @@ name = "aquatic_http_load_test" cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" -aquatic_http_protocol = "0.2.0" -aquatic_toml_config = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common" } +aquatic_http_protocol = { version = "0.2.0", path = "../aquatic_http_protocol" } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } anyhow = "1" futures-lite = "1" diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index 2970534..18e14c2 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -10,10 +10,10 @@ name = "aquatic_http_private" name = "aquatic_http_private" [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = { version = "0.2.0", features = ["rustls-config"] } -aquatic_http_protocol = { version = "0.2.0", features = ["with-axum"] } -aquatic_toml_config = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls-config"] } +aquatic_http_protocol = { version = "0.2.0", path = "../aquatic_http_protocol", features = ["with-axum"] } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } anyhow = "1" axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] } diff --git a/aquatic_udp/Cargo.toml b/aquatic_udp/Cargo.toml index e8b2e8c..b98e16e 100644 --- a/aquatic_udp/Cargo.toml +++ b/aquatic_udp/Cargo.toml @@ -19,10 +19,10 @@ name = "aquatic_udp" cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" -aquatic_toml_config = "0.2.0" -aquatic_udp_protocol = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common" } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } +aquatic_udp_protocol = { version = "0.2.0", path = "../aquatic_udp_protocol" } anyhow = "1" cfg-if = "1" diff --git a/aquatic_udp_bench/Cargo.toml b/aquatic_udp_bench/Cargo.toml index 6350d61..6a6e7e3 100644 --- a/aquatic_udp_bench/Cargo.toml +++ b/aquatic_udp_bench/Cargo.toml @@ -11,11 +11,11 @@ readme = "../README.md" name = "aquatic_udp_bench" [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" -aquatic_toml_config = "0.2.0" -aquatic_udp = "0.2.0" -aquatic_udp_protocol = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common" } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } +aquatic_udp = { version = "0.2.0", path = "../aquatic_udp" } +aquatic_udp_protocol = { version = "0.2.0", path = "../aquatic_udp_protocol" } anyhow = "1" crossbeam-channel = "0.5" diff --git a/aquatic_udp_load_test/Cargo.toml b/aquatic_udp_load_test/Cargo.toml index 93f5c40..50c215b 100644 --- a/aquatic_udp_load_test/Cargo.toml +++ b/aquatic_udp_load_test/Cargo.toml @@ -16,10 +16,10 @@ name = "aquatic_udp_load_test" cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" -aquatic_toml_config = "0.2.0" -aquatic_udp_protocol = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common" } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } +aquatic_udp_protocol = { version = "0.2.0", path = "../aquatic_udp_protocol" } anyhow = "1" hashbrown = "0.12" diff --git a/aquatic_ws/Cargo.toml b/aquatic_ws/Cargo.toml index c1e1b70..ee23f08 100644 --- a/aquatic_ws/Cargo.toml +++ b/aquatic_ws/Cargo.toml @@ -20,10 +20,10 @@ name = "aquatic_ws" cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] -aquatic_cli_helpers = "0.2.0" -aquatic_common = { version = "0.2.0", features = ["rustls-config"] } -aquatic_toml_config = "0.2.0" -aquatic_ws_protocol = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls-config"] } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } +aquatic_ws_protocol = { version = "0.2.0", path = "../aquatic_ws_protocol" } anyhow = "1" async-tungstenite = "0.17" diff --git a/aquatic_ws_load_test/Cargo.toml b/aquatic_ws_load_test/Cargo.toml index e6b58d4..f2d521e 100644 --- a/aquatic_ws_load_test/Cargo.toml +++ b/aquatic_ws_load_test/Cargo.toml @@ -16,13 +16,13 @@ name = "aquatic_ws_load_test" cpu-pinning = ["aquatic_common/cpu-pinning"] [dependencies] -async-tungstenite = "0.17" -aquatic_cli_helpers = "0.2.0" -aquatic_common = "0.2.0" -aquatic_toml_config = "0.2.0" -aquatic_ws_protocol = "0.2.0" +aquatic_cli_helpers = { version = "0.2.0", path = "../aquatic_cli_helpers" } +aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls-config"] } +aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" } +aquatic_ws_protocol = { version = "0.2.0", path = "../aquatic_ws_protocol" } anyhow = "1" +async-tungstenite = "0.17" futures = "0.3" futures-rustls = "0.22" glommio = "0.7" From 9dfc3a82ad4a1dac9ff7feec6767dc24fd76b440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:49:29 +0200 Subject: [PATCH 57/62] Update TODO --- TODO.md | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.md b/TODO.md index e82210f..aeb510a 100644 --- a/TODO.md +++ b/TODO.md @@ -10,6 +10,7 @@ ## Medium priority +* rename request workers to swarm workers * quit whole program if any thread panics * config: fail on unrecognized keys? * Run cargo-deny in CI From c990521b923f855fd38f0d3c2110864751d96c50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:49:35 +0200 Subject: [PATCH 58/62] Run cargo fmt --- aquatic_http_protocol/src/response.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/aquatic_http_protocol/src/response.rs b/aquatic_http_protocol/src/response.rs index d11c448..b770658 100644 --- a/aquatic_http_protocol/src/response.rs +++ b/aquatic_http_protocol/src/response.rs @@ -124,11 +124,7 @@ impl axum::response::IntoResponse for AnnounceResponse { self.write(&mut response_bytes).unwrap(); - ( - [("Content-type", "text/plain")], - response_bytes, - ) - .into_response() + ([("Content-type", "text/plain")], response_bytes).into_response() } } @@ -169,11 +165,7 @@ impl axum::response::IntoResponse for ScrapeResponse { self.write(&mut response_bytes).unwrap(); - ( - [("Content-type", "text/plain")], - response_bytes, - ) - .into_response() + ([("Content-type", "text/plain")], response_bytes).into_response() } } @@ -212,11 +204,7 @@ impl axum::response::IntoResponse for FailureResponse { self.write(&mut response_bytes).unwrap(); - ( - [("Content-type", "text/plain")], - response_bytes, - ) - .into_response() + ([("Content-type", "text/plain")], response_bytes).into_response() } } From 97317915407f2a1a98df6d871b2fb3a416e6031b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:52:50 +0200 Subject: [PATCH 59/62] Remove old nested .gitignore and Cargo.lock files --- aquatic_http_private/.gitignore | 2 - aquatic_http_private/Cargo.lock | 1664 ------------------------------- 2 files changed, 1666 deletions(-) delete mode 100644 aquatic_http_private/.gitignore delete mode 100644 aquatic_http_private/Cargo.lock diff --git a/aquatic_http_private/.gitignore b/aquatic_http_private/.gitignore deleted file mode 100644 index fedaa2b..0000000 --- a/aquatic_http_private/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target -.env diff --git a/aquatic_http_private/Cargo.lock b/aquatic_http_private/Cargo.lock deleted file mode 100644 index 919c414..0000000 --- a/aquatic_http_private/Cargo.lock +++ /dev/null @@ -1,1664 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "anyhow" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" - -[[package]] -name = "aquatic-private" -version = "0.1.0" -dependencies = [ - "anyhow", - "axum", - "dotenv", - "socket2", - "sqlx", - "tokio", -] - -[[package]] -name = "async-trait" -version = "0.1.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atoi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" -dependencies = [ - "num-traits", -] - -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.1.0", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "axum" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5611d4977882c5af1c0f7a34d51b5d87f784f86912bb543986b014ea4995ef93" -dependencies = [ - "async-trait", - "axum-core", - "bitflags", - "bytes", - "futures-util", - "headers", - "http", - "http-body", - "hyper", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "serde", - "sync_wrapper", - "tokio", - "tower", - "tower-http", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95cd109b3e93c9541dcce5b0219dcf89169dcc58c1bebed65082808324258afb" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", -] - -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - -[[package]] -name = "base64ct" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b4d9b1225d28d360ec6a231d65af1fd99a2a095154c8040689617290569c5c" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" - -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "const-oid" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" - -[[package]] -name = "crossbeam-queue" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if", - "lazy_static", -] - -[[package]] -name = "crypto-bigint" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83bd3bb4314701c568e340cd8cf78c975aa0ca79e03d3f6d1677d5b0c9c0c03" -dependencies = [ - "generic-array", - "rand_core", - "subtle", -] - -[[package]] -name = "crypto-common" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "der" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" -dependencies = [ - "const-oid", - "crypto-bigint", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] - -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", - "crypto-common", -] - -[[package]] -name = "dotenv" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", -] - -[[package]] -name = "futures-channel" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" - -[[package]] -name = "futures-intrusive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" -dependencies = [ - "futures-core", - "lock_api", - "parking_lot 0.11.2", -] - -[[package]] -name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - -[[package]] -name = "futures-task" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" - -[[package]] -name = "futures-util" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" -dependencies = [ - "futures-core", - "futures-sink", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - -[[package]] -name = "hashlink" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "headers" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" -dependencies = [ - "base64", - "bitflags", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha-1 0.10.0", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "http" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "http-range-header" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" - -[[package]] -name = "httparse" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "hyper" -version = "0.14.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" -dependencies = [ - "autocfg 1.1.0", - "hashbrown", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "itertools" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" - -[[package]] -name = "js-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] - -[[package]] -name = "libc" -version = "0.2.121" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" - -[[package]] -name = "libm" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db" - -[[package]] -name = "lock_api" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" -dependencies = [ - "autocfg 1.1.0", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "matchit" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" - -[[package]] -name = "memchr" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "mio" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", -] - -[[package]] -name = "nom" -version = "7.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint-dig" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4547ee5541c18742396ae2c895d0717d0f886d8823b8399cdaf7b07d63ad0480" -dependencies = [ - "autocfg 0.1.8", - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg 1.1.0", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" -dependencies = [ - "autocfg 1.1.0", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg 1.1.0", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.5", -] - -[[package]] -name = "parking_lot" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.2", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "paste" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" - -[[package]] -name = "pem-rfc7468" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84e93a3b1cc0510b03020f33f21e62acdde3dcaef432edc95bea377fbd4c2cd4" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "116bee8279d783c0cf370efa1a94632f2108e5ef0bb32df31f051647810a4e2c" -dependencies = [ - "der", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "pkcs8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" -dependencies = [ - "der", - "pem-rfc7468", - "pkcs1", - "spki", - "zeroize", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proc-macro2" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" -dependencies = [ - "bitflags", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "rsa" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c2603e2823634ab331437001b411b9ed11660fbc4066f3908c84a9439260d" -dependencies = [ - "byteorder", - "digest 0.9.0", - "lazy_static", - "num-bigint-dig", - "num-integer", - "num-iter", - "num-traits", - "pkcs1", - "pkcs8", - "rand", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64", - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "serde" -version = "1.0.136" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" - -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.3", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "socket2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spki" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" -dependencies = [ - "der", -] - -[[package]] -name = "sqlformat" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" -dependencies = [ - "itertools", - "nom", - "unicode_categories", -] - -[[package]] -name = "sqlx" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc15591eb44ffb5816a4a70a7efd5dd87bfd3aa84c4c200401c4396140525826" -dependencies = [ - "sqlx-core", - "sqlx-macros", -] - -[[package]] -name = "sqlx-core" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195183bf6ff8328bb82c0511a83faf60aacf75840103388851db61d7a9854ae3" -dependencies = [ - "ahash", - "atoi", - "bitflags", - "byteorder", - "bytes", - "crc", - "crossbeam-queue", - "digest 0.9.0", - "either", - "futures-channel", - "futures-core", - "futures-intrusive", - "futures-util", - "generic-array", - "hashlink", - "hex", - "indexmap", - "itoa", - "libc", - "log", - "memchr", - "num-bigint", - "once_cell", - "paste", - "percent-encoding", - "rand", - "rsa", - "rustls", - "sha-1 0.9.8", - "sha2", - "smallvec", - "sqlformat", - "sqlx-rt", - "stringprep", - "thiserror", - "tokio-stream", - "url", - "webpki", - "webpki-roots", -] - -[[package]] -name = "sqlx-macros" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee35713129561f5e55c554bba1c378e2a7e67f81257b7311183de98c50e6f94" -dependencies = [ - "dotenv", - "either", - "heck", - "once_cell", - "proc-macro2", - "quote", - "sha2", - "sqlx-core", - "sqlx-rt", - "syn", - "url", -] - -[[package]] -name = "sqlx-rt" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b555e70fbbf84e269ec3858b7a6515bcfe7a166a7cc9c636dd6efd20431678b6" -dependencies = [ - "once_cell", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "stringprep" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "syn" -version = "1.0.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "sync_wrapper" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" - -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tinyvec" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" -dependencies = [ - "bytes", - "libc", - "memchr", - "mio", - "num_cpus", - "once_cell", - "parking_lot 0.12.0", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "winapi", -] - -[[package]] -name = "tokio-macros" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" -dependencies = [ - "rustls", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-stream" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tower" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba3f3efabf7fb41fae8534fc20a817013dd1c12cb45441efb6c82e6556b4cd8" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" - -[[package]] -name = "tower-service" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" - -[[package]] -name = "tracing" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" -dependencies = [ - "cfg-if", - "log", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "unicode-bidi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" -dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" - -[[package]] -name = "web-sys" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" -dependencies = [ - "webpki", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" - -[[package]] -name = "windows_i686_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - -[[package]] -name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - -[[package]] -name = "zeroize" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d9dcec5f9b43a30d38c49f91dfedfaac384cb8f085faca366c26207dd1619" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "synstructure", -] From 292ba6f7417f448c6190a004bbc61105afdd5a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:53:26 +0200 Subject: [PATCH 60/62] Bump aquatic_http_private version to 0.2.0 to match other crates --- Cargo.lock | 2 +- aquatic_http_private/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9189991..0a8e40a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,7 +143,7 @@ dependencies = [ [[package]] name = "aquatic_http_private" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "aquatic_cli_helpers", diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index 18e14c2..4619b04 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aquatic_http_private" -version = "0.1.0" +version = "0.2.0" edition = "2021" [lib] From 4b456cc6685de7ec9b79f08f17a93ae40ca2be3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 12:55:19 +0200 Subject: [PATCH 61/62] http_private: add some Cargo.toml fields --- aquatic_http_private/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/aquatic_http_private/Cargo.toml b/aquatic_http_private/Cargo.toml index 4619b04..0d59f6a 100644 --- a/aquatic_http_private/Cargo.toml +++ b/aquatic_http_private/Cargo.toml @@ -2,6 +2,10 @@ name = "aquatic_http_private" version = "0.2.0" edition = "2021" +authors = ["Joakim FrostegĂ„rd "] +license = "Apache-2.0" +repository = "https://github.com/greatest-ape/aquatic" +keywords = ["http", "benchmark", "peer-to-peer", "torrent", "bittorrent"] [lib] name = "aquatic_http_private" From e96dd55c5d57cc6b7a9e98b0e421599668827e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Frosteg=C3=A5rd?= Date: Mon, 4 Apr 2022 13:04:59 +0200 Subject: [PATCH 62/62] http_private: use BINARY(20) for p_peer_id --- aquatic_http_private/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aquatic_http_private/README.md b/aquatic_http_private/README.md index 1301fb7..615d6b2 100644 --- a/aquatic_http_private/README.md +++ b/aquatic_http_private/README.md @@ -38,8 +38,8 @@ CREATE OR REPLACE PROCEDURE aquatic_announce_v1 ( IN p_user_token VARCHAR(255), -- Hex-encoded info hash IN p_info_hash CHAR(40), - -- Peer ID. VARBINARY since it can be any bytes according to spec. - IN p_peer_id VARBINARY(20), + -- Peer ID. BINARY since it can be any bytes according to spec. + IN p_peer_id BINARY(20), -- Event (started/stopped/completed) (can be NULL) IN p_event VARCHAR(9), -- Bytes uploaded. Passed directly from request.