diff --git a/Cargo.lock b/Cargo.lock index a96d956..d843237 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,7 +56,7 @@ dependencies = [ "flate2", "futures-core", "h2", - "http", + "http 0.2.12", "httparse", "httpdate", "itoa", @@ -92,7 +92,7 @@ checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", "cfg-if", - "http", + "http 0.2.12", "regex", "regex-lite", "serde", @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "android-tzdata" @@ -296,9 +296,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -311,43 +311,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] @@ -405,9 +405,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.4" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" dependencies = [ "async-lock", "cfg-if", @@ -594,9 +594,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "bytestring" @@ -609,9 +609,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.31" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -640,9 +640,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -674,25 +674,24 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "1.9.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -727,6 +726,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -735,9 +744,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -791,6 +800,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid", +] + [[package]] name = "der" version = "0.7.9" @@ -813,9 +832,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", @@ -875,9 +894,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -947,20 +966,32 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fern" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +checksum = "69ff9c9d5fb3e6da8ac2f77ab76fe7e8087d512ce095200f8f29ac5b656cf6dc" dependencies = [ "colored", "log", ] +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -969,9 +1000,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -994,6 +1025,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1049,9 +1095,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "cef40d21ae2c515b51041df9ed313ed21e572df340ea58a922a0aefe7e8891a1" dependencies = [ "fastrand", "futures-core", @@ -1150,7 +1196,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -1170,9 +1216,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hashlink" @@ -1234,6 +1280,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows", +] + [[package]] name = "http" version = "0.2.12" @@ -1245,6 +1302,40 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.9.5" @@ -1257,6 +1348,60 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -1280,14 +1425,143 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -1303,20 +1577,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", "serde", ] [[package]] -name = "is-terminal" -version = "0.4.13" +name = "ipnet" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" -dependencies = [ - "hermit-abi 0.4.0", - "libc", - "windows-sys 0.52.0", -] +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -1374,15 +1643,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libsqlite3-sys" @@ -1401,6 +1670,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "local-channel" version = "0.1.5" @@ -1505,6 +1780,23 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nom" version = "7.1.3" @@ -1583,6 +1875,61 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "os_info" +version = "3.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +dependencies = [ + "log", + "serde", + "windows-sys 0.52.0", +] + [[package]] name = "owning_ref" version = "0.4.1" @@ -1667,9 +2014,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -1717,9 +2064,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", @@ -1747,9 +2094,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -1817,9 +2164,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -1829,9 +2176,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1850,6 +2197,46 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + [[package]] name = "ring" version = "0.17.8" @@ -1936,9 +2323,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags", "errno", @@ -1949,9 +2336,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.15" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "once_cell", "ring", @@ -2002,32 +2389,183 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "sentry" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5484316556650182f03b43d4c746ce0e3e48074a21e2f51244b648b6542e1066" +dependencies = [ + "httpdate", + "native-tls", + "reqwest", + "sentry-backtrace", + "sentry-contexts", + "sentry-core", + "sentry-debug-images", + "sentry-panic", + "sentry-tracing", + "tokio", + "ureq", +] + +[[package]] +name = "sentry-actix" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e461c7d3a46d298b5ffc66127c1f16454dd11d3d89fcfb21023cd499d82b9a78" +dependencies = [ + "actix-web", + "futures-util", + "sentry-core", +] + +[[package]] +name = "sentry-backtrace" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40aa225bb41e2ec9d7c90886834367f560efc1af028f1c5478a6cce6a59c463a" +dependencies = [ + "backtrace", + "once_cell", + "regex", + "sentry-core", +] + +[[package]] +name = "sentry-contexts" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" +dependencies = [ + "hostname", + "libc", + "os_info", + "rustc_version", + "sentry-core", + "uname", +] + +[[package]] +name = "sentry-core" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161283cfe8e99c8f6f236a402b9ccf726b201f365988b5bb637ebca0abbd4a30" +dependencies = [ + "once_cell", + "rand", + "sentry-types", + "serde", + "serde_json", +] + +[[package]] +name = "sentry-debug-images" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc6b25e945fcaa5e97c43faee0267eebda9f18d4b09a251775d8fef1086238a" +dependencies = [ + "findshlibs", + "once_cell", + "sentry-core", +] + +[[package]] +name = "sentry-panic" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74f229c7186dd971a9491ffcbe7883544aa064d1589bd30b83fb856cd22d63" +dependencies = [ + "sentry-backtrace", + "sentry-core", +] + +[[package]] +name = "sentry-tracing" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c5faf2103cd01eeda779ea439b68c4ee15adcdb16600836e97feafab362ec" +dependencies = [ + "sentry-backtrace", + "sentry-core", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sentry-types" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d68cdf6bc41b8ff3ae2a9c4671e97426dcdd154cc1d4b6b72813f285d6b163f" +dependencies = [ + "debugid", + "hex", + "rand", + "serde", + "serde_json", + "thiserror 1.0.69", + "time", + "url", + "uuid", +] + [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -2234,7 +2772,7 @@ dependencies = [ "sha2", "smallvec", "sqlformat", - "thiserror", + "thiserror 1.0.69", "tokio", "tokio-stream", "tracing", @@ -2318,7 +2856,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 1.0.69", "tracing", "whoami", ] @@ -2356,7 +2894,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror", + "thiserror 1.0.69", "tracing", "whoami", ] @@ -2415,20 +2953,40 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.82" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -2439,18 +2997,38 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl 2.0.3", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", @@ -2498,6 +3076,16 @@ dependencies = [ "time-core", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -2515,9 +3103,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -2542,6 +3130,16 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" @@ -2632,7 +3230,7 @@ dependencies = [ [[package]] name = "torrust-actix" -version = "4.0.2" +version = "4.0.3" dependencies = [ "actix-cors", "actix-web", @@ -2654,12 +3252,14 @@ dependencies = [ "regex", "rustls", "rustls-pemfile", + "sentry", + "sentry-actix", "serde", "serde_json", "serde_millis", "sha1", "sqlx", - "thiserror", + "thiserror 2.0.3", "tokio", "tokio-shutdown", "toml 0.8.19", @@ -2668,6 +3268,12 @@ dependencies = [ "winres", ] +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.40" @@ -2698,14 +3304,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "tracing-core", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uname" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +dependencies = [ + "libc", +] + [[package]] name = "unicase" version = "2.8.0" @@ -2751,17 +3382,43 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +dependencies = [ + "base64", + "log", + "native-tls", + "once_cell", + "url", +] + [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -2770,9 +3427,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utoipa" -version = "5.1.1" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8861811f7213bb866cd02319acb69a15b0ef8ca46874e805bd92d488c779036a" +checksum = "514a48569e4e21c86d0b84b5612b5e73c0b2cf09db63260134ba426d4e8ea714" dependencies = [ "indexmap", "serde", @@ -2782,9 +3439,9 @@ dependencies = [ [[package]] name = "utoipa-gen" -version = "5.1.1" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fadf94f07d67df4b15e6490dd9a9d59d7374849413e7f137eafe52fdcbd0db5" +checksum = "5629efe65599d0ccd5d493688cbf6e03aa7c1da07fe59ff97cf5977ed0637f66" dependencies = [ "proc-macro2", "quote", @@ -2794,9 +3451,9 @@ dependencies = [ [[package]] name = "utoipa-swagger-ui" -version = "8.0.1" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a551be0331bd01a1d39f2654409ca61cb955f02dfef0fc0f7aced8b2abbc88" +checksum = "a5c80b4dd79ea382e8374d67dcce22b5c6663fa13a82ad3886441d1bbede5e35" dependencies = [ "actix-web", "mime_guess", @@ -2809,11 +3466,26 @@ dependencies = [ "zip", ] +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "serde", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "value-bag" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" +checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2" [[package]] name = "vcpkg" @@ -2837,6 +3509,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2976,6 +3657,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -2985,6 +3676,36 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3151,6 +3872,18 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "yasna" version = "0.5.2" @@ -3160,6 +3893,30 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -3181,12 +3938,55 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zip" version = "2.2.0" @@ -3200,7 +4000,7 @@ dependencies = [ "flate2", "indexmap", "memchr", - "thiserror", + "thiserror 1.0.69", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index 6030d2e..5ce9eda 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "torrust-actix" -version = "4.0.2" +version = "4.0.3" edition = "2021" license = "AGPL-3.0" authors = [ @@ -31,7 +31,7 @@ byteorder = "^1.5" chrono = "^0.4" clap = { version = "^4.5", features = ["derive"] } clap_builder = "^4.5" -fern = { version = "^0.6", features = ["colored"] } +fern = { version = "^0.7", features = ["colored"] } futures-util = "^0.3" hex = "^0.4" log = "^0.4" @@ -42,13 +42,15 @@ rcgen = "^0.13" regex = "^1.11" rustls = { version = "^0.23", default-features = false, features = ["std", "ring"] } rustls-pemfile = "^2.2" +sentry = "0.34.0" +sentry-actix = "0.34.0" serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1.0", features = ["preserve_order"] } serde_millis = "^0.1" sha1 = "^0.10" sqlx = { version = "^0.8", features = ["mysql", "postgres", "sqlite", "runtime-tokio-rustls"] } -thiserror = "^1.0" -tokio = { version = "^1.40", features = ["full"] } +thiserror = "^2.0" +tokio = { version = "^1.41", features = ["full"] } tokio-shutdown = "^0.1" toml = "^0.8" utoipa = { version = "^5", features = ["actix_extras"] } diff --git a/README.md b/README.md index 021d8cb..c9b1c09 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,11 @@ Swagger UI is introduced, and when enabled in the configuration, is accessible t ### ChangeLog +#### v4.0.3 +* Fixing announce and scrape paths, since it is the wrong way. +* Fixing various smaller bugs that isn't app-breaking, but should be handled better. +* Preparing work for version v4.1.0, which will introduce LUA support for middleware. + #### v4.0.2 * Added option that the system will remove data from database. * Added updates variables for the white/black list and keys tables. diff --git a/docker/Dockerfile b/docker/Dockerfile index 0a8fb6f..c51d1b3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,7 @@ FROM rust:alpine RUN apk add git musl-dev curl RUN git clone https://github.com/Power2All/torrust-actix.git /tmp/torrust-actix -RUN cd /tmp/torrust-actix && git checkout tags/v4.0.2 +RUN cd /tmp/torrust-actix && git checkout tags/v4.0.3 WORKDIR /tmp/torrust-actix RUN cd /tmp/torrust-actix RUN cargo build --release && rm -Rf target/release/.fingerprint target/release/build target/release/deps target/release/examples target/release/incremental diff --git a/src/api/api.rs b/src/api/api.rs index 56a25e7..c9a53ff 100644 --- a/src/api/api.rs +++ b/src/api/api.rs @@ -140,22 +140,38 @@ pub async fn api_service( exit(1); } - let key_file = &mut BufReader::new(File::open(api_server_object.ssl_key.clone().unwrap()).unwrap()); - let certs_file = &mut BufReader::new(File::open(api_server_object.ssl_cert.clone().unwrap()).unwrap()); + let key_file = &mut BufReader::new(match File::open(match api_server_object.ssl_key.clone() { + None => { panic!("[APIS] SSL key not set!"); } + Some(data) => { data } + }) { + Ok(data) => { data } + Err(data) => { panic!("[APIS] SSL key unreadable: {}", data); } + }); + let certs_file = &mut BufReader::new(match File::open(match api_server_object.ssl_cert.clone() { + None => { panic!("[APIS] SSL cert not set!"); } + Some(data) => { data } + }) { + Ok(data) => { data } + Err(data) => { panic!("[APIS] SSL cert unreadable: {}", data); } + }); - let tls_certs = rustls_pemfile::certs(certs_file).collect::, _>>().unwrap(); + let tls_certs = match rustls_pemfile::certs(certs_file).collect::, _>>() { + Ok(data) => { data } + Err(data) => { panic!("[APIS] SSL cert couldn't be extracted: {}", data); } + }; let tls_key = match rustls_pemfile::pkcs8_private_keys(key_file).next().unwrap() { - Err(_) => { exit(1); } Ok(data) => { data } + Err(data) => { panic!("[APIS] SSL key couldn't be extracted: {}", data); } }; - let tls_config = rustls::ServerConfig::builder() - .with_no_client_auth() - .with_single_cert(tls_certs, rustls::pki_types::PrivateKeyDer::Pkcs8(tls_key)) - .unwrap(); + let tls_config = match rustls::ServerConfig::builder().with_no_client_auth().with_single_cert(tls_certs, rustls::pki_types::PrivateKeyDer::Pkcs8(tls_key)) { + Ok(data) => { data } + Err(data) => { panic!("[APIS] SSL config couldn't be created: {}", data); } + }; let server = HttpServer::new(move || { App::new() + .wrap(sentry_actix::Sentry::new()) .wrap(api_service_cors()) .configure(api_service_routes(Arc::new(ApiServiceData { torrent_tracker: data.clone(), @@ -177,6 +193,7 @@ pub async fn api_service( info!("[API] Starting server listener on {}", addr); let server = HttpServer::new(move || { App::new() + .wrap(sentry_actix::Sentry::new()) .wrap(api_service_cors()) .configure(api_service_routes(Arc::new(ApiServiceData { torrent_tracker: data.clone(), diff --git a/src/config/impls/configuration.rs b/src/config/impls/configuration.rs index fe9553e..e5b5a09 100644 --- a/src/config/impls/configuration.rs +++ b/src/config/impls/configuration.rs @@ -37,6 +37,8 @@ impl Configuration { peers_cleanup_interval: Some(900), total_downloads: 0, swagger: Some(false), + sentry: Some(false), + sentry_url: None }), database: Some(DatabaseConfig { engine: Some(DatabaseDrivers::sqlite3), diff --git a/src/config/structs/tracker_config.rs b/src/config/structs/tracker_config.rs index 8d5f768..a1f07e5 100644 --- a/src/config/structs/tracker_config.rs +++ b/src/config/structs/tracker_config.rs @@ -13,5 +13,7 @@ pub struct TrackerConfig { pub peers_timeout: Option, pub peers_cleanup_interval: Option, pub total_downloads: u64, - pub swagger: Option + pub swagger: Option, + pub sentry: Option, + pub sentry_url: Option } \ No newline at end of file diff --git a/src/http/http.rs b/src/http/http.rs index bea9a6e..54b0857 100644 --- a/src/http/http.rs +++ b/src/http/http.rs @@ -42,16 +42,16 @@ pub fn http_service_routes(data: Arc) -> Box { panic!("[HTTPS] SSL key not set!"); } + Some(data) => { data } + }) { + Ok(data) => { data } + Err(data) => { panic!("[HTTPS] SSL key unreadable: {}", data); } + }); + let certs_file = &mut BufReader::new(match File::open(match http_server_object.ssl_cert.clone() { + None => { panic!("[HTTPS] SSL cert not set!"); } + Some(data) => { data } + }) { + Ok(data) => { data } + Err(data) => { panic!("[HTTPS] SSL cert unreadable: {}", data); } + }); - let tls_certs = rustls_pemfile::certs(certs_file).collect::, _>>().unwrap(); + let tls_certs = match rustls_pemfile::certs(certs_file).collect::, _>>() { + Ok(data) => { data } + Err(data) => { panic!("[HTTPS] SSL cert couldn't be extracted: {}", data); } + }; let tls_key = match rustls_pemfile::pkcs8_private_keys(key_file).next().unwrap() { - Err(_) => { exit(1); } Ok(data) => { data } + Err(data) => { panic!("[HTTPS] SSL key couldn't be extracted: {}", data); } }; - let tls_config = rustls::ServerConfig::builder() - .with_no_client_auth() - .with_single_cert(tls_certs, rustls::pki_types::PrivateKeyDer::Pkcs8(tls_key)) - .unwrap(); + let tls_config = match rustls::ServerConfig::builder().with_no_client_auth().with_single_cert(tls_certs, rustls::pki_types::PrivateKeyDer::Pkcs8(tls_key)) { + Ok(data) => { data } + Err(data) => { panic!("[HTTPS] SSL config couldn't be created: {}", data); } + }; let server = HttpServer::new(move || { App::new() + .wrap(sentry_actix::Sentry::new()) .wrap(http_service_cors()) .configure(http_service_routes(Arc::new(HttpServiceData { torrent_tracker: data.clone(), @@ -113,6 +129,7 @@ pub async fn http_service( info!("[HTTP] Starting server listener on {}", addr); let server = HttpServer::new(move || { App::new() + .wrap(sentry_actix::Sentry::new()) .wrap(http_service_cors()) .configure(http_service_routes(Arc::new(HttpServiceData { torrent_tracker: data.clone(), diff --git a/src/main.rs b/src/main.rs index bbd33df..297a05c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,8 +18,7 @@ use torrust_actix::stats::enums::stats_event::StatsEvent; use torrust_actix::tracker::structs::torrent_tracker::TorrentTracker; use torrust_actix::udp::udp::udp_service; -#[tokio::main] -async fn main() -> std::io::Result<()> +fn main() -> std::io::Result<()> { let args = Cli::parse(); @@ -32,312 +31,332 @@ async fn main() -> std::io::Result<()> info!("{} - Version: {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); - let tracker = Arc::new(TorrentTracker::new(config.clone(), args.create_database).await); - - if tracker.config.database.clone().unwrap().persistent { - tracker.load_torrents(tracker.clone()).await; - if tracker.config.tracker_config.clone().unwrap().whitelist_enabled.unwrap() { - tracker.load_whitelist(tracker.clone()).await; - } - if tracker.config.tracker_config.clone().unwrap().blacklist_enabled.unwrap() { - tracker.load_blacklist(tracker.clone()).await; - } - if tracker.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { - tracker.load_keys(tracker.clone()).await; - } - if tracker.config.tracker_config.clone().unwrap().users_enabled.unwrap() { - tracker.load_users(tracker.clone()).await; - } - if tracker.config.database.clone().unwrap().update_peers && !tracker.reset_seeds_peers(tracker.clone()).await { - panic!("[RESET SEEDS PEERS] Unable to continue loading"); - } - } else { - tracker.set_stats(StatsEvent::Completed, config.tracker_config.clone().unwrap().total_downloads as i64); - } - - if args.create_selfsigned { tracker.cert_gen(&args).await; } - - if args.export { tracker.export(&args, tracker.clone()).await; } - - if args.import { tracker.import(&args, tracker.clone()).await; } - - let tokio_shutdown = Shutdown::new().expect("shutdown creation works on first call"); - - let deadlocks_handler = tokio_shutdown.clone(); - tokio::spawn(async move { - info!("[BOOT] Starting thread for deadlocks..."); - loop { - if shutdown_waiting(Duration::from_secs(10), deadlocks_handler.clone()).await { - info!("[BOOT] Shutting down thread for deadlocks..."); - return; - } - let deadlocks = deadlock::check_deadlock(); - if deadlocks.is_empty() { - continue; - } - info!("[DEADLOCK] Found {} deadlocks", deadlocks.len()); - for (i, threads) in deadlocks.iter().enumerate() { - info!("[DEADLOCK] #{}", i); - for t in threads { - info!("[DEADLOCK] Thread ID: {:#?}", t.thread_id()); - info!("[DEADLOCK] {:#?}", t.backtrace()); - } - } - } - }); - - let mut api_handlers = Vec::new(); - let mut api_futures = Vec::new(); - let mut apis_handlers = Vec::new(); - let mut apis_futures = Vec::new(); - for api_server_object in &config.api_server { - if api_server_object.enabled { - http_check_host_and_port_used(api_server_object.bind_address.clone()); - let address: SocketAddr = api_server_object.bind_address.parse().unwrap(); - if api_server_object.ssl.unwrap() { - let (handle, https_api) = api_service( - address, - tracker.clone(), - api_server_object.clone() - ).await; - apis_handlers.push(handle); - apis_futures.push(https_api); - } else { - let (handle, http_api) = api_service( - address, - tracker.clone(), - api_server_object.clone() - ).await; - api_handlers.push(handle); - api_futures.push(http_api); + if config.tracker_config.clone().unwrap().sentry.unwrap() { + let _guard = match config.tracker_config.clone().unwrap().sentry_url { + None => { + panic!("[SENTRY] No Sentry URL set in config"); } - } - } - if !api_futures.is_empty() { - tokio::spawn(async move { - let _ = try_join_all(api_futures).await; - }); - } - if !apis_futures.is_empty() { - tokio::spawn(async move { - let _ = try_join_all(apis_futures).await; - }); - } - - let mut http_handlers = Vec::new(); - let mut http_futures = Vec::new(); - let mut https_handlers = Vec::new(); - let mut https_futures = Vec::new(); - for http_server_object in &config.http_server { - if http_server_object.enabled { - http_check_host_and_port_used(http_server_object.bind_address.clone()); - let address: SocketAddr = http_server_object.bind_address.parse().unwrap(); - if http_server_object.ssl.unwrap() { - let (handle, https_service) = http_service( - address, - tracker.clone(), - http_server_object.clone() - ).await; - https_handlers.push(handle); - https_futures.push(https_service); - } else { - let (handle, http_service) = http_service( - address, - tracker.clone(), - http_server_object.clone() - ).await; - http_handlers.push(handle); - http_futures.push(http_service); + Some(url) => { + sentry::init((url, sentry::ClientOptions { + release: sentry::release_name!(), + ..Default::default() + })) } - } + }; } - if !http_futures.is_empty() { - tokio::spawn(async move { - let _ = try_join_all(http_futures).await; - }); - } - if !https_futures.is_empty() { - tokio::spawn(async move { - let _ = try_join_all(https_futures).await; - }); - } - - let (udp_tx, udp_rx) = tokio::sync::watch::channel(false); - let mut udp_futures = Vec::new(); - for udp_server_object in &config.udp_server { - if udp_server_object.enabled { - udp_check_host_and_port_used(udp_server_object.bind_address.clone()); - let address: SocketAddr = udp_server_object.bind_address.parse().unwrap(); - let threads: u64 = match udp_server_object.threads { - None => { available_parallelism().unwrap().get() as u64 } - Some(count) => { count } - }; - let tracker_clone = tracker.clone(); - udp_futures.push(udp_service(address, threads, tracker_clone, udp_rx.clone()).await); - } - } - - let stats_handler = tokio_shutdown.clone(); - let tracker_spawn_stats = tracker.clone(); - info!("[BOOT] Starting thread for console updates with {} seconds delay...", tracker_spawn_stats.config.log_console_interval.unwrap_or(60u64)); - tokio::spawn(async move { - loop { - tracker_spawn_stats.set_stats(StatsEvent::TimestampSave, chrono::Utc::now().timestamp() + 60i64); - if shutdown_waiting(Duration::from_secs(tracker_spawn_stats.config.log_console_interval.unwrap_or(60u64)), stats_handler.clone()).await { - info!("[BOOT] Shutting down thread for console updates..."); - return; - } - - let stats = tracker_spawn_stats.get_stats(); - info!("[STATS] Torrents: {} - Updates: {} - Seeds: {} - Peers: {} - Completed: {}", stats.torrents, stats.torrents_updates, stats.seeds, stats.peers, stats.completed); - info!("[STATS] WList: {} - WList Updates: {} - BLists: {} - BLists Updates: {} - Keys: {} - Keys Updates {}", stats.whitelist, stats.whitelist_updates, stats.blacklist, stats.blacklist_updates, stats.keys, stats.keys_updates); - info!("[STATS TCP IPv4] Connect: {} - API: {} - A: {} - S: {} - F: {} - 404: {}", stats.tcp4_connections_handled, stats.tcp4_api_handled, stats.tcp4_announces_handled, stats.tcp4_scrapes_handled, stats.tcp4_failure, stats.tcp4_not_found); - info!("[STATS TCP IPv6] Connect: {} - API: {} - A: {} - S: {} - F: {} - 404: {}", stats.tcp6_connections_handled, stats.tcp6_api_handled, stats.tcp6_announces_handled, stats.tcp6_scrapes_handled, stats.tcp6_failure, stats.tcp6_not_found); - info!("[STATS UDP IPv4] Connect: {} - A: {} - S: {} - IR: {} - BR: {}", stats.udp4_connections_handled, stats.udp4_announces_handled, stats.udp4_scrapes_handled, stats.udp4_invalid_request, stats.udp4_bad_request); - info!("[STATS UDP IPv6] Connect: {} - A: {} - S: {} - IR: {} - BR: {}", stats.udp6_connections_handled, stats.udp6_announces_handled, stats.udp6_scrapes_handled, stats.udp6_invalid_request, stats.udp6_bad_request); - } - }); - - let cleanup_peers_handler = tokio_shutdown.clone(); - let tracker_spawn_cleanup_peers = tracker.clone(); - info!("[BOOT] Starting thread for peers cleanup with {} seconds delay...", tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_cleanup_interval.unwrap()); - tokio::spawn(async move { - loop { - tracker_spawn_cleanup_peers.set_stats(StatsEvent::TimestampTimeout, chrono::Utc::now().timestamp() + tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_cleanup_interval.unwrap() as i64); - if shutdown_waiting(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_cleanup_interval.unwrap()), cleanup_peers_handler.clone()).await { - info!("[BOOT] Shutting down thread for peers cleanup..."); - return; - } - info!("[PEERS] Checking now for dead peers."); - let _ = tracker_spawn_cleanup_peers.torrent_peers_cleanup(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_timeout.unwrap()), tracker_spawn_cleanup_peers.config.database.clone().unwrap().persistent); - info!("[PEERS] Peers cleaned up."); + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { + let tracker = Arc::new(TorrentTracker::new(config.clone(), args.create_database).await); - if tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().users_enabled.unwrap() { - info!("[USERS] Checking now for inactive torrents in users."); - tracker_spawn_cleanup_peers.clean_user_active_torrents(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_timeout.unwrap())); - info!("[USERS] Inactive torrents in users cleaned up."); - } - } - }); - - if tracker.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { - let cleanup_keys_handler = tokio_shutdown.clone(); - let tracker_spawn_cleanup_keys = tracker.clone(); - info!("[BOOT] Starting thread for keys cleanup with {} seconds delay...", tracker_spawn_cleanup_keys.config.tracker_config.clone().unwrap().keys_cleanup_interval.unwrap()); - tokio::spawn(async move { - loop { - tracker_spawn_cleanup_keys.set_stats(StatsEvent::TimestampKeysTimeout, chrono::Utc::now().timestamp() + tracker_spawn_cleanup_keys.config.tracker_config.clone().unwrap().keys_cleanup_interval.unwrap() as i64); - if shutdown_waiting(Duration::from_secs(tracker_spawn_cleanup_keys.config.tracker_config.clone().unwrap().keys_cleanup_interval.unwrap()), cleanup_keys_handler.clone()).await { - info!("[BOOT] Shutting down thread for keys cleanup..."); - return; + if tracker.config.database.clone().unwrap().persistent { + tracker.load_torrents(tracker.clone()).await; + if tracker.config.tracker_config.clone().unwrap().whitelist_enabled.unwrap() { + tracker.load_whitelist(tracker.clone()).await; } - - info!("[KEYS] Checking now for outdated keys."); - tracker_spawn_cleanup_keys.clean_keys(); - info!("[KEYS] Keys cleaned up."); - } - }); - } - - if tracker.config.database.clone().unwrap().persistent { - let updates_handler = tokio_shutdown.clone(); - let tracker_spawn_updates = tracker.clone(); - info!("[BOOT] Starting thread for database updates with {} seconds delay...", tracker_spawn_updates.config.database.clone().unwrap().persistent_interval.unwrap()); - tokio::spawn(async move { - loop { - tracker_spawn_updates.set_stats(StatsEvent::TimestampSave, chrono::Utc::now().timestamp() + tracker_spawn_updates.config.database.clone().unwrap().persistent_interval.unwrap() as i64); - if shutdown_waiting(Duration::from_secs(tracker_spawn_updates.config.database.clone().unwrap().persistent_interval.unwrap()), updates_handler.clone()).await { - info!("[BOOT] Shutting down thread for updates..."); - return; + if tracker.config.tracker_config.clone().unwrap().blacklist_enabled.unwrap() { + tracker.load_blacklist(tracker.clone()).await; } - - info!("[TORRENTS UPDATES] Start updating torrents into the DB."); - let _ = tracker_spawn_updates.save_torrent_updates(tracker_spawn_updates.clone()).await; - info!("[TORRENTS UPDATES] Torrent updates inserted into DB."); - - if tracker_spawn_updates.config.tracker_config.clone().unwrap().whitelist_enabled.unwrap() { - info!("[WHITELIST UPDATES] Start updating whitelists into the DB."); - let _ = tracker_spawn_updates.save_whitelist_updates(tracker_spawn_updates.clone()).await; - info!("[WHITELIST UPDATES] Whitelists updates inserted into DB."); + if tracker.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { + tracker.load_keys(tracker.clone()).await; } - - if tracker_spawn_updates.config.tracker_config.clone().unwrap().blacklist_enabled.unwrap() { - info!("[BLACKLIST UPDATES] Start updating blacklists into the DB."); - let _ = tracker_spawn_updates.save_blacklist_updates(tracker_spawn_updates.clone()).await; - info!("[BLACKLIST UPDATES] Blacklists updates inserted into DB."); + if tracker.config.tracker_config.clone().unwrap().users_enabled.unwrap() { + tracker.load_users(tracker.clone()).await; } - - if tracker_spawn_updates.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { - info!("[KEY UPDATES] Start updating keys into the DB."); - let _ = tracker_spawn_updates.save_key_updates(tracker_spawn_updates.clone()).await; - info!("[KEY UPDATES] Keys updates inserted into DB."); + if tracker.config.database.clone().unwrap().update_peers && !tracker.reset_seeds_peers(tracker.clone()).await { + panic!("[RESET SEEDS PEERS] Unable to continue loading"); } + } else { + tracker.set_stats(StatsEvent::Completed, config.tracker_config.clone().unwrap().total_downloads as i64); + } - if tracker_spawn_updates.config.tracker_config.clone().unwrap().users_enabled.unwrap() { - info!("[USERS UPDATES] Start updating users into the DB."); - let _ = tracker_spawn_updates.save_user_updates(tracker_spawn_updates.clone()).await; - info!("[USERS UPDATES] Keys updates inserted into DB."); + if args.create_selfsigned { tracker.cert_gen(&args).await; } + + if args.export { tracker.export(&args, tracker.clone()).await; } + + if args.import { tracker.import(&args, tracker.clone()).await; } + + let tokio_shutdown = Shutdown::new().expect("shutdown creation works on first call"); + + let deadlocks_handler = tokio_shutdown.clone(); + tokio::spawn(async move { + info!("[BOOT] Starting thread for deadlocks..."); + loop { + if shutdown_waiting(Duration::from_secs(10), deadlocks_handler.clone()).await { + info!("[BOOT] Shutting down thread for deadlocks..."); + return; + } + let deadlocks = deadlock::check_deadlock(); + if deadlocks.is_empty() { + continue; + } + info!("[DEADLOCK] Found {} deadlocks", deadlocks.len()); + for (i, threads) in deadlocks.iter().enumerate() { + info!("[DEADLOCK] #{}", i); + for t in threads { + info!("[DEADLOCK] Thread ID: {:#?}", t.thread_id()); + info!("[DEADLOCK] {:#?}", t.backtrace()); + } + } + } + }); + + let mut api_handlers = Vec::new(); + let mut api_futures = Vec::new(); + let mut apis_handlers = Vec::new(); + let mut apis_futures = Vec::new(); + for api_server_object in &config.api_server { + if api_server_object.enabled { + http_check_host_and_port_used(api_server_object.bind_address.clone()); + let address: SocketAddr = api_server_object.bind_address.parse().unwrap(); + if api_server_object.ssl.unwrap() { + let (handle, https_api) = api_service( + address, + tracker.clone(), + api_server_object.clone() + ).await; + apis_handlers.push(handle); + apis_futures.push(https_api); + } else { + let (handle, http_api) = api_service( + address, + tracker.clone(), + api_server_object.clone() + ).await; + api_handlers.push(handle); + api_futures.push(http_api); + } } } - }); - } - - tokio::select! { - _ = tokio::signal::ctrl_c() => { - info!("Shutdown request received, shutting down..."); - for handle in api_handlers.iter() { - handle.stop(true).await; + if !api_futures.is_empty() { + tokio::spawn(async move { + let _ = try_join_all(api_futures).await; + }); } - for handle in apis_handlers.iter() { - handle.stop(true).await; + if !apis_futures.is_empty() { + tokio::spawn(async move { + let _ = try_join_all(apis_futures).await; + }); } - for handle in http_handlers.iter() { - handle.stop(true).await; + + let mut http_handlers = Vec::new(); + let mut http_futures = Vec::new(); + let mut https_handlers = Vec::new(); + let mut https_futures = Vec::new(); + for http_server_object in &config.http_server { + if http_server_object.enabled { + http_check_host_and_port_used(http_server_object.bind_address.clone()); + let address: SocketAddr = http_server_object.bind_address.parse().unwrap(); + if http_server_object.ssl.unwrap() { + let (handle, https_service) = http_service( + address, + tracker.clone(), + http_server_object.clone() + ).await; + https_handlers.push(handle); + https_futures.push(https_service); + } else { + let (handle, http_service) = http_service( + address, + tracker.clone(), + http_server_object.clone() + ).await; + http_handlers.push(handle); + http_futures.push(http_service); + } + } } - for handle in https_handlers.iter() { - handle.stop(true).await; + if !http_futures.is_empty() { + tokio::spawn(async move { + let _ = try_join_all(http_futures).await; + }); } - let _ = udp_tx.send(true); - match udp_futures.into_iter().collect::>().await { - Ok(_) => {} - Err(error) => { - error!("Errors happened on shutting down UDP sockets!"); - error!("{}", error.to_string()); - } + if !https_futures.is_empty() { + tokio::spawn(async move { + let _ = try_join_all(https_futures).await; + }); } - tokio_shutdown.handle().await; - - task::sleep(Duration::from_secs(1)).await; - if tracker.config.database.clone().unwrap().persistent { - tracker.set_stats(StatsEvent::Completed, config.tracker_config.clone().unwrap().total_downloads as i64); - Configuration::save_from_config(tracker.config.clone(), "config.toml"); - info!("Saving completed data to an INI..."); - info!("Saving data to the database..."); - let _ = tracker.save_torrent_updates(tracker.clone()).await; - if tracker.config.tracker_config.clone().unwrap().whitelist_enabled.unwrap() { - let _ = tracker.save_whitelist_updates(tracker.clone()).await; - } - if tracker.config.tracker_config.clone().unwrap().blacklist_enabled.unwrap() { - let _ = tracker.save_blacklist_updates(tracker.clone()).await; + let (udp_tx, udp_rx) = tokio::sync::watch::channel(false); + let mut udp_futures = Vec::new(); + for udp_server_object in &config.udp_server { + if udp_server_object.enabled { + udp_check_host_and_port_used(udp_server_object.bind_address.clone()); + let address: SocketAddr = udp_server_object.bind_address.parse().unwrap(); + let threads: u64 = match udp_server_object.threads { + None => { available_parallelism().unwrap().get() as u64 } + Some(count) => { count } + }; + let tracker_clone = tracker.clone(); + udp_futures.push(udp_service(address, threads, tracker_clone, udp_rx.clone()).await); } - if tracker.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { - let _ = tracker.save_key_updates(tracker.clone()).await; + } + + let stats_handler = tokio_shutdown.clone(); + let tracker_spawn_stats = tracker.clone(); + info!("[BOOT] Starting thread for console updates with {} seconds delay...", tracker_spawn_stats.config.log_console_interval.unwrap_or(60u64)); + tokio::spawn(async move { + loop { + tracker_spawn_stats.set_stats(StatsEvent::TimestampSave, chrono::Utc::now().timestamp() + 60i64); + if shutdown_waiting(Duration::from_secs(tracker_spawn_stats.config.log_console_interval.unwrap_or(60u64)), stats_handler.clone()).await { + info!("[BOOT] Shutting down thread for console updates..."); + return; + } + + let stats = tracker_spawn_stats.get_stats(); + info!("[STATS] Torrents: {} - Updates: {} - Seeds: {} - Peers: {} - Completed: {}", stats.torrents, stats.torrents_updates, stats.seeds, stats.peers, stats.completed); + info!("[STATS] WList: {} - WList Updates: {} - BLists: {} - BLists Updates: {} - Keys: {} - Keys Updates {}", stats.whitelist, stats.whitelist_updates, stats.blacklist, stats.blacklist_updates, stats.keys, stats.keys_updates); + info!("[STATS TCP IPv4] Connect: {} - API: {} - A: {} - S: {} - F: {} - 404: {}", stats.tcp4_connections_handled, stats.tcp4_api_handled, stats.tcp4_announces_handled, stats.tcp4_scrapes_handled, stats.tcp4_failure, stats.tcp4_not_found); + info!("[STATS TCP IPv6] Connect: {} - API: {} - A: {} - S: {} - F: {} - 404: {}", stats.tcp6_connections_handled, stats.tcp6_api_handled, stats.tcp6_announces_handled, stats.tcp6_scrapes_handled, stats.tcp6_failure, stats.tcp6_not_found); + info!("[STATS UDP IPv4] Connect: {} - A: {} - S: {} - IR: {} - BR: {}", stats.udp4_connections_handled, stats.udp4_announces_handled, stats.udp4_scrapes_handled, stats.udp4_invalid_request, stats.udp4_bad_request); + info!("[STATS UDP IPv6] Connect: {} - A: {} - S: {} - IR: {} - BR: {}", stats.udp6_connections_handled, stats.udp6_announces_handled, stats.udp6_scrapes_handled, stats.udp6_invalid_request, stats.udp6_bad_request); } - if tracker.config.tracker_config.clone().unwrap().users_enabled.unwrap() { - let _ = tracker.save_user_updates(tracker.clone()).await; + }); + + let cleanup_peers_handler = tokio_shutdown.clone(); + let tracker_spawn_cleanup_peers = tracker.clone(); + info!("[BOOT] Starting thread for peers cleanup with {} seconds delay...", tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_cleanup_interval.unwrap()); + tokio::spawn(async move { + loop { + tracker_spawn_cleanup_peers.set_stats(StatsEvent::TimestampTimeout, chrono::Utc::now().timestamp() + tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_cleanup_interval.unwrap() as i64); + if shutdown_waiting(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_cleanup_interval.unwrap()), cleanup_peers_handler.clone()).await { + info!("[BOOT] Shutting down thread for peers cleanup..."); + return; + } + + info!("[PEERS] Checking now for dead peers."); + let _ = tracker_spawn_cleanup_peers.torrent_peers_cleanup(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_timeout.unwrap()), tracker_spawn_cleanup_peers.config.database.clone().unwrap().persistent); + info!("[PEERS] Peers cleaned up."); + + if tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().users_enabled.unwrap() { + info!("[USERS] Checking now for inactive torrents in users."); + tracker_spawn_cleanup_peers.clean_user_active_torrents(Duration::from_secs(tracker_spawn_cleanup_peers.config.tracker_config.clone().unwrap().peers_timeout.unwrap())); + info!("[USERS] Inactive torrents in users cleaned up."); + } } - } else { - tracker.set_stats(StatsEvent::Completed, config.tracker_config.clone().unwrap().total_downloads as i64); - Configuration::save_from_config(tracker.config.clone(), "config.toml"); - info!("Saving completed data to an INI..."); + }); + + if tracker.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { + let cleanup_keys_handler = tokio_shutdown.clone(); + let tracker_spawn_cleanup_keys = tracker.clone(); + info!("[BOOT] Starting thread for keys cleanup with {} seconds delay...", tracker_spawn_cleanup_keys.config.tracker_config.clone().unwrap().keys_cleanup_interval.unwrap()); + tokio::spawn(async move { + loop { + tracker_spawn_cleanup_keys.set_stats(StatsEvent::TimestampKeysTimeout, chrono::Utc::now().timestamp() + tracker_spawn_cleanup_keys.config.tracker_config.clone().unwrap().keys_cleanup_interval.unwrap() as i64); + if shutdown_waiting(Duration::from_secs(tracker_spawn_cleanup_keys.config.tracker_config.clone().unwrap().keys_cleanup_interval.unwrap()), cleanup_keys_handler.clone()).await { + info!("[BOOT] Shutting down thread for keys cleanup..."); + return; + } + + info!("[KEYS] Checking now for outdated keys."); + tracker_spawn_cleanup_keys.clean_keys(); + info!("[KEYS] Keys cleaned up."); + } + }); } - task::sleep(Duration::from_secs(1)).await; + if tracker.config.database.clone().unwrap().persistent { + let updates_handler = tokio_shutdown.clone(); + let tracker_spawn_updates = tracker.clone(); + info!("[BOOT] Starting thread for database updates with {} seconds delay...", tracker_spawn_updates.config.database.clone().unwrap().persistent_interval.unwrap()); + tokio::spawn(async move { + loop { + tracker_spawn_updates.set_stats(StatsEvent::TimestampSave, chrono::Utc::now().timestamp() + tracker_spawn_updates.config.database.clone().unwrap().persistent_interval.unwrap() as i64); + if shutdown_waiting(Duration::from_secs(tracker_spawn_updates.config.database.clone().unwrap().persistent_interval.unwrap()), updates_handler.clone()).await { + info!("[BOOT] Shutting down thread for updates..."); + return; + } + + info!("[TORRENTS UPDATES] Start updating torrents into the DB."); + let _ = tracker_spawn_updates.save_torrent_updates(tracker_spawn_updates.clone()).await; + info!("[TORRENTS UPDATES] Torrent updates inserted into DB."); + + if tracker_spawn_updates.config.tracker_config.clone().unwrap().whitelist_enabled.unwrap() { + info!("[WHITELIST UPDATES] Start updating whitelists into the DB."); + let _ = tracker_spawn_updates.save_whitelist_updates(tracker_spawn_updates.clone()).await; + info!("[WHITELIST UPDATES] Whitelists updates inserted into DB."); + } + + if tracker_spawn_updates.config.tracker_config.clone().unwrap().blacklist_enabled.unwrap() { + info!("[BLACKLIST UPDATES] Start updating blacklists into the DB."); + let _ = tracker_spawn_updates.save_blacklist_updates(tracker_spawn_updates.clone()).await; + info!("[BLACKLIST UPDATES] Blacklists updates inserted into DB."); + } + + if tracker_spawn_updates.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { + info!("[KEY UPDATES] Start updating keys into the DB."); + let _ = tracker_spawn_updates.save_key_updates(tracker_spawn_updates.clone()).await; + info!("[KEY UPDATES] Keys updates inserted into DB."); + } + + if tracker_spawn_updates.config.tracker_config.clone().unwrap().users_enabled.unwrap() { + info!("[USERS UPDATES] Start updating users into the DB."); + let _ = tracker_spawn_updates.save_user_updates(tracker_spawn_updates.clone()).await; + info!("[USERS UPDATES] Keys updates inserted into DB."); + } + } + }); + } - info!("Server shutting down completed"); - Ok(()) - } - } -} \ No newline at end of file + tokio::select! { + _ = tokio::signal::ctrl_c() => { + info!("Shutdown request received, shutting down..."); + for handle in api_handlers.iter() { + handle.stop(true).await; + } + for handle in apis_handlers.iter() { + handle.stop(true).await; + } + for handle in http_handlers.iter() { + handle.stop(true).await; + } + for handle in https_handlers.iter() { + handle.stop(true).await; + } + let _ = udp_tx.send(true); + match udp_futures.into_iter().collect::>().await { + Ok(_) => {} + Err(error) => { + error!("Errors happened on shutting down UDP sockets!"); + error!("{}", error.to_string()); + } + } + tokio_shutdown.handle().await; + + task::sleep(Duration::from_secs(1)).await; + + if tracker.config.database.clone().unwrap().persistent { + tracker.set_stats(StatsEvent::Completed, config.tracker_config.clone().unwrap().total_downloads as i64); + Configuration::save_from_config(tracker.config.clone(), "config.toml"); + info!("Saving completed data to an INI..."); + info!("Saving data to the database..."); + let _ = tracker.save_torrent_updates(tracker.clone()).await; + if tracker.config.tracker_config.clone().unwrap().whitelist_enabled.unwrap() { + let _ = tracker.save_whitelist_updates(tracker.clone()).await; + } + if tracker.config.tracker_config.clone().unwrap().blacklist_enabled.unwrap() { + let _ = tracker.save_blacklist_updates(tracker.clone()).await; + } + if tracker.config.tracker_config.clone().unwrap().keys_enabled.unwrap() { + let _ = tracker.save_key_updates(tracker.clone()).await; + } + if tracker.config.tracker_config.clone().unwrap().users_enabled.unwrap() { + let _ = tracker.save_user_updates(tracker.clone()).await; + } + } else { + tracker.set_stats(StatsEvent::Completed, config.tracker_config.clone().unwrap().total_downloads as i64); + Configuration::save_from_config(tracker.config.clone(), "config.toml"); + info!("Saving completed data to an INI..."); + } + + task::sleep(Duration::from_secs(1)).await; + + info!("Server shutting down completed"); + Ok(()) + } + } + }) +}