Move webserver to Axum from Warp #1
474
Cargo.lock
generated
474
Cargo.lock
generated
|
@ -2,6 +2,21 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.3.12"
|
||||
|
@ -15,6 +30,17 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -32,6 +58,70 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
"bitflags",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"hyper",
|
||||
"itoa",
|
||||
"matchit",
|
||||
"memchr",
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustversion",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-core"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"mime",
|
||||
"rustversion",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
|
@ -129,7 +219,7 @@ dependencies = [
|
|||
"atty",
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"indexmap 1.8.0",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
|
@ -162,6 +252,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fern"
|
||||
version = "0.6.1"
|
||||
|
@ -239,10 +335,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.11"
|
||||
name = "gimli"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
|
||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -250,10 +352,10 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"indexmap 2.1.0",
|
||||
"slab",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tokio-util 0.7.10",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
@ -263,6 +365,12 @@ version = "0.11.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "headers"
|
||||
version = "0.3.6"
|
||||
|
@ -299,20 +407,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.6"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
|
||||
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa 1.0.1",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
|
||||
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"http",
|
||||
|
@ -321,9 +429,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.5.1"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
|
||||
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
|
||||
|
||||
[[package]]
|
||||
name = "httpdate"
|
||||
|
@ -333,9 +441,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
|||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.16"
|
||||
version = "0.14.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55"
|
||||
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
|
@ -346,9 +454,9 @@ dependencies = [
|
|||
"http-body",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
"itoa 0.4.8",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.4.10",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
@ -362,41 +470,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
"hashbrown 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
version = "0.2.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
|
@ -404,6 +507,36 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "matchit"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||
|
||||
[[package]]
|
||||
name = "maud"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0bab19cef8a7fe1c18a43e881793bfc9d4ea984befec3ae5bd0415abf3ecf00"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"http",
|
||||
"itoa",
|
||||
"maud_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maud_macros"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0be95d66c3024ffce639216058e5bae17a83ecaf266ffc6e4d060ad447c9eed2"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
|
@ -427,13 +560,21 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.3"
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys",
|
||||
]
|
||||
|
@ -468,10 +609,19 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.9.0"
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
|
@ -508,14 +658,14 @@ checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 1.0.86",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.8"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
|
@ -530,23 +680,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.36"
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.86",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.15"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
|
@ -561,22 +747,22 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.136"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.136"
|
||||
version = "1.0.193"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -585,11 +771,21 @@ version = "1.0.78"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
|
||||
dependencies = [
|
||||
"itoa 1.0.1",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
|
@ -597,7 +793,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"itoa 1.0.1",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
@ -632,14 +828,24 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
|||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.4"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -657,6 +863,23 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sync_wrapper"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
|
@ -685,32 +908,31 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.19.2"
|
||||
version = "1.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
|
||||
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"socket2 0.5.5",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.7.0"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
|
||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.39",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -738,6 +960,20 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
|
@ -747,6 +983,28 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"pin-project",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.1"
|
||||
|
@ -755,11 +1013,10 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.29"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
|
||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
|
@ -767,11 +1024,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.21"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
|
||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -791,12 +1048,14 @@ name = "udpt-rs"
|
|||
version = "3.1.2"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"axum",
|
||||
"binascii",
|
||||
"bincode",
|
||||
"chrono",
|
||||
"clap",
|
||||
"fern",
|
||||
"log",
|
||||
"maud",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
|
@ -813,6 +1072,12 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
|
@ -858,7 +1123,7 @@ dependencies = [
|
|||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"tokio-util 0.6.9",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
@ -908,43 +1173,66 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
|
|
@ -21,3 +21,5 @@ fern = "0.6"
|
|||
serde_json = "1.0"
|
||||
async-compression = {version = "^0.3.8", features = ["bzip2", "tokio"]}
|
||||
chrono = "0.4"
|
||||
maud = { version = "*", features = ["axum"] }
|
||||
axum = { version = "0.6.18", features = ["json"] }
|
||||
|
|
|
@ -68,12 +68,10 @@ impl Configuration {
|
|||
pub fn load_file(path: &str) -> Result<Configuration, ConfigError> {
|
||||
match std::fs::read(path) {
|
||||
Err(e) => Err(ConfigError::IOError(e)),
|
||||
Ok(data) => {
|
||||
match Self::load(data.as_slice()) {
|
||||
Ok(cfg) => Ok(cfg),
|
||||
Err(e) => Err(ConfigError::ParseError(e)),
|
||||
}
|
||||
}
|
||||
Ok(data) => match Self::load(data.as_slice()) {
|
||||
Ok(cfg) => Ok(cfg),
|
||||
Err(e) => Err(ConfigError::ParseError(e)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
28
src/main.rs
28
src/main.rs
|
@ -12,20 +12,18 @@ use std::process::exit;
|
|||
fn setup_logging(cfg: &Configuration) {
|
||||
let log_level = match cfg.get_log_level() {
|
||||
None => log::LevelFilter::Info,
|
||||
Some(level) => {
|
||||
match level.as_str() {
|
||||
"off" => log::LevelFilter::Off,
|
||||
"trace" => log::LevelFilter::Trace,
|
||||
"debug" => log::LevelFilter::Debug,
|
||||
"info" => log::LevelFilter::Info,
|
||||
"warn" => log::LevelFilter::Warn,
|
||||
"error" => log::LevelFilter::Error,
|
||||
_ => {
|
||||
eprintln!("udpt: unknown log level encountered '{}'", level.as_str());
|
||||
exit(-1);
|
||||
}
|
||||
Some(level) => match level.as_str() {
|
||||
"off" => log::LevelFilter::Off,
|
||||
"trace" => log::LevelFilter::Trace,
|
||||
"debug" => log::LevelFilter::Debug,
|
||||
"info" => log::LevelFilter::Info,
|
||||
"warn" => log::LevelFilter::Warn,
|
||||
"error" => log::LevelFilter::Error,
|
||||
_ => {
|
||||
eprintln!("udpt: unknown log level encountered '{}'", level.as_str());
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if let Err(err) = fern::Dispatch::new()
|
||||
|
@ -117,7 +115,9 @@ async fn main() {
|
|||
let tokens = http_cfg.get_access_tokens();
|
||||
|
||||
let server = webserver::build_server(https_tracker, tokens.clone());
|
||||
server.bind(bind_addr.parse::<std::net::SocketAddr>().unwrap()).await;
|
||||
let _ = axum::Server::bind(&bind_addr.parse::<std::net::SocketAddr>().unwrap())
|
||||
.serve(server.into_make_service())
|
||||
.await;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -240,15 +240,18 @@ impl UDPTracker {
|
|||
let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
|
||||
let mut payload = StackVec::from(&mut payload_buffer);
|
||||
|
||||
match pack_into(&mut payload, &UDPAnnounceResponse {
|
||||
header: UDPResponseHeader {
|
||||
action: Actions::Announce,
|
||||
transaction_id: packet.header.transaction_id,
|
||||
match pack_into(
|
||||
&mut payload,
|
||||
&UDPAnnounceResponse {
|
||||
header: UDPResponseHeader {
|
||||
action: Actions::Announce,
|
||||
transaction_id: packet.header.transaction_id,
|
||||
},
|
||||
seeders,
|
||||
interval: self.config.get_udp_config().get_announce_interval(),
|
||||
leechers,
|
||||
},
|
||||
seeders,
|
||||
interval: self.config.get_udp_config().get_announce_interval(),
|
||||
leechers,
|
||||
}) {
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
return;
|
||||
|
@ -290,10 +293,13 @@ impl UDPTracker {
|
|||
let mut response_buffer = [0u8; 8 + MAX_SCRAPE * 12];
|
||||
let mut response = StackVec::from(&mut response_buffer);
|
||||
|
||||
if pack_into(&mut response, &UDPResponseHeader {
|
||||
action: Actions::Scrape,
|
||||
transaction_id: header.transaction_id,
|
||||
})
|
||||
if pack_into(
|
||||
&mut response,
|
||||
&UDPResponseHeader {
|
||||
action: Actions::Scrape,
|
||||
transaction_id: header.transaction_id,
|
||||
},
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
// not much we can do...
|
||||
|
@ -331,13 +337,11 @@ impl UDPTracker {
|
|||
leechers,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
UDPScrapeResponseEntry {
|
||||
seeders: 0,
|
||||
completed: 0,
|
||||
leechers: 0,
|
||||
}
|
||||
}
|
||||
None => UDPScrapeResponseEntry {
|
||||
seeders: 0,
|
||||
completed: 0,
|
||||
leechers: 0,
|
||||
},
|
||||
};
|
||||
|
||||
if pack_into(&mut response, &result).is_err() {
|
||||
|
@ -363,7 +367,7 @@ impl UDPTracker {
|
|||
Err(err) => {
|
||||
debug!("failed to send a packet: {}", err);
|
||||
Err(err)
|
||||
},
|
||||
}
|
||||
Ok(sz) => Ok(sz),
|
||||
}
|
||||
}
|
||||
|
@ -372,10 +376,15 @@ impl UDPTracker {
|
|||
let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
|
||||
let mut payload = StackVec::from(&mut payload_buffer);
|
||||
|
||||
if pack_into(&mut payload, &UDPResponseHeader {
|
||||
transaction_id: header.transaction_id,
|
||||
action: Actions::Error,
|
||||
}).is_ok() {
|
||||
if pack_into(
|
||||
&mut payload,
|
||||
&UDPResponseHeader {
|
||||
transaction_id: header.transaction_id,
|
||||
action: Actions::Error,
|
||||
},
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
let msg_bytes = Vec::from(error_msg.as_bytes());
|
||||
payload.extend(msg_bytes);
|
||||
|
||||
|
@ -414,7 +423,10 @@ mod tests {
|
|||
|
||||
assert!(pack_into(&mut payload, &mystruct).is_ok());
|
||||
assert_eq!(payload.as_slice().len(), 16);
|
||||
assert_eq!(payload.as_slice(), &[0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0, 0, 0, 0, 0, 1, 47, 203]);
|
||||
assert_eq!(
|
||||
payload.as_slice(),
|
||||
&[0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0, 0, 0, 0, 0, 1, 47, 203]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -75,9 +75,7 @@ impl std::convert::From<&[u8]> for InfoHash {
|
|||
|
||||
impl From<[u8; 20]> for InfoHash {
|
||||
fn from(info_hash: [u8; 20]) -> Self {
|
||||
InfoHash {
|
||||
info_hash,
|
||||
}
|
||||
InfoHash { info_hash }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +217,8 @@ impl PeerId {
|
|||
impl Serialize for PeerId {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer, {
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let mut tmp = [0u8; 40];
|
||||
binascii::bin2hex(&self.0, &mut tmp).unwrap();
|
||||
let id = std::str::from_utf8(&tmp).ok();
|
||||
|
@ -272,14 +271,17 @@ impl TorrentEntry {
|
|||
let is_seeder = left == 0 && uploaded > 0;
|
||||
let mut was_seeder = false;
|
||||
let mut is_completed = left == 0 && (event as u32) == (Events::Complete as u32);
|
||||
if let Some(prev) = self.peers.insert(*peer_id, TorrentPeer {
|
||||
updated: std::time::Instant::now(),
|
||||
left,
|
||||
downloaded,
|
||||
uploaded,
|
||||
ip: *remote_address,
|
||||
event,
|
||||
}) {
|
||||
if let Some(prev) = self.peers.insert(
|
||||
*peer_id,
|
||||
TorrentPeer {
|
||||
updated: std::time::Instant::now(),
|
||||
left,
|
||||
downloaded,
|
||||
uploaded,
|
||||
ip: *remote_address,
|
||||
event,
|
||||
},
|
||||
) {
|
||||
was_seeder = prev.left == 0 && prev.uploaded > 0;
|
||||
|
||||
if is_completed && (prev.event as u32) == (Events::Complete as u32) {
|
||||
|
@ -383,7 +385,7 @@ impl TorrentTracker {
|
|||
Err(ref err) => {
|
||||
error!("failed to read lines! {}", err);
|
||||
continue;
|
||||
},
|
||||
}
|
||||
};
|
||||
let row: DatabaseRow = match serde_json::from_str(&line) {
|
||||
Ok(v) => v,
|
||||
|
@ -411,7 +413,7 @@ impl TorrentTracker {
|
|||
std::collections::btree_map::Entry::Vacant(ve) => {
|
||||
ve.insert(TorrentEntry::new());
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
std::collections::btree_map::Entry::Occupied(_entry) => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -453,9 +455,7 @@ impl TorrentTracker {
|
|||
&self, info_hash: &InfoHash, remote_addr: &std::net::SocketAddr,
|
||||
) -> Option<Vec<std::net::SocketAddr>> {
|
||||
let read_lock = self.database.torrent_peers.read().await;
|
||||
read_lock
|
||||
.get(info_hash)
|
||||
.map(|entry| entry.get_peers(remote_addr))
|
||||
read_lock.get(info_hash).map(|entry| entry.get_peers(remote_addr))
|
||||
}
|
||||
|
||||
pub async fn update_torrent_and_get_stats(
|
||||
|
@ -465,14 +465,12 @@ impl TorrentTracker {
|
|||
use std::collections::btree_map::Entry;
|
||||
let mut torrent_peers = self.database.torrent_peers.write().await;
|
||||
let torrent_entry = match torrent_peers.entry(info_hash.clone()) {
|
||||
Entry::Vacant(vacant) => {
|
||||
match self.mode {
|
||||
TrackerMode::Dynamic => vacant.insert(TorrentEntry::new()),
|
||||
_ => {
|
||||
return TorrentStats::TorrentNotRegistered;
|
||||
}
|
||||
Entry::Vacant(vacant) => match self.mode {
|
||||
TrackerMode::Dynamic => vacant.insert(TorrentEntry::new()),
|
||||
_ => {
|
||||
return TorrentStats::TorrentNotRegistered;
|
||||
}
|
||||
}
|
||||
},
|
||||
Entry::Occupied(entry) => {
|
||||
if entry.get().is_flagged() {
|
||||
return TorrentStats::TorrentFlagged;
|
||||
|
|
364
src/webserver.rs
364
src/webserver.rs
|
@ -1,42 +1,55 @@
|
|||
use crate::tracker::{InfoHash, TorrentTracker};
|
||||
use axum::extract::{Path, Query, State};
|
||||
use axum::http::{Request, StatusCode};
|
||||
use axum::middleware::{self, Next};
|
||||
use axum::response::{IntoResponse, Redirect, Response};
|
||||
use axum::Json;
|
||||
use maud::{html, Markup, DOCTYPE};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::cmp::min;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use warp::{filters, reply, reply::Reply, serve, Filter, Server};
|
||||
|
||||
fn view_root() -> impl Reply {
|
||||
warp::http::Response::builder()
|
||||
.header("Content-Type", "text/html; charset=utf-8")
|
||||
.header("Server", concat!("udpt/", env!("CARGO_PKG_VERSION"), "; https://abda.nl/"))
|
||||
.body(concat!(r#"<html>
|
||||
<head>
|
||||
<title>udpt server</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: #222;
|
||||
color: #eee;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 20%;
|
||||
max-width: 750px;
|
||||
}
|
||||
a, a:active, a:visited {
|
||||
color: lightpink;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
This server is running <a style="font-weight: bold; font-size: large" href="https://github.com/naim94a/udpt"><code>udpt</code></a>, a <a href="https://en.wikipedia.org/wiki/BitTorrent_tracker" rel="nofollow" target="_blank">BitTorrent tracker</a> based on the <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol" rel="nofollow" target="_blank">UDP</a> protocol.
|
||||
</p>
|
||||
<div style="color: grey; font-size: small; border-top: 1px solid grey; width: 75%; max-width: 300px; margin-left: auto; margin-right: auto; text-align: center; padding-top: 5px">
|
||||
udpt/"#, env!("CARGO_PKG_VERSION"), r#"<br />
|
||||
<a href="https://naim94a.github.com/udpt/">docs</a> · <a href="https://github.com/naim94a/udpt/issues">issues & PRs</a> · <a href="https://paypal.me/naim94a">donate</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>"#))
|
||||
.unwrap()
|
||||
async fn view_root() -> Markup {
|
||||
html! {
|
||||
(DOCTYPE)
|
||||
head {
|
||||
meta charset="utf-8";
|
||||
meta name="viewport" content="width=device-width, initial-scale=1";
|
||||
title { "udpt server" }
|
||||
style { "body {
|
||||
background-color: #222;
|
||||
color: #eee;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 20%;
|
||||
max-width: 750px;
|
||||
}
|
||||
a, a:active, a:visited {
|
||||
color: lightpink;
|
||||
}"}
|
||||
}
|
||||
body {
|
||||
p {
|
||||
"This server is running "
|
||||
a href="https://github.com/naim94a/udpt"
|
||||
style="font-weight: bold; font-size: large" { code { "udpt" } }
|
||||
" a "
|
||||
a
|
||||
href="https://en.wikipedia.org/wiki/BitTorrent_tracker"
|
||||
rel="nofollow"
|
||||
target="_blank" { "BitTorrent tracker" }
|
||||
" based on the "
|
||||
a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol"
|
||||
rel="nofollow" target="_blank" { "UDP" } " protocol."
|
||||
}
|
||||
div style="color: grey; font-size: small; border-top: 1px solid grey; width: 75%; max-width: 300px; margin-left: auto; margin-right: auto; text-align: center; padding-top: 5px" {
|
||||
"udpt/" (env!("CARGO_PKG_VERSION")) br;
|
||||
a href="https://naim94a.github.com/udpt/" { "docs" } " · "
|
||||
a href="https://github.com/naim94a/udpt/issues" { "issues & PRs" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
@ -46,10 +59,10 @@ struct TorrentInfoQuery {
|
|||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TorrentEntry<'a> {
|
||||
info_hash: &'a InfoHash,
|
||||
struct TorrentEntry {
|
||||
info_hash: InfoHash,
|
||||
#[serde(flatten)]
|
||||
data: &'a crate::tracker::TorrentEntry,
|
||||
data: crate::tracker::TorrentEntry,
|
||||
seeders: u32,
|
||||
leechers: u32,
|
||||
|
||||
|
@ -62,6 +75,12 @@ struct TorrentFlag {
|
|||
is_flagged: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
tracker: Arc<TorrentTracker>,
|
||||
tokens: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
#[serde(tag = "status", rename_all = "snake_case")]
|
||||
enum ActionStatus<'a> {
|
||||
|
@ -69,171 +88,120 @@ enum ActionStatus<'a> {
|
|||
Err { reason: std::borrow::Cow<'a, str> },
|
||||
}
|
||||
|
||||
impl warp::reject::Reject for ActionStatus<'static> {}
|
||||
async fn json_torrent_list(State(state): State<AppState>, limits: Query<TorrentInfoQuery>) -> Json<Vec<TorrentEntry>> {
|
||||
let offset = limits.offset.unwrap_or(0);
|
||||
let limit = min(limits.limit.unwrap_or(1000), 4000);
|
||||
|
||||
fn authenticate(tokens: HashMap<String, String>) -> impl Filter<Extract = (), Error = warp::reject::Rejection> + Clone {
|
||||
#[derive(Deserialize)]
|
||||
struct AuthToken {
|
||||
token: Option<String>,
|
||||
let db = state.tracker.get_database().await;
|
||||
let results: Vec<_> = db
|
||||
.iter()
|
||||
.map(|(k, v)| {
|
||||
let (seeders, _, leechers) = v.get_stats();
|
||||
TorrentEntry {
|
||||
info_hash: k.clone(),
|
||||
data: v.clone(),
|
||||
seeders,
|
||||
leechers,
|
||||
peers: None,
|
||||
}
|
||||
})
|
||||
.skip(offset as usize)
|
||||
.take(limit as usize)
|
||||
.collect();
|
||||
|
||||
return axum::Json(results);
|
||||
}
|
||||
|
||||
async fn json_torrent_info(
|
||||
State(state): State<AppState>, Path(info_hash): Path<InfoHash>,
|
||||
) -> Result<Json<TorrentEntry>, StatusCode> {
|
||||
let db = state.tracker.get_database().await;
|
||||
let info = match db.get(&info_hash) {
|
||||
Some(v) => v,
|
||||
None => return Err(StatusCode::NOT_FOUND),
|
||||
};
|
||||
let (seeders, _, leechers) = info.get_stats();
|
||||
|
||||
let peers: Vec<_> = info
|
||||
.get_peers_iter()
|
||||
.take(1000)
|
||||
.map(|(&peer_id, peer_info)| (peer_id, peer_info.clone()))
|
||||
.collect();
|
||||
|
||||
return Ok(axum::Json(TorrentEntry {
|
||||
info_hash,
|
||||
data: info.clone(),
|
||||
seeders,
|
||||
leechers,
|
||||
peers: Some(peers),
|
||||
}));
|
||||
}
|
||||
|
||||
async fn delete_torrent(State(state): State<AppState>, Path(info_hash): Path<InfoHash>) -> Json<ActionStatus<'static>> {
|
||||
let resp = match state.tracker.remove_torrent(&info_hash, true).await.is_ok() {
|
||||
true => ActionStatus::Ok,
|
||||
false => ActionStatus::Err {
|
||||
reason: "failed to delete torrent".into(),
|
||||
},
|
||||
};
|
||||
|
||||
axum::Json(resp)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct ModifyTorrent {
|
||||
flag: Option<bool>,
|
||||
}
|
||||
|
||||
async fn modify_torrent(
|
||||
State(state): State<AppState>, Path(info_hash): Path<InfoHash>, Json(payload): Json<ModifyTorrent>,
|
||||
) -> Json<ActionStatus<'static>> {
|
||||
let is_flagged = payload.flag.unwrap_or_default();
|
||||
let tracker = state.tracker;
|
||||
if !tracker.set_torrent_flag(&info_hash, is_flagged).await {
|
||||
if is_flagged {
|
||||
if tracker.add_torrent(&info_hash).await.is_ok() {
|
||||
tracker.set_torrent_flag(&info_hash, is_flagged).await;
|
||||
} else {
|
||||
return axum::Json(ActionStatus::Err {
|
||||
reason: "failed to flag torrent".into(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tokens: HashSet<String> = tokens.into_iter().map(|(_, v)| v).collect();
|
||||
|
||||
let tokens = Arc::new(tokens);
|
||||
warp::filters::any::any()
|
||||
.map(move || tokens.clone())
|
||||
.and(filters::query::query::<AuthToken>())
|
||||
.and_then(|tokens: Arc<HashSet<String>>, token: AuthToken| {
|
||||
async move {
|
||||
if let Some(token) = token.token {
|
||||
if tokens.contains(&token) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Err(warp::reject::custom(ActionStatus::Err {
|
||||
reason: "Access Denied".into(),
|
||||
}))
|
||||
}
|
||||
})
|
||||
.untuple_one()
|
||||
axum::Json(ActionStatus::Ok)
|
||||
}
|
||||
|
||||
pub fn build_server(
|
||||
tracker: Arc<TorrentTracker>, tokens: HashMap<String, String>,
|
||||
) -> Server<impl Filter<Extract = impl Reply> + Clone + Send + Sync + 'static> {
|
||||
let root = filters::path::end().map(view_root);
|
||||
|
||||
let t1 = tracker.clone();
|
||||
// view_torrent_list -> GET /t/?offset=:u32&limit=:u32 HTTP/1.1
|
||||
let view_torrent_list = filters::path::end()
|
||||
.and(filters::method::get())
|
||||
.and(filters::query::query())
|
||||
.map(move |limits| {
|
||||
let tracker = t1.clone();
|
||||
(limits, tracker)
|
||||
})
|
||||
.and_then(|(limits, tracker): (TorrentInfoQuery, Arc<TorrentTracker>)| {
|
||||
async move {
|
||||
let offset = limits.offset.unwrap_or(0);
|
||||
let limit = min(limits.limit.unwrap_or(1000), 4000);
|
||||
|
||||
let db = tracker.get_database().await;
|
||||
let results: Vec<_> = db
|
||||
.iter()
|
||||
.map(|(k, v)| {
|
||||
let (seeders, _, leechers) = v.get_stats();
|
||||
TorrentEntry {
|
||||
info_hash: k,
|
||||
data: v,
|
||||
seeders,
|
||||
leechers,
|
||||
peers: None,
|
||||
}
|
||||
})
|
||||
.skip(offset as usize)
|
||||
.take(limit as usize)
|
||||
.collect();
|
||||
|
||||
Result::<_, warp::reject::Rejection>::Ok(reply::json(&results))
|
||||
async fn token_auth<B>(State(state): State<AppState>, request: Request<B>, next: Next<B>) -> Response {
|
||||
let mut is_authed = false;
|
||||
let tokens: HashSet<String> = state.tokens.into_iter().map(|(_, v)| v).collect();
|
||||
if request.uri().query().is_some() {
|
||||
let query_params: Vec<&str> = request.uri().query().unwrap().split("&").collect();
|
||||
for query_param in query_params {
|
||||
let split: Vec<&str> = query_param.split("=").collect();
|
||||
let (key, value) = (split[0], split[1]);
|
||||
if key == "token" && tokens.contains(value) {
|
||||
is_authed = true;
|
||||
}
|
||||
});
|
||||
|
||||
let t2 = tracker.clone();
|
||||
// view_torrent_info -> GET /t/:infohash HTTP/*
|
||||
let view_torrent_info = filters::method::get()
|
||||
.and(filters::path::param())
|
||||
.and(filters::path::end())
|
||||
.map(move |info_hash: InfoHash| {
|
||||
let tracker = t2.clone();
|
||||
(info_hash, tracker)
|
||||
})
|
||||
.and_then(|(info_hash, tracker): (InfoHash, Arc<TorrentTracker>)| {
|
||||
async move {
|
||||
let db = tracker.get_database().await;
|
||||
let info = match db.get(&info_hash) {
|
||||
Some(v) => v,
|
||||
None => return Err(warp::reject::reject()),
|
||||
};
|
||||
let (seeders, _, leechers) = info.get_stats();
|
||||
|
||||
let peers: Vec<_> = info
|
||||
.get_peers_iter()
|
||||
.take(1000)
|
||||
.map(|(&peer_id, peer_info)| (peer_id, peer_info.clone()))
|
||||
.collect();
|
||||
|
||||
Ok(reply::json(&TorrentEntry {
|
||||
info_hash: &info_hash,
|
||||
data: info,
|
||||
seeders,
|
||||
leechers,
|
||||
peers: Some(peers),
|
||||
}))
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /t/:info_hash
|
||||
let t3 = tracker.clone();
|
||||
let delete_torrent = filters::method::delete()
|
||||
.and(filters::path::param())
|
||||
.and(filters::path::end())
|
||||
.map(move |info_hash: InfoHash| {
|
||||
let tracker = t3.clone();
|
||||
(info_hash, tracker)
|
||||
})
|
||||
.and_then(|(info_hash, tracker): (InfoHash, Arc<TorrentTracker>)| {
|
||||
async move {
|
||||
let resp = match tracker.remove_torrent(&info_hash, true).await.is_ok() {
|
||||
true => ActionStatus::Ok,
|
||||
false => {
|
||||
ActionStatus::Err {
|
||||
reason: "failed to delete torrent".into(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Result::<_, warp::Rejection>::Ok(reply::json(&resp))
|
||||
}
|
||||
});
|
||||
|
||||
let t4 = tracker;
|
||||
// add_torrent/alter: POST /t/:info_hash
|
||||
// (optional) BODY: json: {"is_flagged": boolean}
|
||||
let change_torrent = filters::method::post()
|
||||
.and(filters::path::param())
|
||||
.and(filters::path::end())
|
||||
.and(filters::body::content_length_limit(4096))
|
||||
.and(filters::body::json())
|
||||
.map(move |info_hash: InfoHash, body: Option<TorrentFlag>| {
|
||||
let tracker = t4.clone();
|
||||
(info_hash, tracker, body)
|
||||
})
|
||||
.and_then(
|
||||
|(info_hash, tracker, body): (InfoHash, Arc<TorrentTracker>, Option<TorrentFlag>)| {
|
||||
async move {
|
||||
let is_flagged = body.map(|e| e.is_flagged).unwrap_or(false);
|
||||
if !tracker.set_torrent_flag(&info_hash, is_flagged).await {
|
||||
// torrent doesn't exist, add it...
|
||||
|
||||
if is_flagged {
|
||||
if tracker.add_torrent(&info_hash).await.is_ok() {
|
||||
tracker.set_torrent_flag(&info_hash, is_flagged).await;
|
||||
} else {
|
||||
return Err(warp::reject::custom(ActionStatus::Err {
|
||||
reason: "failed to flag torrent".into(),
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result::<_, warp::Rejection>::Ok(reply::json(&ActionStatus::Ok))
|
||||
}
|
||||
},
|
||||
);
|
||||
let torrent_mgmt =
|
||||
filters::path::path("t").and(view_torrent_list.or(delete_torrent).or(view_torrent_info).or(change_torrent));
|
||||
|
||||
let server = root.or(authenticate(tokens).and(torrent_mgmt));
|
||||
|
||||
serve(server)
|
||||
}
|
||||
}
|
||||
if is_authed {
|
||||
let response = next.run(request).await;
|
||||
return response;
|
||||
}
|
||||
Redirect::to("/").into_response()
|
||||
}
|
||||
|
||||
pub fn build_server(tracker: Arc<TorrentTracker>, tokens: HashMap<String, String>) -> axum::Router {
|
||||
let state = AppState { tracker, tokens };
|
||||
|
||||
axum::Router::new()
|
||||
.route("/t", axum::routing::get(json_torrent_list))
|
||||
.route("/t/", axum::routing::get(json_torrent_list))
|
||||
.route("/t/:info_hash", axum::routing::get(json_torrent_info))
|
||||
.route("/t/:info_hash", axum::routing::delete(delete_torrent))
|
||||
.route("/t/:info_hash", axum::routing::post(modify_torrent))
|
||||
.layer(middleware::from_fn_with_state(state.clone(), token_auth))
|
||||
.route("/", axum::routing::get(view_root))
|
||||
.with_state(state)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue