diff --git a/Cargo.lock b/Cargo.lock index d81fdbc0..0a72b266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -142,17 +142,6 @@ dependencies = [ "zstd-safe", ] -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "async-stream" version = "0.3.6" @@ -232,9 +221,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.13.0" +version = "1.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" +checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" dependencies = [ "aws-lc-sys", "zeroize", @@ -242,9 +231,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.28.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f" +checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" dependencies = [ "bindgen 0.69.5", "cc", @@ -663,9 +652,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.35" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ "clap_builder", "clap_derive", @@ -673,9 +662,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.35" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" dependencies = [ "anstyle", "clap_lex", @@ -742,8 +731,8 @@ dependencies = [ "opentelemetry-jaeger", "opentelemetry_sdk", "sentry", - "sentry-tower", - "sentry-tracing", + "sentry-tower 0.35.0", + "sentry-tracing 0.35.0", "tokio", "tokio-metrics", "tracing", @@ -916,8 +905,8 @@ dependencies = [ "rustls", "sd-notify", "sentry", - "sentry-tower", - "sentry-tracing", + "sentry-tower 0.35.0", + "sentry-tracing 0.35.0", "serde_json", "tokio", "tower 0.5.2", @@ -938,7 +927,7 @@ dependencies = [ "const-str", "either", "futures", - "hickory-resolver 0.25.1", + "hickory-resolver", "http", "image", "ipaddress", @@ -1072,12 +1061,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - [[package]] name = "crokey" version = "1.1.1" @@ -1119,9 +1102,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] @@ -1204,14 +1187,20 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "07e9666f4a9a948d4f1dff0c08a4512b0f7c86414b23960104c243c10d79f4c3" dependencies = [ - "quote", - "syn", + "ctor-proc-macro", + "dtor", ] +[[package]] +name = "ctor-proc-macro" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f211af61d8efdd104f96e57adf5e426ba1bc3ed7a4ead616e15e5881fd79c4d" + [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1279,9 +1268,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "28cfac68e08048ae1883171632c2aef3ebc555621ae56fbccce1cbf22dd7f058" dependencies = [ "powerfmt", ] @@ -1308,6 +1297,21 @@ dependencies = [ "syn", ] +[[package]] +name = "dtor" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222ef136a1c687d4aa0395c175f2c4586e379924c352fd02f7870cf7de783c23" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7454e41ff9012c00d53cf7f475c5e3afa3b91b7c90568495495e8d9bf47a1055" + [[package]] name = "dunce" version = "1.0.5" @@ -1454,9 +1458,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" dependencies = [ "crc32fast", "miniz_oxide", @@ -1601,19 +1605,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" -dependencies = [ - "cfg-if", - "libc", - "log", - "rustversion", - "windows 0.58.0", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1799,34 +1790,6 @@ dependencies = [ "url", ] -[[package]] -name = "hickory-proto" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d844af74f7b799e41c78221be863bade11c430d46042c3b49ca8ae0c6d27287" -dependencies = [ - "async-recursion", - "async-trait", - "cfg-if", - "critical-section", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna", - "ipnet", - "once_cell", - "rand 0.9.0", - "ring", - "serde", - "thiserror 2.0.12", - "tinyvec", - "tokio", - "tracing", - "url", -] - [[package]] name = "hickory-resolver" version = "0.24.4" @@ -1835,7 +1798,7 @@ checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" dependencies = [ "cfg-if", "futures-util", - "hickory-proto 0.24.4", + "hickory-proto", "ipconfig", "lru-cache", "once_cell", @@ -1848,28 +1811,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hickory-resolver" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a128410b38d6f931fcc6ca5c107a3b02cabd6c05967841269a4ad65d23c44331" -dependencies = [ - "cfg-if", - "futures-util", - "hickory-proto 0.25.1", - "ipconfig", - "moka", - "once_cell", - "parking_lot", - "rand 0.9.0", - "resolv-conf", - "serde", - "smallvec", - "thiserror 2.0.12", - "tokio", - "tracing", -] - [[package]] name = "hmac" version = "0.12.1" @@ -1896,7 +1837,7 @@ checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" dependencies = [ "cfg-if", "libc", - "windows 0.52.0", + "windows", ] [[package]] @@ -2016,9 +1957,9 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ "hyper", "hyper-util", @@ -2029,8 +1970,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.11" -source = "git+https://github.com/girlbossceo/hyper-util?rev=e4ae7628fe4fcdacef9788c4c8415317a4489941#e4ae7628fe4fcdacef9788c4c8415317a4489941" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -2038,7 +1980,6 @@ dependencies = [ "http", "http-body", "hyper", - "libc", "pin-project-lite", "socket2", "tokio", @@ -2335,11 +2276,10 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ - "getrandom 0.3.2", "libc", ] @@ -2519,19 +2459,6 @@ dependencies = [ "futures-sink", ] -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "loop9" version = "0.1.5" @@ -2702,25 +2629,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "moka" -version = "0.12.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9321642ca94a4282428e6ea4af8cc2ca4eac48ac7a6a4ea8f33f76d0ce70926" -dependencies = [ - "crossbeam-channel", - "crossbeam-epoch", - "crossbeam-utils", - "loom", - "parking_lot", - "portable-atomic", - "rustc_version", - "smallvec", - "tagptr", - "thiserror 1.0.69", - "uuid", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -2885,10 +2793,6 @@ name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -dependencies = [ - "critical-section", - "portable-atomic", -] [[package]] name = "openssl-probe" @@ -3168,12 +3072,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "portable-atomic" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" - [[package]] name = "powerfmt" version = "0.2.0" @@ -3574,9 +3472,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "async-compression", "base64 0.22.1", @@ -3585,7 +3483,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "hickory-resolver 0.24.4", + "hickory-resolver", "http", "http-body", "http-body-util", @@ -3612,7 +3510,6 @@ dependencies = [ "tokio-rustls", "tokio-socks", "tokio-util", - "tower 0.5.2", "tower-service", "url", "wasm-bindgen", @@ -3625,7 +3522,8 @@ dependencies = [ [[package]] name = "resolv-conf" version = "0.7.1" -source = "git+https://github.com/girlbossceo/resolv-conf?rev=200e958941d522a70c5877e3d846f55b5586c68d#200e958941d522a70c5877e3d846f55b5586c68d" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4" dependencies = [ "hostname", ] @@ -3653,7 +3551,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.10.1" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "assign", "js_int", @@ -3673,7 +3571,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "js_int", "ruma-common", @@ -3685,7 +3583,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "as_variant", "assign", @@ -3708,7 +3606,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "as_variant", "base64 0.22.1", @@ -3740,7 +3638,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "as_variant", "indexmap 2.8.0", @@ -3765,7 +3663,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "bytes", "headers", @@ -3787,7 +3685,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "js_int", "thiserror 2.0.12", @@ -3796,7 +3694,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "js_int", "ruma-common", @@ -3806,7 +3704,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "cfg-if", "proc-macro-crate", @@ -3821,7 +3719,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "js_int", "ruma-common", @@ -3833,7 +3731,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://github.com/girlbossceo/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4" +source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" dependencies = [ "base64 0.22.1", "ed25519-dalek", @@ -4015,12 +3913,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -4067,21 +3959,21 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "sentry" -version = "0.37.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255914a8e53822abd946e2ce8baa41d4cded6b8e938913b7f7b9da5b7ab44335" +checksum = "3a7332159e544e34db06b251b1eda5e546bd90285c3f58d9c8ff8450b484e0da" dependencies = [ "httpdate", "reqwest", "rustls", "sentry-backtrace", "sentry-contexts", - "sentry-core", + "sentry-core 0.36.0", "sentry-debug-images", "sentry-log", "sentry-panic", - "sentry-tower", - "sentry-tracing", + "sentry-tower 0.36.0", + "sentry-tracing 0.36.0", "tokio", "ureq", "webpki-roots", @@ -4089,83 +3981,107 @@ dependencies = [ [[package]] name = "sentry-backtrace" -version = "0.37.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00293cd332a859961f24fd69258f7e92af736feaeb91020cff84dac4188a4302" +checksum = "565ec31ad37bab8e6d9f289f34913ed8768347b133706192f10606dabd5c6bc4" dependencies = [ "backtrace", "once_cell", "regex", - "sentry-core", + "sentry-core 0.36.0", ] [[package]] name = "sentry-contexts" -version = "0.37.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961990f9caa76476c481de130ada05614cd7f5aa70fb57c2142f0e09ad3fb2aa" +checksum = "e860275f25f27e8c0c7726ce116c7d5c928c5bba2ee73306e52b20a752298ea6" dependencies = [ "hostname", "libc", "os_info", "rustc_version", - "sentry-core", + "sentry-core 0.36.0", "uname", ] [[package]] name = "sentry-core" -version = "0.37.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a6409d845707d82415c800290a5d63be5e3df3c2e417b0997c60531dfbd35ef" +checksum = "f9f8b6dcd4fbae1e3e22b447f32670360b27e31b62ab040f7fb04e0f80c04d92" dependencies = [ "once_cell", "rand 0.8.5", - "sentry-types", + "sentry-types 0.35.0", + "serde", + "serde_json", +] + +[[package]] +name = "sentry-core" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653942e6141f16651273159f4b8b1eaeedf37a7554c00cd798953e64b8a9bf72" +dependencies = [ + "once_cell", + "rand 0.8.5", + "sentry-types 0.36.0", "serde", "serde_json", ] [[package]] name = "sentry-debug-images" -version = "0.37.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ab5df4f3b64760508edfe0ba4290feab5acbbda7566a79d72673065888e5cc" +checksum = "2a60bc2154e6df59beed0ac13d58f8dfaf5ad20a88548a53e29e4d92e8e835c2" dependencies = [ "findshlibs", "once_cell", - "sentry-core", + "sentry-core 0.36.0", ] [[package]] name = "sentry-log" -version = "0.37.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693841da8dfb693af29105edfbea1d91348a13d23dd0a5d03761eedb9e450c46" +checksum = "1c96d796cba1b3a0793e7f53edc420c61f9419fba8fb34ad5519f5c7d01af6b2" dependencies = [ "log", - "sentry-core", + "sentry-core 0.36.0", ] [[package]] name = "sentry-panic" -version = "0.37.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609b1a12340495ce17baeec9e08ff8ed423c337c1a84dffae36a178c783623f3" +checksum = "105e3a956c8aa9dab1e4087b1657b03271bfc49d838c6ae9bfc7c58c802fd0ef" dependencies = [ "sentry-backtrace", - "sentry-core", + "sentry-core 0.36.0", ] [[package]] name = "sentry-tower" -version = "0.37.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b98005537e38ee3bc10e7d36e7febe9b8e573d03f2ddd85fcdf05d21f9abd6d" +checksum = "fcdaf9b1939589476bd57751d12a9653bbfe356610fc476d03d7683189183ab7" +dependencies = [ + "sentry-core 0.35.0", + "tower-layer", + "tower-service", +] + +[[package]] +name = "sentry-tower" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082f781dfc504d984e16d99f8dbf94d6ee4762dd0fc28de25713d0f900a8164d" dependencies = [ "http", "pin-project", - "sentry-core", + "sentry-core 0.36.0", "tower-layer", "tower-service", "url", @@ -4173,21 +4089,49 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.37.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f4e86402d5c50239dc7d8fd3f6d5e048221d5fcb4e026d8d50ab57fe4644cb" +checksum = "263f73c757ed7915d3e1e34625eae18cad498a95b4261603d4ce3f87b159a6f0" +dependencies = [ + "sentry-core 0.35.0", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sentry-tracing" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e75c831b4d8b34a5aec1f65f67c5d46a26c7c5d3c7abd8b5ef430796900cf8" dependencies = [ "sentry-backtrace", - "sentry-core", + "sentry-core 0.36.0", "tracing-core", "tracing-subscriber", ] [[package]] name = "sentry-types" -version = "0.37.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3f117b8755dbede8260952de2aeb029e20f432e72634e8969af34324591631" +checksum = "a71ed3a389948a6a6d92b98e997a2723ca22f09660c5a7b7388ecd509a70a527" +dependencies = [ + "debugid", + "hex", + "rand 0.8.5", + "serde", + "serde_json", + "thiserror 1.0.69", + "time", + "url", + "uuid", +] + +[[package]] +name = "sentry-types" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4203359e60724aa05cf2385aaf5d4f147e837185d7dd2b9ccf1ee77f4420c8" dependencies = [ "debugid", "hex", @@ -4540,12 +4484,6 @@ dependencies = [ "version-compare", ] -[[package]] -name = "tagptr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" - [[package]] name = "target-lexicon" version = "0.12.16" @@ -4758,9 +4696,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", @@ -5449,17 +5387,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core 0.52.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", + "windows-core", "windows-targets 0.52.6", ] @@ -5472,56 +5400,15 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - [[package]] name = "windows-registry" -version = "0.4.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result 0.3.2", - "windows-strings 0.3.1", - "windows-targets 0.53.0", + "windows-result", + "windows-strings", + "windows-targets 0.52.6", ] [[package]] @@ -5533,34 +5420,16 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-result" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result 0.2.0", + "windows-result", "windows-targets 0.52.6", ] -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5612,29 +5481,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -5647,12 +5500,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -5665,12 +5512,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -5683,24 +5524,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -5713,12 +5542,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -5731,12 +5554,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -5749,12 +5566,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -5767,12 +5578,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" version = "0.7.4" diff --git a/Cargo.toml b/Cargo.toml index f5ee3f0f..5819f62b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ license = "Apache-2.0" # See also `rust-toolchain.toml` readme = "README.md" repository = "https://github.com/girlbossceo/conduwuit" -rust-version = "1.86.0" +rust-version = "1.85.0" version = "0.5.0" [workspace.metadata.crane] @@ -48,7 +48,7 @@ features = ["ffi", "std", "union"] version = "0.6.2" [workspace.dependencies.ctor] -version = "0.2.9" +version = "0.4.0" [workspace.dependencies.cargo_toml] version = "0.21" @@ -141,12 +141,12 @@ features = [ ] [workspace.dependencies.rustls] -version = "0.23.25" +version = "0.23.19" default-features = false features = ["aws_lc_rs"] [workspace.dependencies.reqwest] -version = "0.12.15" +version = "0.12.9" default-features = false features = [ "rustls-tls-native-roots", @@ -204,7 +204,7 @@ features = [ # logging [workspace.dependencies.log] -version = "0.4.27" +version = "0.4.22" default-features = false [workspace.dependencies.tracing] version = "0.1.41" @@ -224,7 +224,7 @@ default-features = false # used for conduwuit's CLI and admin room command parsing [workspace.dependencies.clap] -version = "4.5.35" +version = "4.5.23" default-features = false features = [ "derive", @@ -242,7 +242,7 @@ default-features = false features = ["std", "async-await"] [workspace.dependencies.tokio] -version = "1.44.2" +version = "1.44.1" default-features = false features = [ "fs", @@ -284,7 +284,8 @@ features = [ ] [workspace.dependencies.hyper-util] -version = "0.1.11" +# hyper-util >=0.1.9 seems to have DNS issues +version = "0.1.10" default-features = false features = [ "server-auto", @@ -305,13 +306,8 @@ default-features = false features = ["env", "toml"] [workspace.dependencies.hickory-resolver] -version = "0.25.1" +version = "0.24.2" default-features = false -features = [ - "serde", - "system-config", - "tokio", -] # Used for conduwuit::Error type [workspace.dependencies.thiserror] @@ -320,7 +316,7 @@ default-features = false # Used when hashing the state [workspace.dependencies.ring] -version = "0.17.14" +version = "0.17.8" default-features = false # Used to make working with iterators easier, was already a transitive depdendency @@ -350,7 +346,7 @@ version = "0.1.2" [workspace.dependencies.ruma] git = "https://github.com/girlbossceo/ruwuma" #branch = "conduwuit-changes" -rev = "920148dca1076454ca0ca5d43b5ce1aa708381d4" +rev = "d197318a2507d38ffe6ee524d0d52728ca72538a" features = [ "compat", "rand", @@ -427,7 +423,7 @@ features = ["rt-tokio"] # optional sentry metrics for crash/panic reporting [workspace.dependencies.sentry] -version = "0.37.0" +version = "0.36.0" default-features = false features = [ "backtrace", @@ -443,9 +439,9 @@ features = [ ] [workspace.dependencies.sentry-tracing] -version = "0.37.0" +version = "0.35.0" [workspace.dependencies.sentry-tower] -version = "0.37.0" +version = "0.35.0" # jemalloc usage [workspace.dependencies.tikv-jemalloc-sys] @@ -479,7 +475,7 @@ default-features = false features = ["resource"] [workspace.dependencies.sd-notify] -version = "0.4.5" +version = "0.4.3" default-features = false [workspace.dependencies.hardened_malloc-rs] @@ -496,7 +492,7 @@ version = "0.4.3" default-features = false [workspace.dependencies.termimad] -version = "0.31.2" +version = "0.31.1" default-features = false [workspace.dependencies.checked_ops] @@ -570,23 +566,10 @@ rev = "fe4aebeeaae435af60087ddd56b573a2e0be671d" git = "https://github.com/girlbossceo/async-channel" rev = "92e5e74063bf2a3b10414bcc8a0d68b235644280" -# adds affinity masks for selecting more than one core at a time [patch.crates-io.core_affinity] git = "https://github.com/girlbossceo/core_affinity_rs" rev = "9c8e51510c35077df888ee72a36b4b05637147da" -# reverts hyperium#148 conflicting with our delicate federation resolver hooks -[patch.crates-io.hyper-util] -git = "https://github.com/girlbossceo/hyper-util" -rev = "e4ae7628fe4fcdacef9788c4c8415317a4489941" - -# allows no-aaaa option in resolv.conf -# bumps rust edition and toolchain to 1.86.0 and 2024 -# use sat_add on line number errors -[patch.crates-io.resolv-conf] -git = "https://github.com/girlbossceo/resolv-conf" -rev = "200e958941d522a70c5877e3d846f55b5586c68d" - # # Our crates # diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 118bc57d..15e6dd37 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -195,6 +195,14 @@ # #servernameevent_data_cache_capacity = varies by system +# This item is undocumented. Please contribute documentation for it. +# +#server_visibility_cache_capacity = varies by system + +# This item is undocumented. Please contribute documentation for it. +# +#user_visibility_cache_capacity = varies by system + # This item is undocumented. Please contribute documentation for it. # #stateinfo_cache_capacity = varies by system @@ -527,9 +535,9 @@ # Default room version conduwuit will create rooms with. # -# Per spec, room version 11 is the default. +# Per spec, room version 10 is the default. # -#default_room_version = 11 +#default_room_version = 10 # This item is undocumented. Please contribute documentation for it. # @@ -594,7 +602,7 @@ # Currently, conduwuit doesn't support inbound batched key requests, so # this list should only contain other Synapse servers. # -# example: ["matrix.org", "tchncs.de"] +# example: ["matrix.org", "envs.net", "tchncs.de"] # #trusted_servers = ["matrix.org"] @@ -1186,16 +1194,13 @@ # #prune_missing_media = false -# Vector list of regex patterns of server names that conduwuit will refuse -# to download remote media from. -# -# example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"] +# Vector list of servers that conduwuit will refuse to download remote +# media from. # #prevent_media_downloads_from = [] -# List of forbidden server names via regex patterns that we will block -# incoming AND outgoing federation with, and block client room joins / -# remote user invites. +# List of forbidden server names that we will block incoming AND outgoing +# federation with, and block client room joins / remote user invites. # # This check is applied on the room ID, room alias, sender server name, # sender user's server name, inbound federation X-Matrix origin, and @@ -1203,15 +1208,11 @@ # # Basically "global" ACLs. # -# example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"] -# #forbidden_remote_server_names = [] -# List of forbidden server names via regex patterns that we will block all -# outgoing federated room directory requests for. Useful for preventing -# our users from wandering into bad servers or spaces. -# -# example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"] +# List of forbidden server names that we will block all outgoing federated +# room directory requests for. Useful for preventing our users from +# wandering into bad servers or spaces. # #forbidden_remote_room_directory_server_names = [] @@ -1322,7 +1323,7 @@ # used, and startup as warnings if any room aliases in your database have # a forbidden room alias/ID. # -# example: ["19dollarfortnitecards", "b[4a]droom", "badphrase"] +# example: ["19dollarfortnitecards", "b[4a]droom"] # #forbidden_alias_names = [] @@ -1335,7 +1336,7 @@ # startup as warnings if any local users in your database have a forbidden # username. # -# example: ["administrator", "b[a4]dusernam[3e]", "badphrase"] +# example: ["administrator", "b[a4]dusernam[3e]"] # #forbidden_usernames = [] diff --git a/flake.nix b/flake.nix index 49e860ed..9db2e90a 100644 --- a/flake.nix +++ b/flake.nix @@ -26,7 +26,7 @@ file = ./rust-toolchain.toml; # See also `rust-toolchain.toml` - sha256 = "sha256-X/4ZBHO3iW0fOenQ3foEvscgAPJYl2abspaBThDOukI="; + sha256 = "sha256-AJ6LX/Q/Er9kS15bn9iflkUwcgYqRQxiOIL2ToVAXaU="; }; mkScope = pkgs: pkgs.lib.makeScope pkgs.newScope (self: { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index aadc8f99..97b4a789 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -9,7 +9,7 @@ # If you're having trouble making the relevant changes, bug a maintainer. [toolchain] -channel = "1.86.0" +channel = "1.85.0" profile = "minimal" components = [ # For rust-analyzer diff --git a/src/admin/debug/commands.rs b/src/admin/debug/commands.rs index 87ca03a0..c6f6a170 100644 --- a/src/admin/debug/commands.rs +++ b/src/admin/debug/commands.rs @@ -6,9 +6,7 @@ use std::{ }; use conduwuit::{ - Error, Result, debug_error, err, info, - matrix::pdu::{PduEvent, PduId, RawPduId}, - trace, utils, + Error, PduEvent, PduId, RawPduId, Result, debug_error, err, info, trace, utils, utils::{ stream::{IterStream, ReadyExt}, string::EMPTY, diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index 45e550be..35067304 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -2,8 +2,7 @@ use std::{collections::BTreeMap, fmt::Write as _}; use api::client::{full_user_deactivate, join_room_by_id_helper, leave_room}; use conduwuit::{ - Result, debug, debug_warn, error, info, is_equal_to, - matrix::pdu::PduBuilder, + PduBuilder, Result, debug, debug_warn, error, info, is_equal_to, utils::{self, ReadyExt}, warn, }; diff --git a/src/api/client/account.rs b/src/api/client/account.rs index 32f2530c..efa8b142 100644 --- a/src/api/client/account.rs +++ b/src/api/client/account.rs @@ -3,13 +3,10 @@ use std::fmt::Write; use axum::extract::State; use axum_client_ip::InsecureClientIp; use conduwuit::{ - Err, Error, Result, debug_info, err, error, info, is_equal_to, - matrix::pdu::PduBuilder, - utils, + Err, Error, PduBuilder, Result, debug_info, err, error, info, is_equal_to, utils, utils::{ReadyExt, stream::BroadbandExt}, warn, }; -use conduwuit_service::Services; use futures::{FutureExt, StreamExt}; use register::RegistrationKind; use ruma::{ @@ -33,6 +30,7 @@ use ruma::{ }, push, }; +use service::Services; use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH, join_room_by_id_helper}; use crate::Ruma; @@ -320,14 +318,14 @@ pub(crate) async fn register_route( // Success! }, | _ => match body.json_body { - | Some(ref json) => { + | Some(json) => { uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); services.uiaa.create( &UserId::parse_with_server_name("", services.globals.server_name()) .unwrap(), "".into(), &uiaainfo, - json, + &json, ); return Err(Error::Uiaa(uiaainfo)); }, @@ -375,12 +373,8 @@ pub(crate) async fn register_route( ) .await?; - if (!is_guest && body.inhibit_login) - || body - .appservice_info - .as_ref() - .is_some_and(|appservice| appservice.registration.device_management) - { + // Inhibit login does not work for guests + if !is_guest && body.inhibit_login { return Ok(register::v3::Response { access_token: None, user_id, diff --git a/src/api/client/account_data.rs b/src/api/client/account_data.rs index e44ce4e7..60c18b37 100644 --- a/src/api/client/account_data.rs +++ b/src/api/client/account_data.rs @@ -1,6 +1,5 @@ use axum::extract::State; -use conduwuit::{Err, Result, err}; -use conduwuit_service::Services; +use conduwuit::{Err, err}; use ruma::{ RoomId, UserId, api::client::config::{ @@ -16,7 +15,7 @@ use ruma::{ use serde::Deserialize; use serde_json::{json, value::RawValue as RawJsonValue}; -use crate::Ruma; +use crate::{Result, Ruma, service::Services}; /// # `PUT /_matrix/client/r0/user/{userId}/account_data/{type}` /// diff --git a/src/api/client/alias.rs b/src/api/client/alias.rs index 9f1b05f8..319e5141 100644 --- a/src/api/client/alias.rs +++ b/src/api/client/alias.rs @@ -1,12 +1,12 @@ use axum::extract::State; use conduwuit::{Err, Result, debug}; -use conduwuit_service::Services; use futures::StreamExt; use rand::seq::SliceRandom; use ruma::{ OwnedServerName, RoomAliasId, RoomId, api::client::alias::{create_alias, delete_alias, get_alias}, }; +use service::Services; use crate::Ruma; diff --git a/src/api/client/appservice.rs b/src/api/client/appservice.rs index eb6b3312..84955309 100644 --- a/src/api/client/appservice.rs +++ b/src/api/client/appservice.rs @@ -22,13 +22,7 @@ pub(crate) async fn appservice_ping( ))); } - if appservice_info.registration.url.is_none() - || appservice_info - .registration - .url - .as_ref() - .is_some_and(|url| url.is_empty() || url == "null") - { + if appservice_info.registration.url.is_none() { return Err!(Request(UrlNotSet( "Appservice does not have a URL set, there is nothing to ping." ))); diff --git a/src/api/client/backup.rs b/src/api/client/backup.rs index 2ad37cf3..83955fea 100644 --- a/src/api/client/backup.rs +++ b/src/api/client/backup.rs @@ -1,7 +1,7 @@ use std::cmp::Ordering; use axum::extract::State; -use conduwuit::{Err, Result, err}; +use conduwuit::{Err, err}; use ruma::{ UInt, api::client::backup::{ @@ -13,7 +13,7 @@ use ruma::{ }, }; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `POST /_matrix/client/r0/room_keys/version` /// diff --git a/src/api/client/context.rs b/src/api/client/context.rs index dbc2a22f..1dda7b53 100644 --- a/src/api/client/context.rs +++ b/src/api/client/context.rs @@ -1,20 +1,18 @@ use axum::extract::State; use conduwuit::{ - Err, Result, at, debug_warn, err, - matrix::pdu::PduEvent, - ref_at, + Err, PduEvent, Result, at, debug_warn, err, ref_at, utils::{ IterStream, future::TryExtExt, stream::{BroadbandExt, ReadyExt, TryIgnore, WidebandExt}, }, }; -use conduwuit_service::rooms::{lazy_loading, lazy_loading::Options, short::ShortStateKey}; use futures::{ FutureExt, StreamExt, TryFutureExt, TryStreamExt, future::{OptionFuture, join, join3, try_join3}, }; use ruma::{OwnedEventId, UserId, api::client::context::get_context, events::StateEventType}; +use service::rooms::{lazy_loading, lazy_loading::Options, short::ShortStateKey}; use crate::{ Ruma, diff --git a/src/api/client/device.rs b/src/api/client/device.rs index 5519a1a5..6a845aed 100644 --- a/src/api/client/device.rs +++ b/src/api/client/device.rs @@ -1,9 +1,9 @@ use axum::extract::State; use axum_client_ip::InsecureClientIp; -use conduwuit::{Err, Error, Result, debug, err, utils}; +use conduwuit::{Err, err}; use futures::StreamExt; use ruma::{ - MilliSecondsSinceUnixEpoch, OwnedDeviceId, + MilliSecondsSinceUnixEpoch, api::client::{ device::{self, delete_device, delete_devices, get_device, get_devices, update_device}, error::ErrorKind, @@ -12,7 +12,7 @@ use ruma::{ }; use super::SESSION_ID_LENGTH; -use crate::{Ruma, client::DEVICE_ID_LENGTH}; +use crate::{Error, Result, Ruma, utils}; /// # `GET /_matrix/client/r0/devices` /// @@ -59,58 +59,26 @@ pub(crate) async fn update_device_route( InsecureClientIp(client): InsecureClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let appservice = body.appservice_info.as_ref(); + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - match services + let mut device = services .users .get_device_metadata(sender_user, &body.device_id) .await - { - | Ok(mut device) => { - device.display_name.clone_from(&body.display_name); - device.last_seen_ip.clone_from(&Some(client.to_string())); - device - .last_seen_ts - .clone_from(&Some(MilliSecondsSinceUnixEpoch::now())); + .map_err(|_| err!(Request(NotFound("Device not found."))))?; - services - .users - .update_device_metadata(sender_user, &body.device_id, &device) - .await?; + device.display_name.clone_from(&body.display_name); + device.last_seen_ip.clone_from(&Some(client.to_string())); + device + .last_seen_ts + .clone_from(&Some(MilliSecondsSinceUnixEpoch::now())); - Ok(update_device::v3::Response {}) - }, - | Err(_) => { - let Some(appservice) = appservice else { - return Err!(Request(NotFound("Device not found."))); - }; - if !appservice.registration.device_management { - return Err!(Request(NotFound("Device not found."))); - } + services + .users + .update_device_metadata(sender_user, &body.device_id, &device) + .await?; - debug!( - "Creating new device for {sender_user} from appservice {} as MSC4190 is enabled \ - and device ID does not exist", - appservice.registration.id - ); - - let device_id = OwnedDeviceId::from(utils::random_string(DEVICE_ID_LENGTH)); - - services - .users - .create_device( - sender_user, - &device_id, - &appservice.registration.as_token, - None, - Some(client.to_string()), - ) - .await?; - - return Ok(update_device::v3::Response {}); - }, - } + Ok(update_device::v3::Response {}) } /// # `DELETE /_matrix/client/r0/devices/{deviceId}` @@ -127,21 +95,8 @@ pub(crate) async fn delete_device_route( State(services): State, body: Ruma, ) -> Result { - let (sender_user, sender_device) = body.sender(); - let appservice = body.appservice_info.as_ref(); - - if appservice.is_some_and(|appservice| appservice.registration.device_management) { - debug!( - "Skipping UIAA for {sender_user} as this is from an appservice and MSC4190 is \ - enabled" - ); - services - .users - .remove_device(sender_user, &body.device_id) - .await; - - return Ok(delete_device::v3::Response {}); - } + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + let sender_device = body.sender_device.as_ref().expect("user is authenticated"); // UIAA let mut uiaainfo = UiaaInfo { @@ -165,11 +120,11 @@ pub(crate) async fn delete_device_route( // Success! }, | _ => match body.json_body { - | Some(ref json) => { + | Some(json) => { uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); services .uiaa - .create(sender_user, sender_device, &uiaainfo, json); + .create(sender_user, sender_device, &uiaainfo, &json); return Err!(Uiaa(uiaainfo)); }, @@ -187,12 +142,11 @@ pub(crate) async fn delete_device_route( Ok(delete_device::v3::Response {}) } -/// # `POST /_matrix/client/v3/delete_devices` +/// # `PUT /_matrix/client/r0/devices/{deviceId}` /// -/// Deletes the given list of devices. +/// Deletes the given device. /// -/// - Requires UIAA to verify user password unless from an appservice with -/// MSC4190 enabled. +/// - Requires UIAA to verify user password /// /// For each device: /// - Invalidates access token @@ -204,20 +158,8 @@ pub(crate) async fn delete_devices_route( State(services): State, body: Ruma, ) -> Result { - let (sender_user, sender_device) = body.sender(); - let appservice = body.appservice_info.as_ref(); - - if appservice.is_some_and(|appservice| appservice.registration.device_management) { - debug!( - "Skipping UIAA for {sender_user} as this is from an appservice and MSC4190 is \ - enabled" - ); - for device_id in &body.devices { - services.users.remove_device(sender_user, device_id).await; - } - - return Ok(delete_devices::v3::Response {}); - } + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + let sender_device = body.sender_device.as_ref().expect("user is authenticated"); // UIAA let mut uiaainfo = UiaaInfo { @@ -241,11 +183,11 @@ pub(crate) async fn delete_devices_route( // Success! }, | _ => match body.json_body { - | Some(ref json) => { + | Some(json) => { uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); services .uiaa - .create(sender_user, sender_device, &uiaainfo, json); + .create(sender_user, sender_device, &uiaainfo, &json); return Err(Error::Uiaa(uiaainfo)); }, diff --git a/src/api/client/directory.rs b/src/api/client/directory.rs index b44b9f64..f2f668c8 100644 --- a/src/api/client/directory.rs +++ b/src/api/client/directory.rs @@ -9,7 +9,6 @@ use conduwuit::{ stream::{ReadyExt, WidebandExt}, }, }; -use conduwuit_service::Services; use futures::{ FutureExt, StreamExt, TryFutureExt, future::{join, join4, join5}, @@ -36,6 +35,7 @@ use ruma::{ }, uint, }; +use service::Services; use crate::Ruma; @@ -52,13 +52,10 @@ pub(crate) async fn get_public_rooms_filtered_route( ) -> Result { if let Some(server) = &body.server { if services + .server .config .forbidden_remote_room_directory_server_names - .is_match(server.host()) - || services - .config - .forbidden_remote_server_names - .is_match(server.host()) + .contains(server) { return Err!(Request(Forbidden("Server is banned on this homeserver."))); } @@ -93,13 +90,10 @@ pub(crate) async fn get_public_rooms_route( ) -> Result { if let Some(server) = &body.server { if services + .server .config .forbidden_remote_room_directory_server_names - .is_match(server.host()) - || services - .config - .forbidden_remote_server_names - .is_match(server.host()) + .contains(server) { return Err!(Request(Forbidden("Server is banned on this homeserver."))); } diff --git a/src/api/client/filter.rs b/src/api/client/filter.rs index 97044ffc..84086452 100644 --- a/src/api/client/filter.rs +++ b/src/api/client/filter.rs @@ -1,8 +1,8 @@ use axum::extract::State; -use conduwuit::{Result, err}; +use conduwuit::err; use ruma::api::client::filter::{create_filter, get_filter}; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `GET /_matrix/client/r0/user/{userId}/filter/{filterId}` /// diff --git a/src/api/client/keys.rs b/src/api/client/keys.rs index 650c573f..f50d7afa 100644 --- a/src/api/client/keys.rs +++ b/src/api/client/keys.rs @@ -1,8 +1,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use axum::extract::State; -use conduwuit::{Err, Error, Result, debug, debug_warn, err, result::NotFound, utils}; -use conduwuit_service::{Services, users::parse_master_key}; +use conduwuit::{Err, Error, Result, debug, debug_warn, err, info, result::NotFound, utils}; use futures::{StreamExt, stream::FuturesUnordered}; use ruma::{ OneTimeKeyAlgorithm, OwnedDeviceId, OwnedUserId, UserId, @@ -10,8 +9,7 @@ use ruma::{ client::{ error::ErrorKind, keys::{ - claim_keys, get_key_changes, get_keys, upload_keys, - upload_signatures::{self}, + claim_keys, get_key_changes, get_keys, upload_keys, upload_signatures, upload_signing_keys, }, uiaa::{AuthFlow, AuthType, UiaaInfo}, @@ -24,7 +22,10 @@ use ruma::{ use serde_json::json; use super::SESSION_ID_LENGTH; -use crate::Ruma; +use crate::{ + Ruma, + service::{Services, users::parse_master_key}, +}; /// # `POST /_matrix/client/r0/keys/upload` /// @@ -177,7 +178,7 @@ pub(crate) async fn upload_signing_keys_route( body.master_key.as_ref(), ) .await - .inspect_err(|e| debug!(?e)) + .inspect_err(|e| info!(?e)) { | Ok(exists) => { if let Some(result) = exists { @@ -307,60 +308,53 @@ async fn check_for_new_keys( /// # `POST /_matrix/client/r0/keys/signatures/upload` /// /// Uploads end-to-end key signatures from the sender user. -/// -/// TODO: clean this timo-code up more and integrate failures. tried to improve -/// it a bit to stop exploding the entire request on bad sigs, but needs way -/// more work. pub(crate) async fn upload_signatures_route( State(services): State, body: Ruma, ) -> Result { - if body.signed_keys.is_empty() { - debug!("Empty signed_keys sent in key signature upload"); - return Ok(upload_signatures::v3::Response::new()); - } - - let sender_user = body.sender_user(); + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); for (user_id, keys) in &body.signed_keys { for (key_id, key) in keys { - let Ok(key) = serde_json::to_value(key) - .inspect_err(|e| debug_warn!(?key_id, "Invalid \"key\" JSON: {e}")) - else { - continue; - }; + let key = serde_json::to_value(key) + .map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid key JSON"))?; - let Some(signatures) = key.get("signatures") else { - continue; - }; + for signature in key + .get("signatures") + .ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Missing signatures field."))? + .get(sender_user.to_string()) + .ok_or(Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid user in signatures field.", + ))? + .as_object() + .ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Invalid signature."))? + .clone() + { + // Signature validation? + let signature = ( + signature.0, + signature + .1 + .as_str() + .ok_or(Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid signature value.", + ))? + .to_owned(), + ); - let Some(sender_user_val) = signatures.get(sender_user.to_string()) else { - continue; - }; - - let Some(sender_user_object) = sender_user_val.as_object() else { - continue; - }; - - for (signature, val) in sender_user_object.clone() { - let Some(val) = val.as_str().map(ToOwned::to_owned) else { - continue; - }; - let signature = (signature, val); - - if let Err(_e) = services + services .users .sign_key(user_id, key_id, signature, sender_user) - .await - .inspect_err(|e| debug_warn!("{e}")) - { - continue; - } + .await?; } } } - Ok(upload_signatures::v3::Response { failures: BTreeMap::new() }) + Ok(upload_signatures::v3::Response { + failures: BTreeMap::new(), // TODO: integrate + }) } /// # `POST /_matrix/client/r0/keys/changes` diff --git a/src/api/client/membership.rs b/src/api/client/membership.rs index 1eeacf83..315a363c 100644 --- a/src/api/client/membership.rs +++ b/src/api/client/membership.rs @@ -9,25 +9,13 @@ use std::{ use axum::extract::State; use axum_client_ip::InsecureClientIp; use conduwuit::{ - Err, Result, at, debug, debug_info, debug_warn, err, error, info, - matrix::{ - StateKey, - pdu::{PduBuilder, PduEvent, gen_event_id, gen_event_id_canonical_json}, - state_res, - }, + Err, PduEvent, Result, StateKey, at, debug, debug_info, debug_warn, err, error, info, + pdu::{PduBuilder, gen_event_id_canonical_json}, result::{FlatOk, NotFound}, - trace, + state_res, trace, utils::{self, IterStream, ReadyExt, shuffle}, warn, }; -use conduwuit_service::{ - Services, - appservice::RegistrationInfo, - rooms::{ - state::RoomMutexGuard, - state_compressor::{CompressedState, HashSetCompressStateEvent}, - }, -}; use futures::{FutureExt, StreamExt, TryFutureExt, future::join4, join}; use ruma::{ CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, OwnedRoomId, OwnedServerName, @@ -56,6 +44,15 @@ use ruma::{ }, }, }; +use service::{ + Services, + appservice::RegistrationInfo, + pdu::gen_event_id, + rooms::{ + state::RoomMutexGuard, + state_compressor::{CompressedState, HashSetCompressStateEvent}, + }, +}; use crate::{Ruma, client::full_user_deactivate}; @@ -79,9 +76,10 @@ async fn banned_room_check( if let Some(room_id) = room_id { if services.rooms.metadata.is_banned(room_id).await || services + .server .config .forbidden_remote_server_names - .is_match(room_id.server_name().unwrap().host()) + .contains(&room_id.server_name().unwrap().to_owned()) { warn!( "User {user_id} who is not an admin attempted to send an invite for or \ @@ -119,9 +117,10 @@ async fn banned_room_check( } } else if let Some(server_name) = server_name { if services + .server .config .forbidden_remote_server_names - .is_match(server_name.host()) + .contains(&server_name.to_owned()) { warn!( "User {user_id} who is not an admin tried joining a room which has the server \ @@ -476,9 +475,9 @@ pub(crate) async fn leave_room_route( State(services): State, body: Ruma, ) -> Result { - leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone()) - .await - .map(|()| leave_room::v3::Response::new()) + leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone()).await?; + + Ok(leave_room::v3::Response::new()) } /// # `POST /_matrix/client/r0/rooms/{roomId}/invite` @@ -1764,8 +1763,8 @@ pub(crate) async fn invite_helper( Ok(()) } -// Make a user leave all their joined rooms, rescinds knocks, forgets all rooms, -// and ignores errors +// Make a user leave all their joined rooms, forgets all rooms, and ignores +// errors pub async fn leave_all_rooms(services: &Services, user_id: &UserId) { let rooms_joined = services .rooms @@ -1779,17 +1778,7 @@ pub async fn leave_all_rooms(services: &Services, user_id: &UserId) { .rooms_invited(user_id) .map(|(r, _)| r); - let rooms_knocked = services - .rooms - .state_cache - .rooms_knocked(user_id) - .map(|(r, _)| r); - - let all_rooms: Vec<_> = rooms_joined - .chain(rooms_invited) - .chain(rooms_knocked) - .collect() - .await; + let all_rooms: Vec<_> = rooms_joined.chain(rooms_invited).collect().await; for room_id in all_rooms { // ignore errors @@ -1806,40 +1795,7 @@ pub async fn leave_room( user_id: &UserId, room_id: &RoomId, reason: Option, -) -> Result { - let default_member_content = RoomMemberEventContent { - membership: MembershipState::Leave, - reason: reason.clone(), - join_authorized_via_users_server: None, - is_direct: None, - avatar_url: None, - displayname: None, - third_party_invite: None, - blurhash: None, - }; - - if services.rooms.metadata.is_banned(room_id).await - || services.rooms.metadata.is_disabled(room_id).await - { - // the room is banned/disabled, the room must be rejected locally since we - // cant/dont want to federate with this server - services - .rooms - .state_cache - .update_membership( - room_id, - user_id, - default_member_content, - user_id, - None, - None, - true, - ) - .await?; - - return Ok(()); - } - +) -> Result<()> { // Ask a remote server if we don't have this room and are not knocking on it if !services .rooms @@ -1872,7 +1828,7 @@ pub async fn leave_room( .update_membership( room_id, user_id, - default_member_content, + RoomMemberEventContent::new(MembershipState::Leave), user_id, last_state, None, @@ -1892,23 +1848,26 @@ pub async fn leave_room( ) .await else { - debug_warn!( + // Fix for broken rooms + warn!( "Trying to leave a room you are not a member of, marking room as left locally." ); - return services + services .rooms .state_cache .update_membership( room_id, user_id, - default_member_content, + RoomMemberEventContent::new(MembershipState::Leave), user_id, None, None, true, ) - .await; + .await?; + + return Ok(()); }; services @@ -1938,7 +1897,7 @@ async fn remote_leave_room( room_id: &RoomId, ) -> Result<()> { let mut make_leave_response_and_server = - Err!(BadServerResponse("No remote server available to assist in leaving {room_id}.")); + Err!(BadServerResponse("No server available to assist in leaving.")); let mut servers: HashSet = services .rooms @@ -2018,25 +1977,20 @@ async fn remote_leave_room( let (make_leave_response, remote_server) = make_leave_response_and_server?; let Some(room_version_id) = make_leave_response.room_version else { - return Err!(BadServerResponse(warn!( - "No room version was returned by {remote_server} for {room_id}, room version is \ - likely not supported by conduwuit" - ))); + return Err!(BadServerResponse("Remote room version is not supported by conduwuit")); }; if !services.server.supported_room_version(&room_version_id) { - return Err!(BadServerResponse(warn!( - "Remote room version {room_version_id} for {room_id} is not supported by conduwuit", - ))); + return Err!(BadServerResponse( + "Remote room version {room_version_id} is not supported by conduwuit" + )); } let mut leave_event_stub = serde_json::from_str::( make_leave_response.event.get(), ) .map_err(|e| { - err!(BadServerResponse(warn!( - "Invalid make_leave event json received from {remote_server} for {room_id}: {e:?}" - ))) + err!(BadServerResponse("Invalid make_leave event json received from server: {e:?}")) })?; // TODO: Is origin needed? diff --git a/src/api/client/message.rs b/src/api/client/message.rs index db11ef4a..03c7335a 100644 --- a/src/api/client/message.rs +++ b/src/api/client/message.rs @@ -1,24 +1,12 @@ use axum::extract::State; use conduwuit::{ - Err, Result, at, - matrix::{ - Event, - pdu::{PduCount, PduEvent}, - }, + Err, Event, PduCount, PduEvent, Result, at, utils::{ IterStream, ReadyExt, result::{FlatOk, LogErr}, stream::{BroadbandExt, TryIgnore, WidebandExt}, }, }; -use conduwuit_service::{ - Services, - rooms::{ - lazy_loading, - lazy_loading::{Options, Witness}, - timeline::PdusIterItem, - }, -}; use futures::{FutureExt, StreamExt, TryFutureExt, future::OptionFuture, pin_mut}; use ruma::{ RoomId, UserId, @@ -29,6 +17,14 @@ use ruma::{ events::{AnyStateEvent, StateEventType, TimelineEventType, TimelineEventType::*}, serde::Raw, }; +use service::{ + Services, + rooms::{ + lazy_loading, + lazy_loading::{Options, Witness}, + timeline::PdusIterItem, + }, +}; use crate::Ruma; @@ -261,9 +257,10 @@ pub(crate) async fn is_ignored_pdu( let ignored_type = IGNORED_MESSAGE_TYPES.binary_search(&pdu.kind).is_ok(); let ignored_server = services + .server .config .forbidden_remote_server_names - .is_match(pdu.sender().server_name().host()); + .contains(pdu.sender().server_name()); if ignored_type && (ignored_server || services.users.user_is_ignored(&pdu.sender, user_id).await) diff --git a/src/api/client/openid.rs b/src/api/client/openid.rs index 8d2de68d..671d0c6d 100644 --- a/src/api/client/openid.rs +++ b/src/api/client/openid.rs @@ -1,14 +1,14 @@ use std::time::Duration; use axum::extract::State; -use conduwuit::{Error, Result, utils}; +use conduwuit::utils; use ruma::{ api::client::{account, error::ErrorKind}, authentication::TokenType, }; use super::TOKEN_LENGTH; -use crate::Ruma; +use crate::{Error, Result, Ruma}; /// # `POST /_matrix/client/v3/user/{userId}/openid/request_token` /// diff --git a/src/api/client/profile.rs b/src/api/client/profile.rs index 3699b590..5abe5b23 100644 --- a/src/api/client/profile.rs +++ b/src/api/client/profile.rs @@ -3,11 +3,10 @@ use std::collections::BTreeMap; use axum::extract::State; use conduwuit::{ Err, Error, Result, - matrix::pdu::PduBuilder, + pdu::PduBuilder, utils::{IterStream, stream::TryIgnore}, warn, }; -use conduwuit_service::Services; use futures::{StreamExt, TryStreamExt, future::join3}; use ruma::{ OwnedMxcUri, OwnedRoomId, UserId, @@ -23,6 +22,7 @@ use ruma::{ events::room::member::{MembershipState, RoomMemberEventContent}, presence::PresenceState, }; +use service::Services; use crate::Ruma; diff --git a/src/api/client/push.rs b/src/api/client/push.rs index 81020ffa..cc1d3be2 100644 --- a/src/api/client/push.rs +++ b/src/api/client/push.rs @@ -1,6 +1,5 @@ use axum::extract::State; -use conduwuit::{Err, Error, Result, err}; -use conduwuit_service::Services; +use conduwuit::{Err, err}; use ruma::{ CanonicalJsonObject, CanonicalJsonValue, api::client::{ @@ -20,8 +19,9 @@ use ruma::{ RemovePushRuleError, Ruleset, }, }; +use service::Services; -use crate::Ruma; +use crate::{Error, Result, Ruma}; /// # `GET /_matrix/client/r0/pushrules/` /// diff --git a/src/api/client/read_marker.rs b/src/api/client/read_marker.rs index fbfc8fea..b334e356 100644 --- a/src/api/client/read_marker.rs +++ b/src/api/client/read_marker.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use axum::extract::State; -use conduwuit::{Err, PduCount, Result, err}; +use conduwuit::{Err, PduCount, err}; use ruma::{ MilliSecondsSinceUnixEpoch, api::client::{read_marker::set_read_marker, receipt::create_receipt}, @@ -11,7 +11,7 @@ use ruma::{ }, }; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `POST /_matrix/client/r0/rooms/{roomId}/read_markers` /// diff --git a/src/api/client/redact.rs b/src/api/client/redact.rs index 8dbe47a6..7b512d06 100644 --- a/src/api/client/redact.rs +++ b/src/api/client/redact.rs @@ -1,10 +1,9 @@ use axum::extract::State; -use conduwuit::{Result, matrix::pdu::PduBuilder}; use ruma::{ api::client::redact::redact_event, events::room::redaction::RoomRedactionEventContent, }; -use crate::Ruma; +use crate::{Result, Ruma, service::pdu::PduBuilder}; /// # `PUT /_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}` /// diff --git a/src/api/client/relations.rs b/src/api/client/relations.rs index b8c2dd4d..7ed40f14 100644 --- a/src/api/client/relations.rs +++ b/src/api/client/relations.rs @@ -1,10 +1,8 @@ use axum::extract::State; use conduwuit::{ - Result, at, - matrix::pdu::PduCount, + PduCount, Result, at, utils::{IterStream, ReadyExt, result::FlatOk, stream::WidebandExt}, }; -use conduwuit_service::{Services, rooms::timeline::PdusIterItem}; use futures::StreamExt; use ruma::{ EventId, RoomId, UInt, UserId, @@ -17,6 +15,7 @@ use ruma::{ }, events::{TimelineEventType, relation::RelationType}, }; +use service::{Services, rooms::timeline::PdusIterItem}; use crate::Ruma; diff --git a/src/api/client/report.rs b/src/api/client/report.rs index 4ee8ebe5..7922caca 100644 --- a/src/api/client/report.rs +++ b/src/api/client/report.rs @@ -2,8 +2,7 @@ use std::time::Duration; use axum::extract::State; use axum_client_ip::InsecureClientIp; -use conduwuit::{Err, Error, Result, debug_info, info, matrix::pdu::PduEvent, utils::ReadyExt}; -use conduwuit_service::Services; +use conduwuit::{Err, info, utils::ReadyExt}; use rand::Rng; use ruma::{ EventId, RoomId, UserId, @@ -16,7 +15,10 @@ use ruma::{ }; use tokio::time::sleep; -use crate::Ruma; +use crate::{ + Error, Result, Ruma, debug_info, + service::{Services, pdu::PduEvent}, +}; /// # `POST /_matrix/client/v3/rooms/{roomId}/report` /// diff --git a/src/api/client/room/create.rs b/src/api/client/room/create.rs index 4ce53f15..bdc5d5a5 100644 --- a/src/api/client/room/create.rs +++ b/src/api/client/room/create.rs @@ -2,11 +2,8 @@ use std::collections::BTreeMap; use axum::extract::State; use conduwuit::{ - Err, Error, Result, debug_info, debug_warn, err, error, info, - matrix::{StateKey, pdu::PduBuilder}, - warn, + Err, Error, Result, StateKey, debug_info, debug_warn, err, error, info, pdu::PduBuilder, warn, }; -use conduwuit_service::{Services, appservice::RegistrationInfo}; use futures::FutureExt; use ruma::{ CanonicalJsonObject, Int, OwnedRoomAliasId, OwnedRoomId, OwnedUserId, RoomId, RoomVersionId, @@ -32,6 +29,7 @@ use ruma::{ serde::{JsonObject, Raw}, }; use serde_json::{json, value::to_raw_value}; +use service::{Services, appservice::RegistrationInfo}; use crate::{Ruma, client::invite_helper}; diff --git a/src/api/client/room/mod.rs b/src/api/client/room/mod.rs index 86d68f7e..16fcadab 100644 --- a/src/api/client/room/mod.rs +++ b/src/api/client/room/mod.rs @@ -2,14 +2,9 @@ mod aliases; mod create; mod event; mod initial_sync; -mod summary; mod upgrade; pub(crate) use self::{ - aliases::get_room_aliases_route, - create::create_room_route, - event::get_room_event_route, - initial_sync::room_initial_sync_route, - summary::{get_room_summary, get_room_summary_legacy}, - upgrade::upgrade_room_route, + aliases::get_room_aliases_route, create::create_room_route, event::get_room_event_route, + initial_sync::room_initial_sync_route, upgrade::upgrade_room_route, }; diff --git a/src/api/client/room/summary.rs b/src/api/client/room/summary.rs deleted file mode 100644 index 67d2e2ad..00000000 --- a/src/api/client/room/summary.rs +++ /dev/null @@ -1,330 +0,0 @@ -use axum::extract::State; -use axum_client_ip::InsecureClientIp; -use conduwuit::{ - Err, Result, debug_warn, trace, - utils::{IterStream, future::TryExtExt}, -}; -use futures::{ - FutureExt, StreamExt, - future::{OptionFuture, join3}, - stream::FuturesUnordered, -}; -use ruma::{ - OwnedServerName, RoomId, UserId, - api::{ - client::room::get_summary, - federation::space::{SpaceHierarchyParentSummary, get_hierarchy}, - }, - events::room::member::MembershipState, - space::SpaceRoomJoinRule::{self, *}, -}; -use service::Services; - -use crate::{Ruma, RumaResponse}; - -/// # `GET /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary` -/// -/// Returns a short description of the state of a room. -/// -/// This is the "wrong" endpoint that some implementations/clients may use -/// according to the MSC. Request and response bodies are the same as -/// `get_room_summary`. -/// -/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) -pub(crate) async fn get_room_summary_legacy( - State(services): State, - InsecureClientIp(client): InsecureClientIp, - body: Ruma, -) -> Result> { - get_room_summary(State(services), InsecureClientIp(client), body) - .boxed() - .await - .map(RumaResponse) -} - -/// # `GET /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}` -/// -/// Returns a short description of the state of a room. -/// -/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) -#[tracing::instrument(skip_all, fields(%client), name = "room_summary")] -pub(crate) async fn get_room_summary( - State(services): State, - InsecureClientIp(client): InsecureClientIp, - body: Ruma, -) -> Result { - let (room_id, servers) = services - .rooms - .alias - .resolve_with_servers(&body.room_id_or_alias, Some(body.via.clone())) - .await?; - - if services.rooms.metadata.is_banned(&room_id).await { - return Err!(Request(Forbidden("This room is banned on this homeserver."))); - } - - room_summary_response(&services, &room_id, &servers, body.sender_user.as_deref()) - .boxed() - .await -} - -async fn room_summary_response( - services: &Services, - room_id: &RoomId, - servers: &[OwnedServerName], - sender_user: Option<&UserId>, -) -> Result { - if services - .rooms - .state_cache - .server_in_room(services.globals.server_name(), room_id) - .await - { - return local_room_summary_response(services, room_id, sender_user) - .boxed() - .await; - } - - let room = - remote_room_summary_hierarchy_response(services, room_id, servers, sender_user).await?; - - Ok(get_summary::msc3266::Response { - room_id: room_id.to_owned(), - canonical_alias: room.canonical_alias, - avatar_url: room.avatar_url, - guest_can_join: room.guest_can_join, - name: room.name, - num_joined_members: room.num_joined_members, - topic: room.topic, - world_readable: room.world_readable, - join_rule: room.join_rule, - room_type: room.room_type, - room_version: room.room_version, - encryption: room.encryption, - allowed_room_ids: room.allowed_room_ids, - membership: sender_user.is_some().then_some(MembershipState::Leave), - }) -} - -async fn local_room_summary_response( - services: &Services, - room_id: &RoomId, - sender_user: Option<&UserId>, -) -> Result { - trace!(?sender_user, "Sending local room summary response for {room_id:?}"); - let join_rule = services.rooms.state_accessor.get_join_rules(room_id); - let world_readable = services.rooms.state_accessor.is_world_readable(room_id); - let guest_can_join = services.rooms.state_accessor.guest_can_join(room_id); - - let (join_rule, world_readable, guest_can_join) = - join3(join_rule, world_readable, guest_can_join).await; - trace!("{join_rule:?}, {world_readable:?}, {guest_can_join:?}"); - - user_can_see_summary( - services, - room_id, - &join_rule.clone().into(), - guest_can_join, - world_readable, - join_rule.allowed_rooms(), - sender_user, - ) - .await?; - - let canonical_alias = services - .rooms - .state_accessor - .get_canonical_alias(room_id) - .ok(); - - let name = services.rooms.state_accessor.get_name(room_id).ok(); - - let topic = services.rooms.state_accessor.get_room_topic(room_id).ok(); - - let room_type = services.rooms.state_accessor.get_room_type(room_id).ok(); - - let avatar_url = services - .rooms - .state_accessor - .get_avatar(room_id) - .map(|res| res.into_option().unwrap_or_default().url); - - let room_version = services.rooms.state.get_room_version(room_id).ok(); - - let encryption = services - .rooms - .state_accessor - .get_room_encryption(room_id) - .ok(); - - let num_joined_members = services - .rooms - .state_cache - .room_joined_count(room_id) - .unwrap_or(0); - - let membership: OptionFuture<_> = sender_user - .map(|sender_user| { - services - .rooms - .state_accessor - .get_member(room_id, sender_user) - .map_ok_or(MembershipState::Leave, |content| content.membership) - }) - .into(); - - let ( - canonical_alias, - name, - num_joined_members, - topic, - avatar_url, - room_type, - room_version, - encryption, - membership, - ) = futures::join!( - canonical_alias, - name, - num_joined_members, - topic, - avatar_url, - room_type, - room_version, - encryption, - membership, - ); - - Ok(get_summary::msc3266::Response { - room_id: room_id.to_owned(), - canonical_alias, - avatar_url, - guest_can_join, - name, - num_joined_members: num_joined_members.try_into().unwrap_or_default(), - topic, - world_readable, - room_type, - room_version, - encryption, - membership, - allowed_room_ids: join_rule.allowed_rooms().map(Into::into).collect(), - join_rule: join_rule.into(), - }) -} - -/// used by MSC3266 to fetch a room's info if we do not know about it -async fn remote_room_summary_hierarchy_response( - services: &Services, - room_id: &RoomId, - servers: &[OwnedServerName], - sender_user: Option<&UserId>, -) -> Result { - trace!(?sender_user, ?servers, "Sending remote room summary response for {room_id:?}"); - if !services.config.allow_federation { - return Err!(Request(Forbidden("Federation is disabled."))); - } - - if services.rooms.metadata.is_disabled(room_id).await { - return Err!(Request(Forbidden( - "Federaton of room {room_id} is currently disabled on this server." - ))); - } - - let request = get_hierarchy::v1::Request::new(room_id.to_owned()); - - let mut requests: FuturesUnordered<_> = servers - .iter() - .map(|server| { - services - .sending - .send_federation_request(server, request.clone()) - }) - .collect(); - - while let Some(Ok(response)) = requests.next().await { - trace!("{response:?}"); - let room = response.room.clone(); - if room.room_id != room_id { - debug_warn!( - "Room ID {} returned does not belong to the requested room ID {}", - room.room_id, - room_id - ); - continue; - } - - return user_can_see_summary( - services, - room_id, - &room.join_rule, - room.guest_can_join, - room.world_readable, - room.allowed_room_ids.iter().map(AsRef::as_ref), - sender_user, - ) - .await - .map(|()| room); - } - - Err!(Request(NotFound( - "Room is unknown to this server and was unable to fetch over federation with the \ - provided servers available" - ))) -} - -async fn user_can_see_summary<'a, I>( - services: &Services, - room_id: &RoomId, - join_rule: &SpaceRoomJoinRule, - guest_can_join: bool, - world_readable: bool, - allowed_room_ids: I, - sender_user: Option<&UserId>, -) -> Result -where - I: Iterator + Send, -{ - let is_public_room = matches!(join_rule, Public | Knock | KnockRestricted); - match sender_user { - | Some(sender_user) => { - let user_can_see_state_events = services - .rooms - .state_accessor - .user_can_see_state_events(sender_user, room_id); - let is_guest = services.users.is_deactivated(sender_user).unwrap_or(false); - let user_in_allowed_restricted_room = allowed_room_ids - .stream() - .any(|room| services.rooms.state_cache.is_joined(sender_user, room)); - - let (user_can_see_state_events, is_guest, user_in_allowed_restricted_room) = - join3(user_can_see_state_events, is_guest, user_in_allowed_restricted_room) - .boxed() - .await; - - if user_can_see_state_events - || (is_guest && guest_can_join) - || is_public_room - || user_in_allowed_restricted_room - { - return Ok(()); - } - - Err!(Request(Forbidden( - "Room is not world readable, not publicly accessible/joinable, restricted room \ - conditions not met, and guest access is forbidden. Not allowed to see details \ - of this room." - ))) - }, - | None => { - if is_public_room || world_readable { - return Ok(()); - } - - Err!(Request(Forbidden( - "Room is not world readable or publicly accessible/joinable, authentication is \ - required" - ))) - }, - } -} diff --git a/src/api/client/room/upgrade.rs b/src/api/client/room/upgrade.rs index 9ec0b3bb..4ac341a9 100644 --- a/src/api/client/room/upgrade.rs +++ b/src/api/client/room/upgrade.rs @@ -1,10 +1,7 @@ use std::cmp::max; use axum::extract::State; -use conduwuit::{ - Error, Result, err, info, - matrix::{StateKey, pdu::PduBuilder}, -}; +use conduwuit::{Error, Result, StateKey, err, info, pdu::PduBuilder}; use futures::StreamExt; use ruma::{ CanonicalJsonObject, RoomId, RoomVersionId, @@ -106,7 +103,7 @@ pub(crate) async fn upgrade_room_route( // Use the m.room.tombstone event as the predecessor let predecessor = Some(ruma::events::room::create::PreviousRoom::new( body.room_id.clone(), - Some(tombstone_event_id), + (*tombstone_event_id).to_owned(), )); // Send a m.room.create event containing a predecessor field and the applicable diff --git a/src/api/client/search.rs b/src/api/client/search.rs index d4dcde57..d66df881 100644 --- a/src/api/client/search.rs +++ b/src/api/client/search.rs @@ -2,12 +2,10 @@ use std::collections::BTreeMap; use axum::extract::State; use conduwuit::{ - Err, Result, at, is_true, - matrix::pdu::PduEvent, + Err, PduEvent, Result, at, is_true, result::FlatOk, utils::{IterStream, stream::ReadyExt}, }; -use conduwuit_service::{Services, rooms::search::RoomQuery}; use futures::{FutureExt, StreamExt, TryFutureExt, TryStreamExt, future::OptionFuture}; use ruma::{ OwnedRoomId, RoomId, UInt, UserId, @@ -19,6 +17,7 @@ use ruma::{ serde::Raw, }; use search_events::v3::{Request, Response}; +use service::{Services, rooms::search::RoomQuery}; use crate::Ruma; diff --git a/src/api/client/send.rs b/src/api/client/send.rs index f753fa65..1af74f57 100644 --- a/src/api/client/send.rs +++ b/src/api/client/send.rs @@ -1,11 +1,11 @@ use std::collections::BTreeMap; use axum::extract::State; -use conduwuit::{Err, Result, err, matrix::pdu::PduBuilder, utils}; +use conduwuit::{Err, err}; use ruma::{api::client::message::send_message_event, events::MessageLikeEventType}; use serde_json::from_str; -use crate::Ruma; +use crate::{Result, Ruma, service::pdu::PduBuilder, utils}; /// # `PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}` /// diff --git a/src/api/client/session.rs b/src/api/client/session.rs index 2499a43d..3de625e4 100644 --- a/src/api/client/session.rs +++ b/src/api/client/session.rs @@ -2,11 +2,7 @@ use std::time::Duration; use axum::extract::State; use axum_client_ip::InsecureClientIp; -use conduwuit::{ - Err, Error, Result, debug, err, info, utils, - utils::{ReadyExt, hash}, -}; -use conduwuit_service::uiaa::SESSION_ID_LENGTH; +use conduwuit::{Err, debug, err, info, utils::ReadyExt}; use futures::StreamExt; use ruma::{ UserId, @@ -26,9 +22,10 @@ use ruma::{ uiaa, }, }; +use service::uiaa::SESSION_ID_LENGTH; use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH}; -use crate::Ruma; +use crate::{Error, Result, Ruma, utils, utils::hash}; /// # `GET /_matrix/client/v3/login` /// diff --git a/src/api/client/space.rs b/src/api/client/space.rs index 4eee9d76..567ac62f 100644 --- a/src/api/client/space.rs +++ b/src/api/client/space.rs @@ -8,16 +8,16 @@ use conduwuit::{ Err, Result, utils::{future::TryExtExt, stream::IterStream}, }; -use conduwuit_service::{ +use futures::{StreamExt, TryFutureExt, future::OptionFuture}; +use ruma::{ + OwnedRoomId, OwnedServerName, RoomId, UInt, UserId, api::client::space::get_hierarchy, +}; +use service::{ Services, rooms::spaces::{ PaginationToken, SummaryAccessibility, get_parent_children_via, summary_to_chunk, }, }; -use futures::{StreamExt, TryFutureExt, future::OptionFuture}; -use ruma::{ - OwnedRoomId, OwnedServerName, RoomId, UInt, UserId, api::client::space::get_hierarchy, -}; use crate::Ruma; diff --git a/src/api/client/state.rs b/src/api/client/state.rs index 2ddc8f14..9563c26d 100644 --- a/src/api/client/state.rs +++ b/src/api/client/state.rs @@ -1,10 +1,5 @@ use axum::extract::State; -use conduwuit::{ - Err, Result, err, - matrix::pdu::{PduBuilder, PduEvent}, - utils::BoolExt, -}; -use conduwuit_service::Services; +use conduwuit::{Err, PduEvent, Result, err, pdu::PduBuilder, utils::BoolExt}; use futures::TryStreamExt; use ruma::{ OwnedEventId, RoomId, UserId, @@ -21,6 +16,7 @@ use ruma::{ }, serde::Raw, }; +use service::Services; use crate::{Ruma, RumaResponse}; @@ -211,7 +207,7 @@ async fn allowed_to_send_state_event( // irreversible mistakes match json.deserialize_as::() { | Ok(acl_content) => { - if acl_content.allow_is_empty() { + if acl_content.allow.is_empty() { return Err!(Request(BadJson(debug_warn!( ?room_id, "Sending an ACL event with an empty allow key will permanently \ @@ -220,7 +216,9 @@ async fn allowed_to_send_state_event( )))); } - if acl_content.deny_contains("*") && acl_content.allow_contains("*") { + if acl_content.deny.contains(&String::from("*")) + && acl_content.allow.contains(&String::from("*")) + { return Err!(Request(BadJson(debug_warn!( ?room_id, "Sending an ACL event with a deny and allow key value of \"*\" will \ @@ -229,9 +227,8 @@ async fn allowed_to_send_state_event( )))); } - if acl_content.deny_contains("*") + if acl_content.deny.contains(&String::from("*")) && !acl_content.is_allowed(services.globals.server_name()) - && !acl_content.allow_contains(services.globals.server_name().as_str()) { return Err!(Request(BadJson(debug_warn!( ?room_id, @@ -241,9 +238,8 @@ async fn allowed_to_send_state_event( )))); } - if !acl_content.allow_contains("*") + if !acl_content.allow.contains(&String::from("*")) && !acl_content.is_allowed(services.globals.server_name()) - && !acl_content.allow_contains(services.globals.server_name().as_str()) { return Err!(Request(BadJson(debug_warn!( ?room_id, diff --git a/src/api/client/sync/mod.rs b/src/api/client/sync/mod.rs index 14459acf..3eab76cc 100644 --- a/src/api/client/sync/mod.rs +++ b/src/api/client/sync/mod.rs @@ -3,14 +3,12 @@ mod v4; mod v5; use conduwuit::{ - Error, PduCount, Result, - matrix::pdu::PduEvent, + PduCount, utils::{ IterStream, stream::{BroadbandExt, ReadyExt, TryIgnore}, }, }; -use conduwuit_service::Services; use futures::{StreamExt, pin_mut}; use ruma::{ RoomId, UserId, @@ -23,6 +21,7 @@ use ruma::{ pub(crate) use self::{ v3::sync_events_route, v4::sync_events_v4_route, v5::sync_events_v5_route, }; +use crate::{Error, PduEvent, Result, service::Services}; pub(crate) const DEFAULT_BUMP_TYPES: &[TimelineEventType; 6] = &[CallInvite, PollStart, Beacon, RoomEncrypted, RoomMessage, Sticker]; diff --git a/src/api/client/sync/v3.rs b/src/api/client/sync/v3.rs index 24930941..530c1278 100644 --- a/src/api/client/sync/v3.rs +++ b/src/api/client/sync/v3.rs @@ -6,20 +6,15 @@ use std::{ use axum::extract::State; use conduwuit::{ - Result, at, err, error, extract_variant, is_equal_to, - matrix::{ - Event, - pdu::{EventHash, PduCount, PduEvent}, - }, - pair_of, ref_at, + PduCount, PduEvent, Result, at, err, error, extract_variant, is_equal_to, pair_of, + pdu::{Event, EventHash}, + ref_at, result::FlatOk, utils::{ self, BoolExt, IterStream, ReadyExt, TryFutureExtExt, - future::OptionStream, math::ruma_from_u64, stream::{BroadbandExt, Tools, TryExpect, WidebandExt}, }, - warn, }; use conduwuit_service::{ Services, @@ -433,12 +428,9 @@ async fn handle_left_room( return Ok(None); } - if !services.rooms.metadata.exists(room_id).await - || services.rooms.metadata.is_disabled(room_id).await - || services.rooms.metadata.is_banned(room_id).await - { + if !services.rooms.metadata.exists(room_id).await { // This is just a rejected invite, not a room we know - // Insert a leave event anyways for the client + // Insert a leave event anyways let event = PduEvent { event_id: EventId::new(services.globals.server_name()), sender: sender_user.to_owned(), @@ -497,7 +489,7 @@ async fn handle_left_room( .room_state_get_id(room_id, &StateEventType::RoomMember, sender_user.as_str()) .await else { - warn!("Left {room_id} but no left state event"); + error!("Left room but no left state event"); return Ok(None); }; @@ -507,7 +499,7 @@ async fn handle_left_room( .pdu_shortstatehash(&left_event_id) .await else { - warn!(event_id = %left_event_id, "Leave event has no state in {room_id}"); + error!(event_id = %left_event_id, "Leave event has no state"); return Ok(None); }; @@ -1037,7 +1029,7 @@ async fn calculate_state_incremental<'a>( }) .into(); - let state_diff_ids: OptionFuture<_> = (!full_state && state_changed) + let state_diff: OptionFuture<_> = (!full_state && state_changed) .then(|| { StreamExt::into_future( services @@ -1062,9 +1054,45 @@ async fn calculate_state_incremental<'a>( }) .into(); + let lazy_state_ids = lazy_state_ids + .map(|opt| { + opt.map(|(curr, next)| { + let opt = curr; + let iter = Option::into_iter(opt); + IterStream::stream(iter).chain(next) + }) + }) + .map(Option::into_iter) + .map(IterStream::stream) + .flatten_stream() + .flatten(); + + let state_diff_ids = state_diff + .map(|opt| { + opt.map(|(curr, next)| { + let opt = curr; + let iter = Option::into_iter(opt); + IterStream::stream(iter).chain(next) + }) + }) + .map(Option::into_iter) + .map(IterStream::stream) + .flatten_stream() + .flatten(); + let state_events = current_state_ids - .stream() - .chain(state_diff_ids.stream()) + .map(|opt| { + opt.map(|(curr, next)| { + let opt = curr; + let iter = Option::into_iter(opt); + IterStream::stream(iter).chain(next) + }) + }) + .map(Option::into_iter) + .map(IterStream::stream) + .flatten_stream() + .flatten() + .chain(state_diff_ids) .broad_filter_map(|(shortstatekey, shorteventid)| async move { if witness.is_none() || encrypted_room { return Some(shorteventid); @@ -1072,7 +1100,7 @@ async fn calculate_state_incremental<'a>( lazy_filter(services, sender_user, shortstatekey, shorteventid).await }) - .chain(lazy_state_ids.stream()) + .chain(lazy_state_ids) .broad_filter_map(|shorteventid| { services .rooms diff --git a/src/api/client/sync/v4.rs b/src/api/client/sync/v4.rs index f7edb8c0..7e902973 100644 --- a/src/api/client/sync/v4.rs +++ b/src/api/client/sync/v4.rs @@ -438,10 +438,7 @@ pub(crate) async fn sync_events_v4_route( let mut known_subscription_rooms = BTreeSet::new(); for (room_id, room) in &body.room_subscriptions { - if !services.rooms.metadata.exists(room_id).await - || services.rooms.metadata.is_disabled(room_id).await - || services.rooms.metadata.is_banned(room_id).await - { + if !services.rooms.metadata.exists(room_id).await { continue; } let todo_room = diff --git a/src/api/client/sync/v5.rs b/src/api/client/sync/v5.rs index 684752ec..48b41b21 100644 --- a/src/api/client/sync/v5.rs +++ b/src/api/client/sync/v5.rs @@ -6,19 +6,13 @@ use std::{ use axum::extract::State; use conduwuit::{ - Error, Result, debug, error, extract_variant, - matrix::{ - TypeStateKey, - pdu::{PduCount, PduEvent}, - }, - trace, + Error, PduEvent, Result, TypeStateKey, debug, error, extract_variant, trace, utils::{ BoolExt, IterStream, ReadyExt, TryFutureExtExt, math::{ruma_from_usize, usize_from_ruma}, }, warn, }; -use conduwuit_service::rooms::read_receipt::pack_receipts; use futures::{FutureExt, StreamExt, TryFutureExt}; use ruma::{ DeviceId, OwnedEventId, OwnedRoomId, RoomId, UInt, UserId, @@ -33,6 +27,7 @@ use ruma::{ serde::Raw, uint, }; +use service::{PduCount, rooms::read_receipt::pack_receipts}; use super::{filter_rooms, share_encrypted_room}; use crate::{ @@ -219,10 +214,7 @@ async fn fetch_subscriptions( ) { let mut known_subscription_rooms = BTreeSet::new(); for (room_id, room) in &body.room_subscriptions { - if !services.rooms.metadata.exists(room_id).await - || services.rooms.metadata.is_disabled(room_id).await - || services.rooms.metadata.is_banned(room_id).await - { + if !services.rooms.metadata.exists(room_id).await { continue; } let todo_room = diff --git a/src/api/client/tag.rs b/src/api/client/tag.rs index caafe10d..3b3b40d4 100644 --- a/src/api/client/tag.rs +++ b/src/api/client/tag.rs @@ -1,7 +1,6 @@ use std::collections::BTreeMap; use axum::extract::State; -use conduwuit::Result; use ruma::{ api::client::tag::{create_tag, delete_tag, get_tags}, events::{ @@ -10,7 +9,7 @@ use ruma::{ }, }; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}` /// diff --git a/src/api/client/thirdparty.rs b/src/api/client/thirdparty.rs index 0713a882..790b27d3 100644 --- a/src/api/client/thirdparty.rs +++ b/src/api/client/thirdparty.rs @@ -1,9 +1,8 @@ use std::collections::BTreeMap; -use conduwuit::Result; use ruma::api::client::thirdparty::get_protocols; -use crate::{Ruma, RumaResponse}; +use crate::{Result, Ruma, RumaResponse}; /// # `GET /_matrix/client/r0/thirdparty/protocols` /// diff --git a/src/api/client/threads.rs b/src/api/client/threads.rs index 5b838bef..00bfe553 100644 --- a/src/api/client/threads.rs +++ b/src/api/client/threads.rs @@ -1,12 +1,9 @@ use axum::extract::State; -use conduwuit::{ - Result, at, - matrix::pdu::{PduCount, PduEvent}, -}; +use conduwuit::{PduCount, PduEvent, at}; use futures::StreamExt; use ruma::{api::client::threads::get_threads, uint}; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `GET /_matrix/client/r0/rooms/{roomId}/threads` pub(crate) async fn get_threads_route( diff --git a/src/api/client/to_device.rs b/src/api/client/to_device.rs index 8ad9dc99..1b942fba 100644 --- a/src/api/client/to_device.rs +++ b/src/api/client/to_device.rs @@ -2,7 +2,6 @@ use std::collections::BTreeMap; use axum::extract::State; use conduwuit::{Error, Result}; -use conduwuit_service::sending::EduBuf; use futures::StreamExt; use ruma::{ api::{ @@ -11,6 +10,7 @@ use ruma::{ }, to_device::DeviceIdOrAllDevices, }; +use service::sending::EduBuf; use crate::Ruma; diff --git a/src/api/client/typing.rs b/src/api/client/typing.rs index 1d8d02fd..b02cc473 100644 --- a/src/api/client/typing.rs +++ b/src/api/client/typing.rs @@ -1,8 +1,8 @@ use axum::extract::State; -use conduwuit::{Err, Result, utils, utils::math::Tried}; +use conduwuit::{Err, utils::math::Tried}; use ruma::api::client::typing::create_typing_event; -use crate::Ruma; +use crate::{Result, Ruma, utils}; /// # `PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}` /// diff --git a/src/api/client/unstable.rs b/src/api/client/unstable.rs index e21eaf21..45ad103e 100644 --- a/src/api/client/unstable.rs +++ b/src/api/client/unstable.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use axum::extract::State; use axum_client_ip::InsecureClientIp; -use conduwuit::{Err, Error, Result}; +use conduwuit::Err; use futures::StreamExt; use ruma::{ OwnedRoomId, @@ -14,14 +14,16 @@ use ruma::{ delete_profile_key, delete_timezone_key, get_profile_key, get_timezone_key, set_profile_key, set_timezone_key, }, + room::get_summary, }, federation, }, + events::room::member::MembershipState, presence::PresenceState, }; use super::{update_avatar_url, update_displayname}; -use crate::Ruma; +use crate::{Error, Result, Ruma, RumaResponse}; /// # `GET /_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms` /// @@ -36,10 +38,13 @@ pub(crate) async fn get_mutual_rooms_route( InsecureClientIp(client): InsecureClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - if sender_user == body.user_id { - return Err!(Request(Unknown("You cannot request rooms in common with yourself."))); + if sender_user == &body.user_id { + return Err(Error::BadRequest( + ErrorKind::Unknown, + "You cannot request rooms in common with yourself.", + )); } if !services.users.exists(&body.user_id).await { @@ -60,6 +65,129 @@ pub(crate) async fn get_mutual_rooms_route( }) } +/// # `GET /_matrix/client/unstable/im.nheko.summary/rooms/{roomIdOrAlias}/summary` +/// +/// Returns a short description of the state of a room. +/// +/// This is the "wrong" endpoint that some implementations/clients may use +/// according to the MSC. Request and response bodies are the same as +/// `get_room_summary`. +/// +/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) +pub(crate) async fn get_room_summary_legacy( + State(services): State, + InsecureClientIp(client): InsecureClientIp, + body: Ruma, +) -> Result> { + get_room_summary(State(services), InsecureClientIp(client), body) + .await + .map(RumaResponse) +} + +/// # `GET /_matrix/client/unstable/im.nheko.summary/summary/{roomIdOrAlias}` +/// +/// Returns a short description of the state of a room. +/// +/// TODO: support fetching remote room info if we don't know the room +/// +/// An implementation of [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266) +#[tracing::instrument(skip_all, fields(%client), name = "room_summary")] +pub(crate) async fn get_room_summary( + State(services): State, + InsecureClientIp(client): InsecureClientIp, + body: Ruma, +) -> Result { + let sender_user = body.sender_user.as_ref(); + + let room_id = services.rooms.alias.resolve(&body.room_id_or_alias).await?; + + if !services.rooms.metadata.exists(&room_id).await { + return Err(Error::BadRequest(ErrorKind::NotFound, "Room is unknown to this server")); + } + + if sender_user.is_none() + && !services + .rooms + .state_accessor + .is_world_readable(&room_id) + .await + { + return Err(Error::BadRequest( + ErrorKind::forbidden(), + "Room is not world readable, authentication is required", + )); + } + + Ok(get_summary::msc3266::Response { + room_id: room_id.clone(), + canonical_alias: services + .rooms + .state_accessor + .get_canonical_alias(&room_id) + .await + .ok(), + avatar_url: services + .rooms + .state_accessor + .get_avatar(&room_id) + .await + .into_option() + .unwrap_or_default() + .url, + guest_can_join: services.rooms.state_accessor.guest_can_join(&room_id).await, + name: services.rooms.state_accessor.get_name(&room_id).await.ok(), + num_joined_members: services + .rooms + .state_cache + .room_joined_count(&room_id) + .await + .unwrap_or(0) + .try_into()?, + topic: services + .rooms + .state_accessor + .get_room_topic(&room_id) + .await + .ok(), + world_readable: services + .rooms + .state_accessor + .is_world_readable(&room_id) + .await, + join_rule: services + .rooms + .state_accessor + .get_join_rule(&room_id) + .await + .unwrap_or_default() + .0, + room_type: services + .rooms + .state_accessor + .get_room_type(&room_id) + .await + .ok(), + room_version: services.rooms.state.get_room_version(&room_id).await.ok(), + membership: if let Some(sender_user) = sender_user { + services + .rooms + .state_accessor + .get_member(&room_id, sender_user) + .await + .map_or_else(|_| MembershipState::Leave, |content| content.membership) + .into() + } else { + None + }, + encryption: services + .rooms + .state_accessor + .get_room_encryption(&room_id) + .await + .ok(), + }) +} + /// # `DELETE /_matrix/client/unstable/uk.tcpip.msc4133/profile/:user_id/us.cloke.msc4175.tz` /// /// Deletes the `tz` (timezone) of a user, as per MSC4133 and MSC4175. diff --git a/src/api/client/unversioned.rs b/src/api/client/unversioned.rs index 232d5b28..4e2b7d9d 100644 --- a/src/api/client/unversioned.rs +++ b/src/api/client/unversioned.rs @@ -1,11 +1,10 @@ use std::collections::BTreeMap; use axum::{Json, extract::State, response::IntoResponse}; -use conduwuit::Result; use futures::StreamExt; use ruma::api::client::discovery::get_supported_versions; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `GET /_matrix/client/versions` /// diff --git a/src/api/client/user_directory.rs b/src/api/client/user_directory.rs index 99b3bb67..c5d79a56 100644 --- a/src/api/client/user_directory.rs +++ b/src/api/client/user_directory.rs @@ -1,19 +1,15 @@ use axum::extract::State; -use conduwuit::{ - Result, - utils::{future::BoolExt, stream::BroadbandExt}, -}; -use futures::{FutureExt, StreamExt, pin_mut}; +use conduwuit::utils::TryFutureExtExt; +use futures::{StreamExt, pin_mut}; use ruma::{ - api::client::user_directory::search_users::{self}, - events::room::join_rules::JoinRule, + api::client::user_directory::search_users, + events::{ + StateEventType, + room::join_rules::{JoinRule, RoomJoinRulesEventContent}, + }, }; -use crate::Ruma; - -// conduwuit can handle a lot more results than synapse -const LIMIT_MAX: usize = 500; -const LIMIT_DEFAULT: usize = 10; +use crate::{Result, Ruma}; /// # `POST /_matrix/client/r0/user_directory/search` /// @@ -25,63 +21,78 @@ pub(crate) async fn search_users_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let limit = usize::try_from(body.limit) - .map_or(LIMIT_DEFAULT, usize::from) - .min(LIMIT_MAX); + let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + let limit = usize::try_from(body.limit).map_or(10, usize::from).min(100); // default limit is 10 - let mut users = services - .users - .stream() - .map(ToOwned::to_owned) - .broad_filter_map(async |user_id| { - let user = search_users::v3::User { - user_id: user_id.clone(), - display_name: services.users.displayname(&user_id).await.ok(), - avatar_url: services.users.avatar_url(&user_id).await.ok(), - }; + let users = services.users.stream().filter_map(|user_id| async { + // Filter out buggy users (they should not exist, but you never know...) + let user = search_users::v3::User { + user_id: user_id.to_owned(), + display_name: services.users.displayname(user_id).await.ok(), + avatar_url: services.users.avatar_url(user_id).await.ok(), + }; - let user_id_matches = user - .user_id - .as_str() - .to_lowercase() - .contains(&body.search_term.to_lowercase()); + let user_id_matches = user + .user_id + .to_string() + .to_lowercase() + .contains(&body.search_term.to_lowercase()); - let user_displayname_matches = user.display_name.as_ref().is_some_and(|name| { + let user_displayname_matches = user + .display_name + .as_ref() + .filter(|name| { name.to_lowercase() .contains(&body.search_term.to_lowercase()) - }); + }) + .is_some(); - if !user_id_matches && !user_displayname_matches { - return None; + if !user_id_matches && !user_displayname_matches { + return None; + } + + // It's a matching user, but is the sender allowed to see them? + let mut user_visible = false; + + let user_is_in_public_rooms = services + .rooms + .state_cache + .rooms_joined(&user.user_id) + .any(|room| { + services + .rooms + .state_accessor + .room_state_get_content::( + room, + &StateEventType::RoomJoinRules, + "", + ) + .map_ok_or(false, |content| content.join_rule == JoinRule::Public) + }) + .await; + + if user_is_in_public_rooms { + user_visible = true; + } else { + let user_is_in_shared_rooms = services + .rooms + .state_cache + .user_sees_user(sender_user, &user.user_id) + .await; + + if user_is_in_shared_rooms { + user_visible = true; } + } - let user_in_public_room = services - .rooms - .state_cache - .rooms_joined(&user_id) - .map(ToOwned::to_owned) - .any(|room| async move { - services - .rooms - .state_accessor - .get_join_rules(&room) - .map(|rule| matches!(rule, JoinRule::Public)) - .await - }); + user_visible.then_some(user) + }); - let user_sees_user = services - .rooms - .state_cache - .user_sees_user(sender_user, &user_id); + pin_mut!(users); - pin_mut!(user_in_public_room, user_sees_user); + let limited = users.by_ref().next().await.is_some(); - user_in_public_room.or(user_sees_user).await.then_some(user) - }); - - let results = users.by_ref().take(limit).collect().await; - let limited = users.next().await.is_some(); + let results = users.take(limit).collect().await; Ok(search_users::v3::Response { results, limited }) } diff --git a/src/api/client/voip.rs b/src/api/client/voip.rs index 91991d24..37e67984 100644 --- a/src/api/client/voip.rs +++ b/src/api/client/voip.rs @@ -2,12 +2,12 @@ use std::time::{Duration, SystemTime}; use axum::extract::State; use base64::{Engine as _, engine::general_purpose}; -use conduwuit::{Err, Result, utils}; +use conduwuit::{Err, utils}; use hmac::{Hmac, Mac}; use ruma::{SecondsSinceUnixEpoch, UserId, api::client::voip::get_turn_server_info}; use sha1::Sha1; -use crate::Ruma; +use crate::{Result, Ruma}; const RANDOM_USER_ID_LENGTH: usize = 10; diff --git a/src/api/client/well_known.rs b/src/api/client/well_known.rs index eedab981..abda61b0 100644 --- a/src/api/client/well_known.rs +++ b/src/api/client/well_known.rs @@ -1,5 +1,4 @@ use axum::{Json, extract::State, response::IntoResponse}; -use conduwuit::{Error, Result}; use ruma::api::client::{ discovery::{ discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo}, @@ -8,7 +7,7 @@ use ruma::api::client::{ error::ErrorKind, }; -use crate::Ruma; +use crate::{Error, Result, Ruma}; /// # `GET /.well-known/matrix/client` /// diff --git a/src/api/mod.rs b/src/api/mod.rs index 9ca24e72..090cf897 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -8,6 +8,8 @@ pub mod server; extern crate conduwuit_core as conduwuit; extern crate conduwuit_service as service; +pub(crate) use conduwuit::{Error, Result, debug_info, pdu::PduEvent, utils}; + pub(crate) use self::router::{Ruma, RumaResponse, State}; conduwuit::mod_ctor! {} diff --git a/src/api/router/auth.rs b/src/api/router/auth.rs index 0eb61ca6..5cd7b831 100644 --- a/src/api/router/auth.rs +++ b/src/api/router/auth.rs @@ -317,9 +317,10 @@ fn auth_server_checks(services: &Services, x_matrix: &XMatrix) -> Result<()> { let origin = &x_matrix.origin; if services + .server .config .forbidden_remote_server_names - .is_match(origin.host()) + .contains(origin) { return Err!(Request(Forbidden(debug_warn!( "Federation requests from {origin} denied." diff --git a/src/api/server/backfill.rs b/src/api/server/backfill.rs index 3cfbcedc..5c875807 100644 --- a/src/api/server/backfill.rs +++ b/src/api/server/backfill.rs @@ -6,17 +6,11 @@ use conduwuit::{ utils::{IterStream, ReadyExt, stream::TryTools}, }; use futures::{FutureExt, StreamExt, TryStreamExt}; -use ruma::{MilliSecondsSinceUnixEpoch, api::federation::backfill::get_backfill}; +use ruma::{MilliSecondsSinceUnixEpoch, api::federation::backfill::get_backfill, uint}; use super::AccessCheck; use crate::Ruma; -/// arbitrary number but synapse's is 100 and we can handle lots of these -/// anyways -const LIMIT_MAX: usize = 150; -/// no spec defined number but we can handle a lot of these -const LIMIT_DEFAULT: usize = 50; - /// # `GET /_matrix/federation/v1/backfill/` /// /// Retrieves events from before the sender joined the room, if the room's @@ -36,9 +30,9 @@ pub(crate) async fn get_backfill_route( let limit = body .limit + .min(uint!(100)) .try_into() - .unwrap_or(LIMIT_DEFAULT) - .min(LIMIT_MAX); + .expect("UInt could not be converted to usize"); let from = body .v diff --git a/src/api/server/get_missing_events.rs b/src/api/server/get_missing_events.rs index 04dc30ed..3d0bbb07 100644 --- a/src/api/server/get_missing_events.rs +++ b/src/api/server/get_missing_events.rs @@ -1,15 +1,13 @@ use axum::extract::State; -use conduwuit::{Result, debug, debug_error, utils::to_canonical_object}; -use ruma::api::federation::event::get_missing_events; +use conduwuit::{Error, Result}; +use ruma::{ + CanonicalJsonValue, EventId, RoomId, + api::{client::error::ErrorKind, federation::event::get_missing_events}, +}; use super::AccessCheck; use crate::Ruma; -/// arbitrary number but synapse's is 20 and we can handle lots of these anyways -const LIMIT_MAX: usize = 50; -/// spec says default is 10 -const LIMIT_DEFAULT: usize = 10; - /// # `POST /_matrix/federation/v1/get_missing_events/{roomId}` /// /// Retrieves events that the sender is missing. @@ -26,11 +24,7 @@ pub(crate) async fn get_missing_events_route( .check() .await?; - let limit = body - .limit - .try_into() - .unwrap_or(LIMIT_DEFAULT) - .min(LIMIT_MAX); + let limit = body.limit.try_into()?; let mut queued_events = body.latest_events.clone(); // the vec will never have more entries the limit @@ -38,52 +32,60 @@ pub(crate) async fn get_missing_events_route( let mut i: usize = 0; while i < queued_events.len() && events.len() < limit { - let Ok(pdu) = services.rooms.timeline.get_pdu(&queued_events[i]).await else { - debug!( - ?body.origin, - "Event {} does not exist locally, skipping", &queued_events[i] - ); - i = i.saturating_add(1); - continue; - }; - - if body.earliest_events.contains(&queued_events[i]) { - i = i.saturating_add(1); - continue; - } - - if !services + if let Ok(pdu) = services .rooms - .state_accessor - .server_can_see_event(body.origin(), &body.room_id, &queued_events[i]) + .timeline + .get_pdu_json(&queued_events[i]) .await { - debug!( - ?body.origin, - "Server cannot see {:?} in {:?}, skipping", pdu.event_id, pdu.room_id + let room_id_str = pdu + .get("room_id") + .and_then(|val| val.as_str()) + .ok_or_else(|| Error::bad_database("Invalid event in database."))?; + + let event_room_id = <&RoomId>::try_from(room_id_str) + .map_err(|_| Error::bad_database("Invalid room_id in event in database."))?; + + if event_room_id != body.room_id { + return Err(Error::BadRequest(ErrorKind::InvalidParam, "Event from wrong room.")); + } + + if body.earliest_events.contains(&queued_events[i]) { + i = i.saturating_add(1); + continue; + } + + if !services + .rooms + .state_accessor + .server_can_see_event(body.origin(), &body.room_id, &queued_events[i]) + .await + { + i = i.saturating_add(1); + continue; + } + + let prev_events = pdu + .get("prev_events") + .and_then(CanonicalJsonValue::as_array) + .unwrap_or_default(); + + queued_events.extend( + prev_events + .iter() + .map(<&EventId>::try_from) + .filter_map(Result::ok) + .map(ToOwned::to_owned), + ); + + events.push( + services + .sending + .convert_to_outgoing_federation_event(pdu) + .await, ); - i = i.saturating_add(1); - continue; } - - let Ok(event) = to_canonical_object(&pdu) else { - debug_error!( - ?body.origin, - "Failed to convert PDU in database to canonical JSON: {pdu:?}" - ); - i = i.saturating_add(1); - continue; - }; - - let prev_events = pdu.prev_events.iter().map(ToOwned::to_owned); - - let event = services - .sending - .convert_to_outgoing_federation_event(event) - .await; - - queued_events.extend(prev_events); - events.push(event); + i = i.saturating_add(1); } Ok(get_missing_events::v1::Response { events }) diff --git a/src/api/server/hierarchy.rs b/src/api/server/hierarchy.rs index 42c348f9..c759c8ea 100644 --- a/src/api/server/hierarchy.rs +++ b/src/api/server/hierarchy.rs @@ -3,11 +3,9 @@ use conduwuit::{ Err, Result, utils::stream::{BroadbandExt, IterStream}, }; -use conduwuit_service::rooms::spaces::{ - Identifier, SummaryAccessibility, get_parent_children_via, -}; use futures::{FutureExt, StreamExt}; use ruma::api::federation::space::get_hierarchy; +use service::rooms::spaces::{Identifier, SummaryAccessibility, get_parent_children_via}; use crate::Ruma; diff --git a/src/api/server/invite.rs b/src/api/server/invite.rs index edd6ac16..f4cc6eb2 100644 --- a/src/api/server/invite.rs +++ b/src/api/server/invite.rs @@ -1,15 +1,14 @@ use axum::extract::State; use axum_client_ip::InsecureClientIp; use base64::{Engine as _, engine::general_purpose}; -use conduwuit::{ - Err, Error, PduEvent, Result, err, pdu::gen_event_id, utils, utils::hash::sha256, warn, -}; +use conduwuit::{Err, Error, PduEvent, Result, err, utils, utils::hash::sha256, warn}; use ruma::{ CanonicalJsonValue, OwnedUserId, UserId, api::{client::error::ErrorKind, federation::membership::create_invite}, events::room::member::{MembershipState, RoomMemberEventContent}, serde::JsonObject, }; +use service::pdu::gen_event_id; use crate::Ruma; @@ -38,18 +37,20 @@ pub(crate) async fn create_invite_route( if let Some(server) = body.room_id.server_name() { if services + .server .config .forbidden_remote_server_names - .is_match(server.host()) + .contains(&server.to_owned()) { return Err!(Request(Forbidden("Server is banned on this homeserver."))); } } if services + .server .config .forbidden_remote_server_names - .is_match(body.origin().host()) + .contains(body.origin()) { warn!( "Received federated/remote invite from banned server {} for room ID {}. Rejecting.", diff --git a/src/api/server/make_join.rs b/src/api/server/make_join.rs index ac2c5485..f18d1304 100644 --- a/src/api/server/make_join.rs +++ b/src/api/server/make_join.rs @@ -1,8 +1,5 @@ use axum::extract::State; -use conduwuit::{ - Err, Error, Result, debug_info, matrix::pdu::PduBuilder, utils::IterStream, warn, -}; -use conduwuit_service::Services; +use conduwuit::{Err, debug_info, utils::IterStream, warn}; use futures::StreamExt; use ruma::{ CanonicalJsonObject, OwnedUserId, RoomId, RoomVersionId, UserId, @@ -17,7 +14,10 @@ use ruma::{ }; use serde_json::value::to_raw_value; -use crate::Ruma; +use crate::{ + Error, Result, Ruma, + service::{Services, pdu::PduBuilder}, +}; /// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}` /// @@ -42,9 +42,10 @@ pub(crate) async fn create_join_event_template_route( .await?; if services + .server .config .forbidden_remote_server_names - .is_match(body.origin().host()) + .contains(body.origin()) { warn!( "Server {} for remote user {} tried joining room ID {} which has a server name that \ @@ -58,9 +59,10 @@ pub(crate) async fn create_join_event_template_route( if let Some(server) = body.room_id.server_name() { if services + .server .config .forbidden_remote_server_names - .is_match(server.host()) + .contains(&server.to_owned()) { return Err!(Request(Forbidden(warn!( "Room ID server name {server} is banned on this homeserver." diff --git a/src/api/server/make_knock.rs b/src/api/server/make_knock.rs index 511c13b2..71536439 100644 --- a/src/api/server/make_knock.rs +++ b/src/api/server/make_knock.rs @@ -1,14 +1,15 @@ use RoomVersionId::*; use axum::extract::State; -use conduwuit::{Err, Error, Result, debug_warn, matrix::pdu::PduBuilder, warn}; +use conduwuit::{Err, debug_warn}; use ruma::{ RoomVersionId, api::{client::error::ErrorKind, federation::knock::create_knock_event_template}, events::room::member::{MembershipState, RoomMemberEventContent}, }; use serde_json::value::to_raw_value; +use tracing::warn; -use crate::Ruma; +use crate::{Error, Result, Ruma, service::pdu::PduBuilder}; /// # `GET /_matrix/federation/v1/make_knock/{roomId}/{userId}` /// @@ -33,9 +34,10 @@ pub(crate) async fn create_knock_event_template_route( .await?; if services + .server .config .forbidden_remote_server_names - .is_match(body.origin().host()) + .contains(body.origin()) { warn!( "Server {} for remote user {} tried knocking room ID {} which has a server name \ @@ -49,9 +51,10 @@ pub(crate) async fn create_knock_event_template_route( if let Some(server) = body.room_id.server_name() { if services + .server .config .forbidden_remote_server_names - .is_match(server.host()) + .contains(&server.to_owned()) { return Err!(Request(Forbidden("Server is banned on this homeserver."))); } diff --git a/src/api/server/make_leave.rs b/src/api/server/make_leave.rs index cb6bd2fa..1ed02785 100644 --- a/src/api/server/make_leave.rs +++ b/src/api/server/make_leave.rs @@ -1,5 +1,5 @@ use axum::extract::State; -use conduwuit::{Err, Result, matrix::pdu::PduBuilder}; +use conduwuit::{Err, Result}; use ruma::{ api::federation::membership::prepare_leave_event, events::room::member::{MembershipState, RoomMemberEventContent}, @@ -7,7 +7,7 @@ use ruma::{ use serde_json::value::to_raw_value; use super::make_join::maybe_strip_event_id; -use crate::Ruma; +use crate::{Ruma, service::pdu::PduBuilder}; /// # `GET /_matrix/federation/v1/make_leave/{roomId}/{eventId}` /// diff --git a/src/api/server/openid.rs b/src/api/server/openid.rs index a09cd7ad..4833fbe1 100644 --- a/src/api/server/openid.rs +++ b/src/api/server/openid.rs @@ -1,8 +1,7 @@ use axum::extract::State; -use conduwuit::Result; use ruma::api::federation::openid::get_openid_userinfo; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `GET /_matrix/federation/v1/openid/userinfo` /// diff --git a/src/api/server/publicrooms.rs b/src/api/server/publicrooms.rs index cf66ea71..ff74574a 100644 --- a/src/api/server/publicrooms.rs +++ b/src/api/server/publicrooms.rs @@ -1,6 +1,5 @@ use axum::extract::State; use axum_client_ip::InsecureClientIp; -use conduwuit::{Error, Result}; use ruma::{ api::{ client::error::ErrorKind, @@ -9,7 +8,7 @@ use ruma::{ directory::Filter, }; -use crate::Ruma; +use crate::{Error, Result, Ruma}; /// # `POST /_matrix/federation/v1/publicRooms` /// diff --git a/src/api/server/send.rs b/src/api/server/send.rs index 9c5bfd2b..1f467dac 100644 --- a/src/api/server/send.rs +++ b/src/api/server/send.rs @@ -9,15 +9,11 @@ use conduwuit::{ result::LogErr, trace, utils::{ - IterStream, ReadyExt, millis_since_unix_epoch, + IterStream, ReadyExt, stream::{BroadbandExt, TryBroadbandExt, automatic_width}, }, warn, }; -use conduwuit_service::{ - Services, - sending::{EDU_LIMIT, PDU_LIMIT}, -}; use futures::{FutureExt, Stream, StreamExt, TryFutureExt, TryStreamExt}; use itertools::Itertools; use ruma::{ @@ -37,8 +33,16 @@ use ruma::{ serde::Raw, to_device::DeviceIdOrAllDevices, }; +use service::{ + Services, + sending::{EDU_LIMIT, PDU_LIMIT}, +}; +use utils::millis_since_unix_epoch; -use crate::Ruma; +use crate::{ + Ruma, + utils::{self}, +}; type ResolvedMap = BTreeMap; type Pdu = (OwnedRoomId, OwnedEventId, CanonicalJsonObject); diff --git a/src/api/server/send_join.rs b/src/api/server/send_join.rs index a66d8890..c1749835 100644 --- a/src/api/server/send_join.rs +++ b/src/api/server/send_join.rs @@ -9,7 +9,6 @@ use conduwuit::{ utils::stream::{IterStream, TryBroadbandExt}, warn, }; -use conduwuit_service::Services; use futures::{FutureExt, StreamExt, TryStreamExt}; use ruma::{ CanonicalJsonValue, OwnedEventId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, @@ -21,6 +20,7 @@ use ruma::{ }, }; use serde_json::value::{RawValue as RawJsonValue, to_raw_value}; +use service::Services; use crate::Ruma; @@ -268,9 +268,10 @@ pub(crate) async fn create_join_event_v1_route( body: Ruma, ) -> Result { if services + .server .config .forbidden_remote_server_names - .is_match(body.origin().host()) + .contains(body.origin()) { warn!( "Server {} tried joining room ID {} through us who has a server name that is \ @@ -283,9 +284,10 @@ pub(crate) async fn create_join_event_v1_route( if let Some(server) = body.room_id.server_name() { if services + .server .config .forbidden_remote_server_names - .is_match(server.host()) + .contains(&server.to_owned()) { warn!( "Server {} tried joining room ID {} through us which has a server name that is \ @@ -314,18 +316,20 @@ pub(crate) async fn create_join_event_v2_route( body: Ruma, ) -> Result { if services + .server .config .forbidden_remote_server_names - .is_match(body.origin().host()) + .contains(body.origin()) { return Err!(Request(Forbidden("Server is banned on this homeserver."))); } if let Some(server) = body.room_id.server_name() { if services + .server .config .forbidden_remote_server_names - .is_match(server.host()) + .contains(&server.to_owned()) { warn!( "Server {} tried joining room ID {} through us which has a server name that is \ diff --git a/src/api/server/send_knock.rs b/src/api/server/send_knock.rs index ee7b6cba..f7bb0735 100644 --- a/src/api/server/send_knock.rs +++ b/src/api/server/send_knock.rs @@ -1,9 +1,5 @@ use axum::extract::State; -use conduwuit::{ - Err, Result, err, - matrix::pdu::{PduEvent, gen_event_id_canonical_json}, - warn, -}; +use conduwuit::{Err, PduEvent, Result, err, pdu::gen_event_id_canonical_json, warn}; use futures::FutureExt; use ruma::{ OwnedServerName, OwnedUserId, @@ -26,9 +22,10 @@ pub(crate) async fn create_knock_event_v1_route( body: Ruma, ) -> Result { if services + .server .config .forbidden_remote_server_names - .is_match(body.origin().host()) + .contains(body.origin()) { warn!( "Server {} tried knocking room ID {} who has a server name that is globally \ @@ -41,9 +38,10 @@ pub(crate) async fn create_knock_event_v1_route( if let Some(server) = body.room_id.server_name() { if services + .server .config .forbidden_remote_server_names - .is_match(server.host()) + .contains(&server.to_owned()) { warn!( "Server {} tried knocking room ID {} which has a server name that is globally \ diff --git a/src/api/server/send_leave.rs b/src/api/server/send_leave.rs index d3dc994c..71516553 100644 --- a/src/api/server/send_leave.rs +++ b/src/api/server/send_leave.rs @@ -1,8 +1,7 @@ #![allow(deprecated)] use axum::extract::State; -use conduwuit::{Err, Result, err, matrix::pdu::gen_event_id_canonical_json}; -use conduwuit_service::Services; +use conduwuit::{Err, Result, err}; use futures::FutureExt; use ruma::{ OwnedRoomId, OwnedUserId, RoomId, ServerName, @@ -14,7 +13,10 @@ use ruma::{ }; use serde_json::value::RawValue as RawJsonValue; -use crate::Ruma; +use crate::{ + Ruma, + service::{Services, pdu::gen_event_id_canonical_json}, +}; /// # `PUT /_matrix/federation/v1/send_leave/{roomId}/{eventId}` /// diff --git a/src/api/server/version.rs b/src/api/server/version.rs index b08ff77a..036b61f7 100644 --- a/src/api/server/version.rs +++ b/src/api/server/version.rs @@ -1,7 +1,6 @@ -use conduwuit::Result; use ruma::api::federation::discovery::get_server_version; -use crate::Ruma; +use crate::{Result, Ruma}; /// # `GET /_matrix/federation/v1/version` /// diff --git a/src/api/server/well_known.rs b/src/api/server/well_known.rs index 75c7cf5d..48caa7d6 100644 --- a/src/api/server/well_known.rs +++ b/src/api/server/well_known.rs @@ -1,8 +1,7 @@ use axum::extract::State; -use conduwuit::{Error, Result}; use ruma::api::{client::error::ErrorKind, federation::discovery::discover_homeserver}; -use crate::Ruma; +use crate::{Error, Result, Ruma}; /// # `GET /.well-known/matrix/server` /// diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index 0ca6bbaf..52df19ac 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -3,7 +3,7 @@ pub mod manager; pub mod proxy; use std::{ - collections::{BTreeMap, BTreeSet}, + collections::{BTreeMap, BTreeSet, HashSet}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, path::{Path, PathBuf}, }; @@ -252,6 +252,14 @@ pub struct Config { #[serde(default = "default_servernameevent_data_cache_capacity")] pub servernameevent_data_cache_capacity: u32, + /// default: varies by system + #[serde(default = "default_server_visibility_cache_capacity")] + pub server_visibility_cache_capacity: u32, + + /// default: varies by system + #[serde(default = "default_user_visibility_cache_capacity")] + pub user_visibility_cache_capacity: u32, + /// default: varies by system #[serde(default = "default_stateinfo_cache_capacity")] pub stateinfo_cache_capacity: u32, @@ -640,9 +648,9 @@ pub struct Config { /// Default room version conduwuit will create rooms with. /// - /// Per spec, room version 11 is the default. + /// Per spec, room version 10 is the default. /// - /// default: 11 + /// default: 10 #[serde(default = "default_default_room_version")] pub default_room_version: RoomVersionId, @@ -715,7 +723,7 @@ pub struct Config { /// Currently, conduwuit doesn't support inbound batched key requests, so /// this list should only contain other Synapse servers. /// - /// example: ["matrix.org", "tchncs.de"] + /// example: ["matrix.org", "envs.net", "tchncs.de"] /// /// default: ["matrix.org"] #[serde(default = "default_trusted_servers")] @@ -1361,18 +1369,15 @@ pub struct Config { #[serde(default)] pub prune_missing_media: bool, - /// Vector list of regex patterns of server names that conduwuit will refuse - /// to download remote media from. - /// - /// example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"] + /// Vector list of servers that conduwuit will refuse to download remote + /// media from. /// /// default: [] - #[serde(default, with = "serde_regex")] - pub prevent_media_downloads_from: RegexSet, + #[serde(default)] + pub prevent_media_downloads_from: HashSet, - /// List of forbidden server names via regex patterns that we will block - /// incoming AND outgoing federation with, and block client room joins / - /// remote user invites. + /// List of forbidden server names that we will block incoming AND outgoing + /// federation with, and block client room joins / remote user invites. /// /// This check is applied on the room ID, room alias, sender server name, /// sender user's server name, inbound federation X-Matrix origin, and @@ -1380,21 +1385,17 @@ pub struct Config { /// /// Basically "global" ACLs. /// - /// example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"] - /// /// default: [] - #[serde(default, with = "serde_regex")] - pub forbidden_remote_server_names: RegexSet, + #[serde(default)] + pub forbidden_remote_server_names: HashSet, - /// List of forbidden server names via regex patterns that we will block all - /// outgoing federated room directory requests for. Useful for preventing - /// our users from wandering into bad servers or spaces. - /// - /// example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"] + /// List of forbidden server names that we will block all outgoing federated + /// room directory requests for. Useful for preventing our users from + /// wandering into bad servers or spaces. /// /// default: [] - #[serde(default, with = "serde_regex")] - pub forbidden_remote_room_directory_server_names: RegexSet, + #[serde(default = "HashSet::new")] + pub forbidden_remote_room_directory_server_names: HashSet, /// Vector list of IPv4 and IPv6 CIDR ranges / subnets *in quotes* that you /// do not want conduwuit to send outbound requests to. Defaults to @@ -1515,10 +1516,11 @@ pub struct Config { /// used, and startup as warnings if any room aliases in your database have /// a forbidden room alias/ID. /// - /// example: ["19dollarfortnitecards", "b[4a]droom", "badphrase"] + /// example: ["19dollarfortnitecards", "b[4a]droom"] /// /// default: [] - #[serde(default, with = "serde_regex")] + #[serde(default)] + #[serde(with = "serde_regex")] pub forbidden_alias_names: RegexSet, /// List of forbidden username patterns/strings. @@ -1530,10 +1532,11 @@ pub struct Config { /// startup as warnings if any local users in your database have a forbidden /// username. /// - /// example: ["administrator", "b[a4]dusernam[3e]", "badphrase"] + /// example: ["administrator", "b[a4]dusernam[3e]"] /// /// default: [] - #[serde(default, with = "serde_regex")] + #[serde(default)] + #[serde(with = "serde_regex")] pub forbidden_usernames: RegexSet, /// Retry failed and incomplete messages to remote servers immediately upon @@ -2032,6 +2035,10 @@ fn default_servernameevent_data_cache_capacity() -> u32 { parallelism_scaled_u32(100_000).saturating_add(500_000) } +fn default_server_visibility_cache_capacity() -> u32 { parallelism_scaled_u32(500) } + +fn default_user_visibility_cache_capacity() -> u32 { parallelism_scaled_u32(1000) } + fn default_stateinfo_cache_capacity() -> u32 { parallelism_scaled_u32(100) } fn default_roomid_spacehierarchy_cache_capacity() -> u32 { parallelism_scaled_u32(1000) } @@ -2175,7 +2182,7 @@ fn default_rocksdb_stats_level() -> u8 { 1 } // I know, it's a great name #[must_use] #[inline] -pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V11 } +pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V10 } fn default_ip_range_denylist() -> Vec { vec![ diff --git a/src/core/matrix/mod.rs b/src/core/matrix/mod.rs deleted file mode 100644 index 8c978173..00000000 --- a/src/core/matrix/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -//! Core Matrix Library - -pub mod event; -pub mod pdu; -pub mod state_res; - -pub use event::Event; -pub use pdu::{PduBuilder, PduCount, PduEvent, PduId, RawPduId, StateKey}; -pub use state_res::{EventTypeExt, RoomVersion, StateMap, TypeStateKey}; diff --git a/src/core/mod.rs b/src/core/mod.rs index b91cdf0b..80ebbdcb 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -6,10 +6,11 @@ pub mod debug; pub mod error; pub mod info; pub mod log; -pub mod matrix; pub mod metrics; pub mod mods; +pub mod pdu; pub mod server; +pub mod state_res; pub mod utils; pub use ::arrayvec; @@ -22,8 +23,9 @@ pub use ::tracing; pub use config::Config; pub use error::Error; pub use info::{rustc_flags_capture, version, version::version}; -pub use matrix::{Event, EventTypeExt, PduCount, PduEvent, PduId, RoomVersion, pdu, state_res}; +pub use pdu::{Event, PduBuilder, PduCount, PduEvent, PduId, RawPduId, StateKey}; pub use server::Server; +pub use state_res::{EventTypeExt, RoomVersion, StateMap, TypeStateKey}; pub use utils::{ctor, dtor, implement, result, result::Result}; pub use crate as conduwuit_core; diff --git a/src/core/matrix/pdu/builder.rs b/src/core/pdu/builder.rs similarity index 100% rename from src/core/matrix/pdu/builder.rs rename to src/core/pdu/builder.rs diff --git a/src/core/matrix/pdu/content.rs b/src/core/pdu/content.rs similarity index 100% rename from src/core/matrix/pdu/content.rs rename to src/core/pdu/content.rs diff --git a/src/core/matrix/pdu/count.rs b/src/core/pdu/count.rs similarity index 100% rename from src/core/matrix/pdu/count.rs rename to src/core/pdu/count.rs diff --git a/src/core/pdu/event.rs b/src/core/pdu/event.rs new file mode 100644 index 00000000..09ad1666 --- /dev/null +++ b/src/core/pdu/event.rs @@ -0,0 +1,35 @@ +use ruma::{MilliSecondsSinceUnixEpoch, OwnedEventId, RoomId, UserId, events::TimelineEventType}; +use serde_json::value::RawValue as RawJsonValue; + +use super::Pdu; +pub use crate::state_res::Event; + +impl Event for Pdu { + type Id = OwnedEventId; + + fn event_id(&self) -> &Self::Id { &self.event_id } + + fn room_id(&self) -> &RoomId { &self.room_id } + + fn sender(&self) -> &UserId { &self.sender } + + fn event_type(&self) -> &TimelineEventType { &self.kind } + + fn content(&self) -> &RawJsonValue { &self.content } + + fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch { + MilliSecondsSinceUnixEpoch(self.origin_server_ts) + } + + fn state_key(&self) -> Option<&str> { self.state_key.as_deref() } + + fn prev_events(&self) -> impl DoubleEndedIterator + Send + '_ { + self.prev_events.iter() + } + + fn auth_events(&self) -> impl DoubleEndedIterator + Send + '_ { + self.auth_events.iter() + } + + fn redacts(&self) -> Option<&Self::Id> { self.redacts.as_ref() } +} diff --git a/src/core/matrix/pdu/event_id.rs b/src/core/pdu/event_id.rs similarity index 100% rename from src/core/matrix/pdu/event_id.rs rename to src/core/pdu/event_id.rs diff --git a/src/core/matrix/pdu/filter.rs b/src/core/pdu/filter.rs similarity index 100% rename from src/core/matrix/pdu/filter.rs rename to src/core/pdu/filter.rs diff --git a/src/core/matrix/pdu/id.rs b/src/core/pdu/id.rs similarity index 100% rename from src/core/matrix/pdu/id.rs rename to src/core/pdu/id.rs diff --git a/src/core/matrix/pdu.rs b/src/core/pdu/mod.rs similarity index 72% rename from src/core/matrix/pdu.rs rename to src/core/pdu/mod.rs index 7e1ecfa8..9fb2a3da 100644 --- a/src/core/matrix/pdu.rs +++ b/src/core/pdu/mod.rs @@ -1,6 +1,7 @@ mod builder; mod content; mod count; +mod event; mod event_id; mod filter; mod id; @@ -16,8 +17,8 @@ mod unsigned; use std::cmp::Ordering; use ruma::{ - CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, - OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, UInt, UserId, events::TimelineEventType, + CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, OwnedServerName, + OwnedUserId, UInt, events::TimelineEventType, }; use serde::{Deserialize, Serialize}; use serde_json::value::RawValue as RawJsonValue; @@ -26,12 +27,12 @@ pub use self::{ Count as PduCount, Id as PduId, Pdu as PduEvent, RawId as RawPduId, builder::{Builder, Builder as PduBuilder}, count::Count, + event::Event, event_id::*, id::*, raw_id::*, state_key::{ShortStateKey, StateKey}, }; -use super::Event; use crate::Result; /// Persistent Data Unit (Event) @@ -78,36 +79,6 @@ impl Pdu { } } -impl Event for Pdu { - type Id = OwnedEventId; - - fn event_id(&self) -> &Self::Id { &self.event_id } - - fn room_id(&self) -> &RoomId { &self.room_id } - - fn sender(&self) -> &UserId { &self.sender } - - fn event_type(&self) -> &TimelineEventType { &self.kind } - - fn content(&self) -> &RawJsonValue { &self.content } - - fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch { - MilliSecondsSinceUnixEpoch(self.origin_server_ts) - } - - fn state_key(&self) -> Option<&str> { self.state_key.as_deref() } - - fn prev_events(&self) -> impl DoubleEndedIterator + Send + '_ { - self.prev_events.iter() - } - - fn auth_events(&self) -> impl DoubleEndedIterator + Send + '_ { - self.auth_events.iter() - } - - fn redacts(&self) -> Option<&Self::Id> { self.redacts.as_ref() } -} - /// Prevent derived equality which wouldn't limit itself to event_id impl Eq for Pdu {} @@ -116,12 +87,12 @@ impl PartialEq for Pdu { fn eq(&self, other: &Self) -> bool { self.event_id == other.event_id } } -/// Ordering determined by the Pdu's ID, not the memory representations. -impl Ord for Pdu { - fn cmp(&self, other: &Self) -> Ordering { self.event_id.cmp(&other.event_id) } -} - /// Ordering determined by the Pdu's ID, not the memory representations. impl PartialOrd for Pdu { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } + +/// Ordering determined by the Pdu's ID, not the memory representations. +impl Ord for Pdu { + fn cmp(&self, other: &Self) -> Ordering { self.event_id.cmp(&other.event_id) } +} diff --git a/src/core/matrix/pdu/raw_id.rs b/src/core/pdu/raw_id.rs similarity index 100% rename from src/core/matrix/pdu/raw_id.rs rename to src/core/pdu/raw_id.rs diff --git a/src/core/matrix/pdu/redact.rs b/src/core/pdu/redact.rs similarity index 100% rename from src/core/matrix/pdu/redact.rs rename to src/core/pdu/redact.rs diff --git a/src/core/matrix/pdu/relation.rs b/src/core/pdu/relation.rs similarity index 100% rename from src/core/matrix/pdu/relation.rs rename to src/core/pdu/relation.rs diff --git a/src/core/matrix/pdu/state_key.rs b/src/core/pdu/state_key.rs similarity index 100% rename from src/core/matrix/pdu/state_key.rs rename to src/core/pdu/state_key.rs diff --git a/src/core/matrix/pdu/strip.rs b/src/core/pdu/strip.rs similarity index 100% rename from src/core/matrix/pdu/strip.rs rename to src/core/pdu/strip.rs diff --git a/src/core/matrix/pdu/tests.rs b/src/core/pdu/tests.rs similarity index 100% rename from src/core/matrix/pdu/tests.rs rename to src/core/pdu/tests.rs diff --git a/src/core/matrix/pdu/unsigned.rs b/src/core/pdu/unsigned.rs similarity index 100% rename from src/core/matrix/pdu/unsigned.rs rename to src/core/pdu/unsigned.rs diff --git a/src/core/server.rs b/src/core/server.rs index 4b673f32..b67759d6 100644 --- a/src/core/server.rs +++ b/src/core/server.rs @@ -69,6 +69,10 @@ impl Server { return Err!("Reloading not enabled"); } + #[cfg(all(feature = "systemd", target_os = "linux"))] + sd_notify::notify(true, &[sd_notify::NotifyState::Reloading]) + .expect("failed to notify systemd of reloading state"); + if self.reloading.swap(true, Ordering::AcqRel) { return Err!("Reloading already in progress"); } @@ -94,6 +98,10 @@ impl Server { } pub fn shutdown(&self) -> Result { + #[cfg(all(feature = "systemd", target_os = "linux"))] + sd_notify::notify(true, &[sd_notify::NotifyState::Stopping]) + .expect("failed to notify systemd of stopping state"); + if self.stopping.swap(true, Ordering::AcqRel) { return Err!("Shutdown already in progress"); } @@ -136,16 +144,7 @@ impl Server { } #[inline] - pub fn running(&self) -> bool { !self.is_stopping() } - - #[inline] - pub fn is_stopping(&self) -> bool { self.stopping.load(Ordering::Relaxed) } - - #[inline] - pub fn is_reloading(&self) -> bool { self.reloading.load(Ordering::Relaxed) } - - #[inline] - pub fn is_restarting(&self) -> bool { self.restarting.load(Ordering::Relaxed) } + pub fn running(&self) -> bool { !self.stopping.load(Ordering::Acquire) } #[inline] pub fn is_ours(&self, name: &str) -> bool { name == self.config.server_name } diff --git a/src/core/matrix/state_res/LICENSE b/src/core/state_res/LICENSE similarity index 100% rename from src/core/matrix/state_res/LICENSE rename to src/core/state_res/LICENSE diff --git a/src/core/matrix/state_res/benches.rs b/src/core/state_res/benches.rs similarity index 100% rename from src/core/matrix/state_res/benches.rs rename to src/core/state_res/benches.rs diff --git a/src/core/matrix/state_res/error.rs b/src/core/state_res/error.rs similarity index 100% rename from src/core/matrix/state_res/error.rs rename to src/core/state_res/error.rs diff --git a/src/core/matrix/state_res/event_auth.rs b/src/core/state_res/event_auth.rs similarity index 100% rename from src/core/matrix/state_res/event_auth.rs rename to src/core/state_res/event_auth.rs diff --git a/src/core/matrix/state_res/mod.rs b/src/core/state_res/mod.rs similarity index 99% rename from src/core/matrix/state_res/mod.rs rename to src/core/state_res/mod.rs index 93c00d15..1db92e59 100644 --- a/src/core/matrix/state_res/mod.rs +++ b/src/core/state_res/mod.rs @@ -4,6 +4,7 @@ pub(crate) mod error; pub mod event_auth; mod power_levels; mod room_version; +mod state_event; #[cfg(test)] mod test_utils; @@ -35,12 +36,9 @@ use self::power_levels::PowerLevelsContentFields; pub use self::{ event_auth::{auth_check, auth_types_for_event}, room_version::RoomVersion, + state_event::Event, }; -use crate::{ - debug, - matrix::{event::Event, pdu::StateKey}, - trace, warn, -}; +use crate::{debug, pdu::StateKey, trace, warn}; /// A mapping of event type and state_key to some value `T`, usually an /// `EventId`. diff --git a/src/core/matrix/state_res/outcomes.txt b/src/core/state_res/outcomes.txt similarity index 100% rename from src/core/matrix/state_res/outcomes.txt rename to src/core/state_res/outcomes.txt diff --git a/src/core/matrix/state_res/power_levels.rs b/src/core/state_res/power_levels.rs similarity index 99% rename from src/core/matrix/state_res/power_levels.rs rename to src/core/state_res/power_levels.rs index 19ba8fb9..045b1666 100644 --- a/src/core/matrix/state_res/power_levels.rs +++ b/src/core/state_res/power_levels.rs @@ -11,9 +11,9 @@ use ruma::{ }; use serde::Deserialize; use serde_json::{Error, from_str as from_json_str}; +use tracing::error; use super::{Result, RoomVersion}; -use crate::error; #[derive(Deserialize)] struct IntRoomPowerLevelsEventContent { diff --git a/src/core/matrix/state_res/room_version.rs b/src/core/state_res/room_version.rs similarity index 100% rename from src/core/matrix/state_res/room_version.rs rename to src/core/state_res/room_version.rs diff --git a/src/core/matrix/event.rs b/src/core/state_res/state_event.rs similarity index 100% rename from src/core/matrix/event.rs rename to src/core/state_res/state_event.rs diff --git a/src/core/matrix/state_res/test_utils.rs b/src/core/state_res/test_utils.rs similarity index 99% rename from src/core/matrix/state_res/test_utils.rs rename to src/core/state_res/test_utils.rs index f2ee4238..d96ee927 100644 --- a/src/core/matrix/state_res/test_utils.rs +++ b/src/core/state_res/test_utils.rs @@ -28,10 +28,7 @@ use serde_json::{ pub(crate) use self::event::PduEvent; use super::auth_types_for_event; -use crate::{ - Result, info, - matrix::{Event, EventTypeExt, StateMap}, -}; +use crate::{Event, EventTypeExt, Result, StateMap, info}; static SERVER_TIMESTAMP: AtomicU64 = AtomicU64::new(0); diff --git a/src/core/utils/future/mod.rs b/src/core/utils/future/mod.rs index 4edd0102..e1d96941 100644 --- a/src/core/utils/future/mod.rs +++ b/src/core/utils/future/mod.rs @@ -1,11 +1,9 @@ mod bool_ext; mod ext_ext; mod option_ext; -mod option_stream; mod try_ext_ext; pub use bool_ext::{BoolExt, and, or}; pub use ext_ext::ExtExt; pub use option_ext::OptionExt; -pub use option_stream::OptionStream; pub use try_ext_ext::TryExtExt; diff --git a/src/core/utils/future/option_ext.rs b/src/core/utils/future/option_ext.rs index 920dd044..d553e5dc 100644 --- a/src/core/utils/future/option_ext.rs +++ b/src/core/utils/future/option_ext.rs @@ -11,14 +11,11 @@ pub trait OptionExt { impl OptionExt for OptionFuture where Fut: Future + Send, - T: Send, { - #[inline] fn is_none_or(self, f: impl FnOnce(&T) -> bool + Send) -> impl Future + Send { self.map(|o| o.as_ref().is_none_or(f)) } - #[inline] fn is_some_and(self, f: impl FnOnce(&T) -> bool + Send) -> impl Future + Send { self.map(|o| o.as_ref().is_some_and(f)) } diff --git a/src/core/utils/future/option_stream.rs b/src/core/utils/future/option_stream.rs deleted file mode 100644 index 81130c87..00000000 --- a/src/core/utils/future/option_stream.rs +++ /dev/null @@ -1,25 +0,0 @@ -use futures::{Future, FutureExt, Stream, StreamExt, future::OptionFuture}; - -use super::super::IterStream; - -pub trait OptionStream { - fn stream(self) -> impl Stream + Send; -} - -impl OptionStream for OptionFuture -where - Fut: Future + Send, - S: Stream + Send, - O: IntoIterator + Send, - ::IntoIter: Send, - T: Send, -{ - #[inline] - fn stream(self) -> impl Stream + Send { - self.map(|opt| opt.map(|(curr, next)| curr.into_iter().stream().chain(next))) - .map(Option::into_iter) - .map(IterStream::stream) - .flatten_stream() - .flatten() - } -} diff --git a/src/core/utils/mod.rs b/src/core/utils/mod.rs index 117fb739..7593990c 100644 --- a/src/core/utils/mod.rs +++ b/src/core/utils/mod.rs @@ -49,10 +49,10 @@ pub fn exchange(state: &mut T, source: T) -> T { std::mem::replace(state, sou #[macro_export] macro_rules! extract_variant { - ( $e:expr_2021, $( $variant:path )|* ) => { + ($e:expr_2021, $variant:path) => { match $e { - $( $variant(value) => Some(value), )* - _ => None, + | $variant(value) => Some(value), + | _ => None, } }; } diff --git a/src/database/pool.rs b/src/database/pool.rs index 0fa742d1..47e61c30 100644 --- a/src/database/pool.rs +++ b/src/database/pool.rs @@ -12,7 +12,7 @@ use std::{ use async_channel::{QueueStrategy, Receiver, RecvError, Sender}; use conduwuit::{ - Error, Result, Server, debug, err, error, implement, + Error, Result, Server, debug, debug_warn, err, error, implement, result::DebugInspect, smallvec::SmallVec, trace, @@ -245,6 +245,13 @@ async fn execute(&self, queue: &Sender, cmd: Cmd) -> Result { self.queued_max.fetch_max(queue.len(), Ordering::Relaxed); } + if queue.is_full() { + debug_warn!( + capacity = ?queue.capacity(), + "pool queue is full" + ); + } + queue .send(cmd) .await diff --git a/src/main/main.rs b/src/main/main.rs index 1a9d3fe4..52f40384 100644 --- a/src/main/main.rs +++ b/src/main/main.rs @@ -16,14 +16,15 @@ use server::Server; rustc_flags_capture! {} -fn main() -> Result { +fn main() -> Result<(), Error> { let args = clap::parse(); let runtime = runtime::new(&args)?; let server = Server::new(&args, Some(runtime.handle()))?; - runtime.spawn(signal::signal(server.clone())); runtime.block_on(async_main(&server))?; - runtime::shutdown(&server, runtime); + + // explicit drop here to trace thread and tls dtors + drop(runtime); #[cfg(unix)] if server.server.restarting.load(Ordering::Acquire) { diff --git a/src/main/runtime.rs b/src/main/runtime.rs index 1c58ea81..920476db 100644 --- a/src/main/runtime.rs +++ b/src/main/runtime.rs @@ -1,7 +1,7 @@ use std::{ iter::once, sync::{ - Arc, OnceLock, + OnceLock, atomic::{AtomicUsize, Ordering}, }, thread, @@ -11,18 +11,17 @@ use std::{ #[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] use conduwuit_core::result::LogDebugErr; use conduwuit_core::{ - Result, debug, is_true, + Result, is_true, utils::sys::compute::{nth_core_available, set_affinity}, }; use tokio::runtime::Builder; -use crate::{clap::Args, server::Server}; +use crate::clap::Args; const WORKER_NAME: &str = "conduwuit:worker"; const WORKER_MIN: usize = 2; const WORKER_KEEPALIVE: u64 = 36; const MAX_BLOCKING_THREADS: usize = 1024; -const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(10000); #[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] const DISABLE_MUZZY_THRESHOLD: usize = 4; @@ -84,42 +83,6 @@ fn enable_histogram(builder: &mut Builder, args: &Args) { .metrics_poll_time_histogram_configuration(linear); } -#[cfg(tokio_unstable)] -#[tracing::instrument(name = "stop", level = "info", skip_all)] -pub(super) fn shutdown(server: &Arc, runtime: tokio::runtime::Runtime) { - use conduwuit_core::event; - use tracing::Level; - - // The final metrics output is promoted to INFO when tokio_unstable is active in - // a release/bench mode and DEBUG is likely optimized out - const LEVEL: Level = if cfg!(debug_assertions) { - Level::DEBUG - } else { - Level::INFO - }; - - debug!( - timeout = ?SHUTDOWN_TIMEOUT, - "Waiting for runtime..." - ); - - runtime.shutdown_timeout(SHUTDOWN_TIMEOUT); - let runtime_metrics = server.server.metrics.runtime_interval().unwrap_or_default(); - - event!(LEVEL, ?runtime_metrics, "Final runtime metrics"); -} - -#[cfg(not(tokio_unstable))] -#[tracing::instrument(name = "stop", level = "info", skip_all)] -pub(super) fn shutdown(_server: &Arc, runtime: tokio::runtime::Runtime) { - debug!( - timeout = ?SHUTDOWN_TIMEOUT, - "Waiting for runtime..." - ); - - runtime.shutdown_timeout(SHUTDOWN_TIMEOUT); -} - #[tracing::instrument( name = "fork", level = "debug", diff --git a/src/router/run.rs b/src/router/run.rs index ff54594f..31789626 100644 --- a/src/router/run.rs +++ b/src/router/run.rs @@ -77,10 +77,6 @@ pub(crate) async fn start(server: Arc) -> Result> { pub(crate) async fn stop(services: Arc) -> Result<()> { debug!("Shutting down..."); - #[cfg(all(feature = "systemd", target_os = "linux"))] - sd_notify::notify(true, &[sd_notify::NotifyState::Stopping]) - .expect("failed to notify systemd of stopping state"); - // Wait for all completions before dropping or we'll lose them to the module // unload and explode. services.stop().await; diff --git a/src/service/admin/grant.rs b/src/service/admin/grant.rs index 6780b7ae..5173987a 100644 --- a/src/service/admin/grant.rs +++ b/src/service/admin/grant.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use conduwuit::{Err, Result, debug_info, debug_warn, error, implement, matrix::pdu::PduBuilder}; +use conduwuit::{Err, Result, debug_info, debug_warn, error, implement}; use ruma::{ RoomId, UserId, events::{ @@ -14,6 +14,8 @@ use ruma::{ }, }; +use crate::pdu::PduBuilder; + /// Invite the user to the conduwuit admin room. /// /// This is equivalent to granting server admin privileges. diff --git a/src/service/client/mod.rs b/src/service/client/mod.rs index 1aeeb492..d51e5721 100644 --- a/src/service/client/mod.rs +++ b/src/service/client/mod.rs @@ -56,7 +56,7 @@ impl crate::Service for Service { .build()?, well_known: base(config)? - .dns_resolver(resolver.resolver.clone()) + .dns_resolver(resolver.resolver.hooked.clone()) .connect_timeout(Duration::from_secs(config.well_known_conn_timeout)) .read_timeout(Duration::from_secs(config.well_known_timeout)) .timeout(Duration::from_secs(config.well_known_timeout)) diff --git a/src/service/federation/execute.rs b/src/service/federation/execute.rs index 97314ffb..63f2ccfb 100644 --- a/src/service/federation/execute.rs +++ b/src/service/federation/execute.rs @@ -69,7 +69,7 @@ where .server .config .forbidden_remote_server_names - .is_match(dest.host()) + .contains(dest) { return Err!(Request(Forbidden(debug_warn!("Federation with {dest} is not allowed.")))); } diff --git a/src/service/media/remote.rs b/src/service/media/remote.rs index cdcb429e..b6c853d2 100644 --- a/src/service/media/remote.rs +++ b/src/service/media/remote.rs @@ -426,13 +426,7 @@ fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> { .server .config .prevent_media_downloads_from - .is_match(mxc.server_name.host()) - || self - .services - .server - .config - .forbidden_remote_server_names - .is_match(mxc.server_name.host()) + .contains(mxc.server_name) { // we'll lie to the client and say the blocked server's media was not found and // log. the client has no way of telling anyways so this is a security bonus. diff --git a/src/service/mod.rs b/src/service/mod.rs index 63a51213..8f4a84b0 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -31,6 +31,7 @@ pub mod users; extern crate conduwuit_core as conduwuit; extern crate conduwuit_database as database; +pub use conduwuit::{PduBuilder, PduCount, PduEvent, pdu}; pub(crate) use service::{Args, Dep, Service}; pub use crate::services::Services; diff --git a/src/service/resolver/actual.rs b/src/service/resolver/actual.rs index 0151c4d7..1ad76f66 100644 --- a/src/service/resolver/actual.rs +++ b/src/service/resolver/actual.rs @@ -5,7 +5,7 @@ use std::{ use conduwuit::{Err, Result, debug, debug_info, err, error, trace}; use futures::{FutureExt, TryFutureExt}; -use hickory_resolver::ResolveError; +use hickory_resolver::error::ResolveError; use ipaddress::IPAddress; use ruma::ServerName; @@ -334,28 +334,25 @@ impl super::Service { } fn handle_resolve_error(e: &ResolveError, host: &'_ str) -> Result<()> { - use hickory_resolver::{ResolveErrorKind::Proto, proto::ProtoErrorKind}; + use hickory_resolver::error::ResolveErrorKind; - match e.kind() { - | Proto(e) => match e.kind() { - | ProtoErrorKind::NoRecordsFound { .. } => { - // Raise to debug_warn if we can find out the result wasn't from cache - debug!(%host, "No DNS records found: {e}"); - Ok(()) - }, - | ProtoErrorKind::Timeout => { - Err!(warn!(%host, "DNS {e}")) - }, - | ProtoErrorKind::NoConnections => { - error!( - "Your DNS server is overloaded and has ran out of connections. It is \ - strongly recommended you remediate this issue to ensure proper \ - federation connectivity." - ); + match *e.kind() { + | ResolveErrorKind::NoRecordsFound { .. } => { + // Raise to debug_warn if we can find out the result wasn't from cache + debug!(%host, "No DNS records found: {e}"); + Ok(()) + }, + | ResolveErrorKind::Timeout => { + Err!(warn!(%host, "DNS {e}")) + }, + | ResolveErrorKind::NoConnections => { + error!( + "Your DNS server is overloaded and has ran out of connections. It is \ + strongly recommended you remediate this issue to ensure proper federation \ + connectivity." + ); - Err!(error!(%host, "DNS error: {e}")) - }, - | _ => Err!(error!(%host, "DNS error: {e}")), + Err!(error!(%host, "DNS error: {e}")) }, | _ => Err!(error!(%host, "DNS error: {e}")), } diff --git a/src/service/resolver/dns.rs b/src/service/resolver/dns.rs index 3a0b2551..e4245a5b 100644 --- a/src/service/resolver/dns.rs +++ b/src/service/resolver/dns.rs @@ -2,19 +2,19 @@ use std::{net::SocketAddr, sync::Arc, time::Duration}; use conduwuit::{Result, Server, err}; use futures::FutureExt; -use hickory_resolver::{TokioResolver, lookup_ip::LookupIp}; +use hickory_resolver::{TokioAsyncResolver, lookup_ip::LookupIp}; use reqwest::dns::{Addrs, Name, Resolve, Resolving}; use super::cache::{Cache, CachedOverride}; pub struct Resolver { - pub(crate) resolver: Arc, + pub(crate) resolver: Arc, pub(crate) hooked: Arc, server: Arc, } pub(crate) struct Hooked { - resolver: Arc, + resolver: Arc, cache: Arc, server: Arc, } @@ -42,7 +42,7 @@ impl Resolver { let mut ns = sys_conf.clone(); if config.query_over_tcp_only { - ns.protocol = hickory_resolver::proto::xfer::Protocol::Tcp; + ns.protocol = hickory_resolver::config::Protocol::Tcp; } ns.trust_negative_responses = !config.query_all_nameservers; @@ -51,7 +51,6 @@ impl Resolver { } opts.cache_size = config.dns_cache_entries as usize; - opts.preserve_intermediates = true; opts.negative_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain)); opts.negative_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 30)); opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl)); @@ -61,7 +60,8 @@ impl Resolver { opts.try_tcp_on_error = config.dns_tcp_fallback; opts.num_concurrent_reqs = 1; opts.edns0 = true; - opts.case_randomization = true; + opts.shuffle_dns_servers = true; + opts.rotate = true; opts.ip_strategy = match config.ip_lookup_strategy { | 1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only, | 2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only, @@ -69,13 +69,9 @@ impl Resolver { | 4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4, | _ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6, }; + opts.authentic_data = false; - let rt_prov = hickory_resolver::proto::runtime::TokioRuntimeProvider::new(); - let conn_prov = hickory_resolver::name_server::TokioConnectionProvider::new(rt_prov); - let mut builder = TokioResolver::builder_with_config(conf, conn_prov); - *builder.options_mut() = opts; - let resolver = Arc::new(builder.build()); - + let resolver = Arc::new(TokioAsyncResolver::tokio(conf, opts)); Ok(Arc::new(Self { resolver: resolver.clone(), hooked: Arc::new(Hooked { resolver, cache, server: server.clone() }), @@ -109,7 +105,7 @@ impl Resolve for Hooked { async fn hooked_resolve( cache: Arc, server: Arc, - resolver: Arc, + resolver: Arc, name: Name, ) -> Result> { match cache.get_override(name.as_str()).await { @@ -133,7 +129,7 @@ async fn hooked_resolve( async fn resolve_to_reqwest( server: Arc, - resolver: Arc, + resolver: Arc, name: Name, ) -> ResolvingResult { use std::{io, io::ErrorKind::Interrupted}; diff --git a/src/service/rooms/event_handler/fetch_and_handle_outliers.rs b/src/service/rooms/event_handler/fetch_and_handle_outliers.rs index b0a7d827..80e91eff 100644 --- a/src/service/rooms/event_handler/fetch_and_handle_outliers.rs +++ b/src/service/rooms/event_handler/fetch_and_handle_outliers.rs @@ -1,5 +1,6 @@ use std::{ collections::{BTreeMap, HashSet, VecDeque, hash_map}, + sync::Arc, time::Instant, }; @@ -7,6 +8,7 @@ use conduwuit::{ PduEvent, debug, debug_error, debug_warn, implement, pdu, trace, utils::continue_exponential_backoff_secs, warn, }; +use futures::TryFutureExt; use ruma::{ CanonicalJsonValue, OwnedEventId, RoomId, ServerName, api::federation::event::get_event, }; @@ -29,7 +31,7 @@ pub(super) async fn fetch_and_handle_outliers<'a>( events: &'a [OwnedEventId], create_event: &'a PduEvent, room_id: &'a RoomId, -) -> Vec<(PduEvent, Option>)> { +) -> Vec<(Arc, Option>)> { let back_off = |id| match self .services .globals @@ -51,7 +53,7 @@ pub(super) async fn fetch_and_handle_outliers<'a>( // a. Look in the main timeline (pduid_pdu tree) // b. Look at outlier pdu tree // (get_pdu_json checks both) - if let Ok(local_pdu) = self.services.timeline.get_pdu(id).await { + if let Ok(local_pdu) = self.services.timeline.get_pdu(id).map_ok(Arc::new).await { trace!("Found {id} in db"); events_with_auth_events.push((id, Some(local_pdu), vec![])); continue; diff --git a/src/service/rooms/event_handler/fetch_prev.rs b/src/service/rooms/event_handler/fetch_prev.rs index 0f92d6e6..e817430b 100644 --- a/src/service/rooms/event_handler/fetch_prev.rs +++ b/src/service/rooms/event_handler/fetch_prev.rs @@ -1,4 +1,7 @@ -use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; +use std::{ + collections::{BTreeMap, HashMap, HashSet, VecDeque}, + sync::Arc, +}; use conduwuit::{ PduEvent, Result, debug_warn, err, implement, @@ -28,7 +31,7 @@ pub(super) async fn fetch_prev( initial_set: Vec, ) -> Result<( Vec, - HashMap)>, + HashMap, BTreeMap)>, )> { let mut graph: HashMap = HashMap::with_capacity(initial_set.len()); let mut eventid_info = HashMap::new(); diff --git a/src/service/rooms/event_handler/handle_incoming_pdu.rs b/src/service/rooms/event_handler/handle_incoming_pdu.rs index 77cae41d..b437bf2e 100644 --- a/src/service/rooms/event_handler/handle_incoming_pdu.rs +++ b/src/service/rooms/event_handler/handle_incoming_pdu.rs @@ -3,12 +3,9 @@ use std::{ time::Instant, }; -use conduwuit::{ - Err, Result, debug, debug::INFO_SPAN_LEVEL, defer, err, implement, utils::stream::IterStream, - warn, -}; +use conduwuit::{Err, Result, debug, debug::INFO_SPAN_LEVEL, err, implement, warn}; use futures::{ - FutureExt, TryFutureExt, TryStreamExt, + FutureExt, future::{OptionFuture, try_join5}, }; use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UserId, events::StateEventType}; @@ -89,7 +86,7 @@ pub async fn handle_incoming_pdu<'a>( .state_accessor .room_state_get(room_id, &StateEventType::RoomCreate, ""); - let (meta_exists, is_disabled, (), (), ref create_event) = try_join5( + let (meta_exists, is_disabled, (), (), create_event) = try_join5( meta_exists, is_disabled, origin_acl_check, @@ -107,7 +104,7 @@ pub async fn handle_incoming_pdu<'a>( } let (incoming_pdu, val) = self - .handle_outlier_pdu(origin, create_event, event_id, room_id, value, false) + .handle_outlier_pdu(origin, &create_event, event_id, room_id, value, false) .await?; // 8. if not timeline event: stop @@ -132,71 +129,66 @@ pub async fn handle_incoming_pdu<'a>( let (sorted_prev_events, mut eventid_info) = self .fetch_prev( origin, - create_event, + &create_event, room_id, first_ts_in_room, incoming_pdu.prev_events.clone(), ) .await?; - debug!( - events = ?sorted_prev_events, - "Handling previous events" - ); - - sorted_prev_events - .iter() - .try_stream() - .map_ok(AsRef::as_ref) - .try_for_each(|prev_id| { - self.handle_prev_pdu( + debug!(events = ?sorted_prev_events, "Got previous events"); + for prev_id in sorted_prev_events { + self.services.server.check_running()?; + if let Err(e) = self + .handle_prev_pdu( origin, event_id, room_id, - eventid_info.remove(prev_id), - create_event, + &mut eventid_info, + &create_event, first_ts_in_room, - prev_id, + &prev_id, ) - .inspect_err(move |e| { - warn!("Prev {prev_id} failed: {e}"); - match self - .services - .globals - .bad_event_ratelimiter - .write() - .expect("locked") - .entry(prev_id.into()) - { - | hash_map::Entry::Vacant(e) => { - e.insert((Instant::now(), 1)); - }, - | hash_map::Entry::Occupied(mut e) => { - let tries = e.get().1.saturating_add(1); - *e.get_mut() = (Instant::now(), tries); - }, - } - }) - .map(|_| self.services.server.check_running()) - }) - .boxed() - .await?; + .await + { + use hash_map::Entry; + + let now = Instant::now(); + warn!("Prev event {prev_id} failed: {e}"); + + match self + .services + .globals + .bad_event_ratelimiter + .write() + .expect("locked") + .entry(prev_id) + { + | Entry::Vacant(e) => { + e.insert((now, 1)); + }, + | Entry::Occupied(mut e) => { + *e.get_mut() = (now, e.get().1.saturating_add(1)); + }, + } + } + } // Done with prev events, now handling the incoming event let start_time = Instant::now(); self.federation_handletime .write() .expect("locked") - .insert(room_id.into(), (event_id.to_owned(), start_time)); + .insert(room_id.to_owned(), (event_id.to_owned(), start_time)); - defer! {{ - self.federation_handletime - .write() - .expect("locked") - .remove(room_id); - }}; + let r = self + .upgrade_outlier_to_timeline_pdu(incoming_pdu, val, &create_event, origin, room_id) + .await; - self.upgrade_outlier_to_timeline_pdu(incoming_pdu, val, create_event, origin, room_id) - .boxed() - .await + self.federation_handletime + .write() + .expect("locked") + .remove(&room_id.to_owned()); + + r } diff --git a/src/service/rooms/event_handler/handle_outlier_pdu.rs b/src/service/rooms/event_handler/handle_outlier_pdu.rs index 5339249d..99e90a50 100644 --- a/src/service/rooms/event_handler/handle_outlier_pdu.rs +++ b/src/service/rooms/event_handler/handle_outlier_pdu.rs @@ -1,9 +1,12 @@ -use std::collections::{BTreeMap, HashMap, hash_map}; +use std::{ + collections::{BTreeMap, HashMap, hash_map}, + sync::Arc, +}; use conduwuit::{ Err, Error, PduEvent, Result, debug, debug_info, err, implement, state_res, trace, warn, }; -use futures::future::ready; +use futures::{TryFutureExt, future::ready}; use ruma::{ CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, ServerName, api::client::error::ErrorKind, events::StateEventType, @@ -21,7 +24,7 @@ pub(super) async fn handle_outlier_pdu<'a>( room_id: &'a RoomId, mut value: CanonicalJsonObject, auth_events_known: bool, -) -> Result<(PduEvent, BTreeMap)> { +) -> Result<(Arc, BTreeMap)> { // 1. Remove unsigned field value.remove("unsigned"); @@ -92,7 +95,7 @@ pub(super) async fn handle_outlier_pdu<'a>( // Build map of auth events let mut auth_events = HashMap::with_capacity(incoming_pdu.auth_events.len()); for id in &incoming_pdu.auth_events { - let Ok(auth_event) = self.services.timeline.get_pdu(id).await else { + let Ok(auth_event) = self.services.timeline.get_pdu(id).map_ok(Arc::new).await else { warn!("Could not find auth event {id}"); continue; }; @@ -120,10 +123,15 @@ pub(super) async fn handle_outlier_pdu<'a>( // The original create event must be in the auth events if !matches!( - auth_events.get(&(StateEventType::RoomCreate, String::new().into())), + auth_events + .get(&(StateEventType::RoomCreate, String::new().into())) + .map(AsRef::as_ref), Some(_) | None ) { - return Err!(Request(InvalidParam("Incoming event refers to wrong create event."))); + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Incoming event refers to wrong create event.", + )); } let state_fetch = |ty: &StateEventType, sk: &str| { @@ -153,5 +161,5 @@ pub(super) async fn handle_outlier_pdu<'a>( trace!("Added pdu as outlier."); - Ok((incoming_pdu, val)) + Ok((Arc::new(incoming_pdu), val)) } diff --git a/src/service/rooms/event_handler/handle_prev_pdu.rs b/src/service/rooms/event_handler/handle_prev_pdu.rs index d612b2bf..cf69a515 100644 --- a/src/service/rooms/event_handler/handle_prev_pdu.rs +++ b/src/service/rooms/event_handler/handle_prev_pdu.rs @@ -1,10 +1,14 @@ -use std::{collections::BTreeMap, time::Instant}; +use std::{ + collections::{BTreeMap, HashMap}, + sync::Arc, + time::Instant, +}; use conduwuit::{ - Err, PduEvent, Result, debug, debug::INFO_SPAN_LEVEL, defer, implement, + Err, PduEvent, Result, debug, debug::INFO_SPAN_LEVEL, implement, utils::continue_exponential_backoff_secs, }; -use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UInt}; +use ruma::{CanonicalJsonValue, EventId, OwnedEventId, RoomId, ServerName, UInt}; #[implement(super::Service)] #[allow(clippy::type_complexity)] @@ -20,10 +24,13 @@ pub(super) async fn handle_prev_pdu<'a>( origin: &'a ServerName, event_id: &'a EventId, room_id: &'a RoomId, - eventid_info: Option<(PduEvent, BTreeMap)>, - create_event: &'a PduEvent, + eventid_info: &mut HashMap< + OwnedEventId, + (Arc, BTreeMap), + >, + create_event: &PduEvent, first_ts_in_room: UInt, - prev_id: &'a EventId, + prev_id: &EventId, ) -> Result { // Check for disabled again because it might have changed if self.services.metadata.is_disabled(room_id).await { @@ -54,35 +61,31 @@ pub(super) async fn handle_prev_pdu<'a>( } } - let Some((pdu, json)) = eventid_info else { - return Ok(()); - }; + if let Some((pdu, json)) = eventid_info.remove(prev_id) { + // Skip old events + if pdu.origin_server_ts < first_ts_in_room { + return Ok(()); + } - // Skip old events - if pdu.origin_server_ts < first_ts_in_room { - return Ok(()); - } - - let start_time = Instant::now(); - self.federation_handletime - .write() - .expect("locked") - .insert(room_id.into(), ((*prev_id).to_owned(), start_time)); - - defer! {{ + let start_time = Instant::now(); self.federation_handletime .write() .expect("locked") - .remove(room_id); - }}; + .insert(room_id.to_owned(), ((*prev_id).to_owned(), start_time)); - self.upgrade_outlier_to_timeline_pdu(pdu, json, create_event, origin, room_id) - .await?; + self.upgrade_outlier_to_timeline_pdu(pdu, json, create_event, origin, room_id) + .await?; - debug!( - elapsed = ?start_time.elapsed(), - "Handled prev_event", - ); + self.federation_handletime + .write() + .expect("locked") + .remove(&room_id.to_owned()); + + debug!( + elapsed = ?start_time.elapsed(), + "Handled prev_event", + ); + } Ok(()) } diff --git a/src/service/rooms/event_handler/state_at_incoming.rs b/src/service/rooms/event_handler/state_at_incoming.rs index eb38c2c3..8326f9da 100644 --- a/src/service/rooms/event_handler/state_at_incoming.rs +++ b/src/service/rooms/event_handler/state_at_incoming.rs @@ -2,12 +2,11 @@ use std::{ borrow::Borrow, collections::{HashMap, HashSet}, iter::Iterator, + sync::Arc, }; use conduwuit::{ - Result, debug, err, implement, - matrix::{PduEvent, StateMap}, - trace, + PduEvent, Result, StateMap, debug, err, implement, trace, utils::stream::{BroadbandExt, IterStream, ReadyExt, TryBroadbandExt, TryWidebandExt}, }; use futures::{FutureExt, StreamExt, TryFutureExt, TryStreamExt, future::try_join}; @@ -21,7 +20,7 @@ use crate::rooms::short::ShortStateHash; #[tracing::instrument(name = "state", level = "debug", skip_all)] pub(super) async fn state_at_incoming_degree_one( &self, - incoming_pdu: &PduEvent, + incoming_pdu: &Arc, ) -> Result>> { let prev_event = &incoming_pdu.prev_events[0]; let Ok(prev_event_sstatehash) = self @@ -68,7 +67,7 @@ pub(super) async fn state_at_incoming_degree_one( #[tracing::instrument(name = "state", level = "debug", skip_all)] pub(super) async fn state_at_incoming_resolved( &self, - incoming_pdu: &PduEvent, + incoming_pdu: &Arc, room_id: &RoomId, room_version_id: &RoomVersionId, ) -> Result>> { diff --git a/src/service/rooms/event_handler/upgrade_outlier_pdu.rs b/src/service/rooms/event_handler/upgrade_outlier_pdu.rs index 97d3df97..c1a1c3eb 100644 --- a/src/service/rooms/event_handler/upgrade_outlier_pdu.rs +++ b/src/service/rooms/event_handler/upgrade_outlier_pdu.rs @@ -1,8 +1,7 @@ use std::{borrow::Borrow, collections::BTreeMap, iter::once, sync::Arc, time::Instant}; use conduwuit::{ - Err, Result, debug, debug_info, err, implement, - matrix::{EventTypeExt, PduEvent, StateKey, state_res}, + Err, EventTypeExt, PduEvent, Result, StateKey, debug, debug_info, err, implement, state_res, trace, utils::stream::{BroadbandExt, ReadyExt}, warn, @@ -19,7 +18,7 @@ use crate::rooms::{ #[implement(super::Service)] pub(super) async fn upgrade_outlier_to_timeline_pdu( &self, - incoming_pdu: PduEvent, + incoming_pdu: Arc, val: BTreeMap, create_event: &PduEvent, origin: &ServerName, diff --git a/src/service/rooms/outlier/mod.rs b/src/service/rooms/outlier/mod.rs index 12b56935..a1b0263a 100644 --- a/src/service/rooms/outlier/mod.rs +++ b/src/service/rooms/outlier/mod.rs @@ -1,9 +1,11 @@ use std::sync::Arc; -use conduwuit::{Result, implement, matrix::pdu::PduEvent}; -use conduwuit_database::{Deserialized, Json, Map}; +use conduwuit::{Result, implement}; +use database::{Deserialized, Json, Map}; use ruma::{CanonicalJsonObject, EventId}; +use crate::PduEvent; + pub struct Service { db: Data, } diff --git a/src/service/rooms/read_receipt/mod.rs b/src/service/rooms/read_receipt/mod.rs index 69e859c4..d6239aee 100644 --- a/src/service/rooms/read_receipt/mod.rs +++ b/src/service/rooms/read_receipt/mod.rs @@ -2,11 +2,7 @@ mod data; use std::{collections::BTreeMap, sync::Arc}; -use conduwuit::{ - Result, debug, err, - matrix::pdu::{PduCount, PduId, RawPduId}, - warn, -}; +use conduwuit::{PduCount, PduId, RawPduId, Result, debug, err, warn}; use futures::{Stream, TryFutureExt, try_join}; use ruma::{ OwnedEventId, OwnedUserId, RoomId, UserId, diff --git a/src/service/rooms/short/mod.rs b/src/service/rooms/short/mod.rs index 06ff6493..3980617e 100644 --- a/src/service/rooms/short/mod.rs +++ b/src/service/rooms/short/mod.rs @@ -1,7 +1,7 @@ use std::{borrow::Borrow, fmt::Debug, mem::size_of_val, sync::Arc}; -pub use conduwuit::matrix::pdu::{ShortEventId, ShortId, ShortRoomId, ShortStateKey}; -use conduwuit::{Result, err, implement, matrix::StateKey, utils, utils::IterStream}; +pub use conduwuit::pdu::{ShortEventId, ShortId, ShortRoomId, ShortStateKey}; +use conduwuit::{Result, StateKey, err, implement, utils, utils::IterStream}; use database::{Deserialized, Get, Map, Qry}; use futures::{Stream, StreamExt}; use ruma::{EventId, RoomId, events::StateEventType}; diff --git a/src/service/rooms/spaces/mod.rs b/src/service/rooms/spaces/mod.rs index ea9756ba..da52e095 100644 --- a/src/service/rooms/spaces/mod.rs +++ b/src/service/rooms/spaces/mod.rs @@ -27,6 +27,7 @@ use ruma::{ }, events::{ StateEventType, + room::join_rules::{JoinRule, RoomJoinRulesEventContent}, space::child::{HierarchySpaceChildEvent, SpaceChildEventContent}, }, serde::Raw, @@ -121,22 +122,21 @@ pub async fn get_summary_and_children_local( | None => (), // cache miss | Some(None) => return Ok(None), | Some(Some(cached)) => { - let allowed_rooms = cached.summary.allowed_room_ids.iter().map(AsRef::as_ref); - - let is_accessible_child = self.is_accessible_child( - current_room, - &cached.summary.join_rule, - identifier, - allowed_rooms, - ); - - let accessibility = if is_accessible_child.await { - SummaryAccessibility::Accessible(cached.summary.clone()) - } else { - SummaryAccessibility::Inaccessible - }; - - return Ok(Some(accessibility)); + return Ok(Some( + if self + .is_accessible_child( + current_room, + &cached.summary.join_rule, + identifier, + &cached.summary.allowed_room_ids, + ) + .await + { + SummaryAccessibility::Accessible(cached.summary.clone()) + } else { + SummaryAccessibility::Inaccessible + }, + )); }, } @@ -146,11 +146,12 @@ pub async fn get_summary_and_children_local( .collect() .await; - let Ok(summary) = self + let summary = self .get_room_summary(current_room, children_pdus, identifier) .boxed() - .await - else { + .await; + + let Ok(summary) = summary else { return Ok(None); }; @@ -217,19 +218,20 @@ async fn get_summary_and_children_federation( .await; let identifier = Identifier::UserId(user_id); - let allowed_room_ids = summary.allowed_room_ids.iter().map(AsRef::as_ref); - let is_accessible_child = self - .is_accessible_child(current_room, &summary.join_rule, &identifier, allowed_room_ids) + .is_accessible_child( + current_room, + &summary.join_rule, + &identifier, + &summary.allowed_room_ids, + ) .await; - let accessibility = if is_accessible_child { - SummaryAccessibility::Accessible(summary) - } else { - SummaryAccessibility::Inaccessible - }; + if is_accessible_child { + return Ok(Some(SummaryAccessibility::Accessible(summary))); + } - Ok(Some(accessibility)) + Ok(Some(SummaryAccessibility::Inaccessible)) } /// Simply returns the stripped m.space.child events of a room @@ -304,19 +306,25 @@ async fn get_room_summary( children_state: Vec>, identifier: &Identifier<'_>, ) -> Result { - let join_rule = self.services.state_accessor.get_join_rules(room_id).await; + let join_rule = self + .services + .state_accessor + .room_state_get_content(room_id, &StateEventType::RoomJoinRules, "") + .await + .map_or(JoinRule::Invite, |c: RoomJoinRulesEventContent| c.join_rule); + let allowed_room_ids = self + .services + .state_accessor + .allowed_room_ids(join_rule.clone()); + + let join_rule = join_rule.clone().into(); let is_accessible_child = self - .is_accessible_child( - room_id, - &join_rule.clone().into(), - identifier, - join_rule.allowed_rooms(), - ) + .is_accessible_child(room_id, &join_rule, identifier, &allowed_room_ids) .await; if !is_accessible_child { - return Err!(Request(Forbidden("User is not allowed to see the room"))); + return Err!(Request(Forbidden("User is not allowed to see the room",))); } let name = self.services.state_accessor.get_name(room_id).ok(); @@ -347,14 +355,6 @@ async fn get_room_summary( .get_avatar(room_id) .map(|res| res.into_option().unwrap_or_default().url); - let room_version = self.services.state.get_room_version(room_id).ok(); - - let encryption = self - .services - .state_accessor - .get_room_encryption(room_id) - .ok(); - let ( canonical_alias, name, @@ -364,8 +364,6 @@ async fn get_room_summary( guest_can_join, avatar_url, room_type, - room_version, - encryption, ) = futures::join!( canonical_alias, name, @@ -374,12 +372,10 @@ async fn get_room_summary( world_readable, guest_can_join, avatar_url, - room_type, - room_version, - encryption, + room_type ); - let summary = SpaceHierarchyParentSummary { + Ok(SpaceHierarchyParentSummary { canonical_alias, name, topic, @@ -388,29 +384,24 @@ async fn get_room_summary( avatar_url, room_type, children_state, - encryption, - room_version, + allowed_room_ids, + join_rule, room_id: room_id.to_owned(), - num_joined_members: num_joined_members.try_into().unwrap_or_default(), - allowed_room_ids: join_rule.allowed_rooms().map(Into::into).collect(), - join_rule: join_rule.clone().into(), - }; - - Ok(summary) + num_joined_members: num_joined_members + .try_into() + .expect("user count should not be that big"), + }) } /// With the given identifier, checks if a room is accessable #[implement(Service)] -async fn is_accessible_child<'a, I>( +async fn is_accessible_child( &self, current_room: &RoomId, join_rule: &SpaceRoomJoinRule, identifier: &Identifier<'_>, - allowed_rooms: I, -) -> bool -where - I: Iterator + Send, -{ + allowed_room_ids: &[OwnedRoomId], +) -> bool { if let Identifier::ServerName(server_name) = identifier { // Checks if ACLs allow for the server to participate if self @@ -435,18 +426,21 @@ where } } - match *join_rule { + match join_rule { | SpaceRoomJoinRule::Public | SpaceRoomJoinRule::Knock | SpaceRoomJoinRule::KnockRestricted => true, | SpaceRoomJoinRule::Restricted => - allowed_rooms + allowed_room_ids + .iter() .stream() - .any(async |room| match identifier { - | Identifier::UserId(user) => - self.services.state_cache.is_joined(user, room).await, - | Identifier::ServerName(server) => - self.services.state_cache.server_in_room(server, room).await, + .any(|room| async { + match identifier { + | Identifier::UserId(user) => + self.services.state_cache.is_joined(user, room).await, + | Identifier::ServerName(server) => + self.services.state_cache.server_in_room(server, room).await, + } }) .await, @@ -493,8 +487,6 @@ async fn cache_insert( join_rule, room_type, allowed_room_ids, - encryption, - room_version, } = child; let summary = SpaceHierarchyParentSummary { @@ -514,8 +506,6 @@ async fn cache_insert( .map(PduEvent::into_stripped_spacechild_state_event) .collect() .await, - encryption, - room_version, }; cache.insert(current_room.to_owned(), Some(CachedSpaceHierarchySummary { summary })); @@ -537,9 +527,7 @@ impl From for SpaceHierarchyRoomsChunk { join_rule, room_type, children_state, - allowed_room_ids, - encryption, - room_version, + .. } = value.summary; Self { @@ -554,9 +542,6 @@ impl From for SpaceHierarchyRoomsChunk { join_rule, room_type, children_state, - encryption, - room_version, - allowed_room_ids, } } } @@ -577,9 +562,7 @@ pub fn summary_to_chunk(summary: SpaceHierarchyParentSummary) -> SpaceHierarchyR join_rule, room_type, children_state, - allowed_room_ids, - encryption, - room_version, + .. } = summary; SpaceHierarchyRoomsChunk { @@ -594,8 +577,5 @@ pub fn summary_to_chunk(summary: SpaceHierarchyParentSummary) -> SpaceHierarchyR join_rule, room_type, children_state, - encryption, - room_version, - allowed_room_ids, } } diff --git a/src/service/rooms/state_accessor/mod.rs b/src/service/rooms/state_accessor/mod.rs index f719fc7b..652fdbd7 100644 --- a/src/service/rooms/state_accessor/mod.rs +++ b/src/service/rooms/state_accessor/mod.rs @@ -3,13 +3,21 @@ mod server_can; mod state; mod user_can; -use std::sync::Arc; +use std::{ + fmt::Write, + sync::{Arc, Mutex as StdMutex, Mutex}, +}; use async_trait::async_trait; -use conduwuit::{Result, err}; +use conduwuit::{ + Result, err, utils, + utils::math::{Expected, usize_from_f64}, +}; use database::Map; +use lru_cache::LruCache; use ruma::{ - EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, RoomId, UserId, + EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, + OwnedUserId, RoomId, UserId, events::{ StateEventType, room::{ @@ -19,18 +27,21 @@ use ruma::{ encryption::RoomEncryptionEventContent, guest_access::{GuestAccess, RoomGuestAccessEventContent}, history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent}, - join_rules::{JoinRule, RoomJoinRulesEventContent}, + join_rules::{AllowRule, JoinRule, RoomJoinRulesEventContent, RoomMembership}, member::RoomMemberEventContent, name::RoomNameEventContent, topic::RoomTopicEventContent, }, }, room::RoomType, + space::SpaceRoomJoinRule, }; -use crate::{Dep, rooms}; +use crate::{Dep, rooms, rooms::short::ShortStateHash}; pub struct Service { + pub server_visibility_cache: Mutex>, + pub user_visibility_cache: Mutex>, services: Services, db: Data, } @@ -50,7 +61,19 @@ struct Data { #[async_trait] impl crate::Service for Service { fn build(args: crate::Args<'_>) -> Result> { + let config = &args.server.config; + let server_visibility_cache_capacity = + f64::from(config.server_visibility_cache_capacity) * config.cache_capacity_modifier; + let user_visibility_cache_capacity = + f64::from(config.user_visibility_cache_capacity) * config.cache_capacity_modifier; + Ok(Arc::new(Self { + server_visibility_cache: StdMutex::new(LruCache::new(usize_from_f64( + server_visibility_cache_capacity, + )?)), + user_visibility_cache: StdMutex::new(LruCache::new(usize_from_f64( + user_visibility_cache_capacity, + )?)), services: Services { state_cache: args.depend::("rooms::state_cache"), timeline: args.depend::("rooms::timeline"), @@ -65,6 +88,44 @@ impl crate::Service for Service { })) } + async fn memory_usage(&self, out: &mut (dyn Write + Send)) -> Result { + use utils::bytes::pretty; + + let (svc_count, svc_bytes) = self.server_visibility_cache.lock()?.iter().fold( + (0_usize, 0_usize), + |(count, bytes), (key, _)| { + ( + count.expected_add(1), + bytes + .expected_add(key.0.capacity()) + .expected_add(size_of_val(&key.1)), + ) + }, + ); + + let (uvc_count, uvc_bytes) = self.user_visibility_cache.lock()?.iter().fold( + (0_usize, 0_usize), + |(count, bytes), (key, _)| { + ( + count.expected_add(1), + bytes + .expected_add(key.0.capacity()) + .expected_add(size_of_val(&key.1)), + ) + }, + ); + + writeln!(out, "server_visibility_cache: {svc_count} ({})", pretty(svc_bytes))?; + writeln!(out, "user_visibility_cache: {uvc_count} ({})", pretty(uvc_bytes))?; + + Ok(()) + } + + async fn clear_cache(&self) { + self.server_visibility_cache.lock().expect("locked").clear(); + self.user_visibility_cache.lock().expect("locked").clear(); + } + fn name(&self) -> &str { crate::service::make_name(std::module_path!()) } } @@ -128,12 +189,30 @@ impl Service { .map(|c: RoomTopicEventContent| c.topic) } - /// Returns the join rules for a given room (`JoinRule` type). Will default - /// to Invite if doesnt exist or invalid - pub async fn get_join_rules(&self, room_id: &RoomId) -> JoinRule { + /// Returns the join rule (`SpaceRoomJoinRule`) for a given room + pub async fn get_join_rule( + &self, + room_id: &RoomId, + ) -> Result<(SpaceRoomJoinRule, Vec)> { self.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "") .await - .map_or(JoinRule::Invite, |c: RoomJoinRulesEventContent| c.join_rule) + .map(|c: RoomJoinRulesEventContent| { + (c.join_rule.clone().into(), self.allowed_room_ids(c.join_rule)) + }) + .or_else(|_| Ok((SpaceRoomJoinRule::Invite, vec![]))) + } + + /// Returns an empty vec if not a restricted room + pub fn allowed_room_ids(&self, join_rule: JoinRule) -> Vec { + let mut room_ids = Vec::with_capacity(1); + if let JoinRule::Restricted(r) | JoinRule::KnockRestricted(r) = join_rule { + for rule in r.allow { + if let AllowRule::RoomMembership(RoomMembership { room_id: membership }) = rule { + room_ids.push(membership.clone()); + } + } + } + room_ids } pub async fn get_room_type(&self, room_id: &RoomId) -> Result { diff --git a/src/service/rooms/state_accessor/room_state.rs b/src/service/rooms/state_accessor/room_state.rs index 89fa2a83..642cd5d2 100644 --- a/src/service/rooms/state_accessor/room_state.rs +++ b/src/service/rooms/state_accessor/room_state.rs @@ -1,9 +1,6 @@ use std::borrow::Borrow; -use conduwuit::{ - Result, err, implement, - matrix::{PduEvent, StateKey}, -}; +use conduwuit::{PduEvent, Result, StateKey, err, implement}; use futures::{Stream, StreamExt, TryFutureExt}; use ruma::{EventId, RoomId, events::StateEventType}; use serde::Deserialize; diff --git a/src/service/rooms/state_accessor/server_can.rs b/src/service/rooms/state_accessor/server_can.rs index 2befec22..2e8f3325 100644 --- a/src/service/rooms/state_accessor/server_can.rs +++ b/src/service/rooms/state_accessor/server_can.rs @@ -1,4 +1,4 @@ -use conduwuit::{implement, utils::stream::ReadyExt}; +use conduwuit::{error, implement, utils::stream::ReadyExt}; use futures::StreamExt; use ruma::{ EventId, RoomId, ServerName, @@ -22,6 +22,15 @@ pub async fn server_can_see_event( return true; }; + if let Some(visibility) = self + .server_visibility_cache + .lock() + .expect("locked") + .get_mut(&(origin.to_owned(), shortstatehash)) + { + return *visibility; + } + let history_visibility = self .state_get_content(shortstatehash, &StateEventType::RoomHistoryVisibility, "") .await @@ -35,7 +44,8 @@ pub async fn server_can_see_event( .room_members(room_id) .ready_filter(|member| member.server_name() == origin); - match history_visibility { + let visibility = match history_visibility { + | HistoryVisibility::WorldReadable | HistoryVisibility::Shared => true, | HistoryVisibility::Invited => { // Allow if any member on requesting server was AT LEAST invited, else deny current_server_members @@ -48,6 +58,16 @@ pub async fn server_can_see_event( .any(|member| self.user_was_joined(shortstatehash, member)) .await }, - | HistoryVisibility::WorldReadable | HistoryVisibility::Shared | _ => true, - } + | _ => { + error!("Unknown history visibility {history_visibility}"); + false + }, + }; + + self.server_visibility_cache + .lock() + .expect("locked") + .insert((origin.to_owned(), shortstatehash), visibility); + + visibility } diff --git a/src/service/rooms/state_accessor/state.rs b/src/service/rooms/state_accessor/state.rs index 169e69e9..8f2dd76f 100644 --- a/src/service/rooms/state_accessor/state.rs +++ b/src/service/rooms/state_accessor/state.rs @@ -1,15 +1,13 @@ use std::{borrow::Borrow, ops::Deref, sync::Arc}; use conduwuit::{ - Result, at, err, implement, - matrix::{PduEvent, StateKey}, - pair_of, + PduEvent, Result, StateKey, at, err, implement, pair_of, utils::{ result::FlatOk, stream::{BroadbandExt, IterStream, ReadyExt, TryIgnore}, }, }; -use conduwuit_database::Deserialized; +use database::Deserialized; use futures::{FutureExt, Stream, StreamExt, TryFutureExt, future::try_join, pin_mut}; use ruma::{ EventId, OwnedEventId, UserId, diff --git a/src/service/rooms/state_accessor/user_can.rs b/src/service/rooms/state_accessor/user_can.rs index 67e0b52b..c30e1da8 100644 --- a/src/service/rooms/state_accessor/user_can.rs +++ b/src/service/rooms/state_accessor/user_can.rs @@ -1,4 +1,4 @@ -use conduwuit::{Err, Result, implement, pdu::PduBuilder}; +use conduwuit::{Err, Error, Result, error, implement, pdu::PduBuilder}; use ruma::{ EventId, RoomId, UserId, events::{ @@ -76,8 +76,8 @@ pub async fn user_can_redact( || redacting_event .as_ref() .is_ok_and(|redacting_event| redacting_event.sender == sender)), - | _ => Err!(Database( - "No m.room.power_levels or m.room.create events in database for room" + | _ => Err(Error::bad_database( + "No m.room.power_levels or m.room.create events in database for room", )), } }, @@ -98,6 +98,15 @@ pub async fn user_can_see_event( return true; }; + if let Some(visibility) = self + .user_visibility_cache + .lock() + .expect("locked") + .get_mut(&(user_id.to_owned(), shortstatehash)) + { + return *visibility; + } + let currently_member = self.services.state_cache.is_joined(user_id, room_id).await; let history_visibility = self @@ -107,7 +116,9 @@ pub async fn user_can_see_event( c.history_visibility }); - match history_visibility { + let visibility = match history_visibility { + | HistoryVisibility::WorldReadable => true, + | HistoryVisibility::Shared => currently_member, | HistoryVisibility::Invited => { // Allow if any member on requesting server was AT LEAST invited, else deny self.user_was_invited(shortstatehash, user_id).await @@ -116,9 +127,18 @@ pub async fn user_can_see_event( // Allow if any member on requested server was joined, else deny self.user_was_joined(shortstatehash, user_id).await }, - | HistoryVisibility::WorldReadable => true, - | HistoryVisibility::Shared | _ => currently_member, - } + | _ => { + error!("Unknown history visibility {history_visibility}"); + false + }, + }; + + self.user_visibility_cache + .lock() + .expect("locked") + .insert((user_id.to_owned(), shortstatehash), visibility); + + visibility } /// Whether a user is allowed to see an event, based on diff --git a/src/service/rooms/state_cache/mod.rs b/src/service/rooms/state_cache/mod.rs index d3dbc143..23ba0520 100644 --- a/src/service/rooms/state_cache/mod.rs +++ b/src/service/rooms/state_cache/mod.rs @@ -40,7 +40,6 @@ struct Services { account_data: Dep, config: Dep, globals: Dep, - metadata: Dep, state_accessor: Dep, users: Dep, } @@ -74,7 +73,6 @@ impl crate::Service for Service { account_data: args.depend::("account_data"), config: args.depend::("config"), globals: args.depend::("globals"), - metadata: args.depend::("rooms::metadata"), state_accessor: args .depend::("rooms::state_accessor"), users: args.depend::("users"), @@ -273,9 +271,7 @@ impl Service { self.mark_as_left(user_id, room_id); if self.services.globals.user_is_local(user_id) - && (self.services.config.forget_forced_upon_leave - || self.services.metadata.is_banned(room_id).await - || self.services.metadata.is_disabled(room_id).await) + && self.services.config.forget_forced_upon_leave { self.forget(room_id, user_id); } diff --git a/src/service/rooms/threads/mod.rs b/src/service/rooms/threads/mod.rs index a680df55..7f9a7515 100644 --- a/src/service/rooms/threads/mod.rs +++ b/src/service/rooms/threads/mod.rs @@ -1,14 +1,13 @@ use std::{collections::BTreeMap, sync::Arc}; use conduwuit::{ - Result, err, - matrix::pdu::{PduCount, PduEvent, PduId, RawPduId}, + PduCount, PduEvent, PduId, RawPduId, Result, err, utils::{ ReadyExt, stream::{TryIgnore, WidebandExt}, }, }; -use conduwuit_database::{Deserialized, Map}; +use database::{Deserialized, Map}; use futures::{Stream, StreamExt}; use ruma::{ CanonicalJsonValue, EventId, OwnedUserId, RoomId, UserId, diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 947e1c38..dc359d22 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -10,19 +10,16 @@ use std::{ }; use async_trait::async_trait; -pub use conduwuit::matrix::pdu::{PduId, RawPduId}; use conduwuit::{ Err, Error, Result, Server, at, debug, debug_warn, err, error, implement, info, - matrix::{ - Event, - pdu::{EventHash, PduBuilder, PduCount, PduEvent, gen_event_id}, - state_res::{self, RoomVersion}, - }, + pdu::{EventHash, PduBuilder, PduCount, PduEvent, gen_event_id}, + state_res::{self, Event, RoomVersion}, utils::{ self, IterStream, MutexMap, MutexMapGuard, ReadyExt, future::TryExtExt, stream::TryIgnore, }, validated, warn, }; +pub use conduwuit::{PduId, RawPduId}; use futures::{ Future, FutureExt, Stream, StreamExt, TryStreamExt, future, future::ready, pin_mut, }; diff --git a/src/service/sending/appservice.rs b/src/service/sending/appservice.rs index c7fae11f..7fa0be9a 100644 --- a/src/service/sending/appservice.rs +++ b/src/service/sending/appservice.rs @@ -25,10 +25,6 @@ where return Ok(None); }; - if dest == *"null" || dest.is_empty() { - return Ok(None); - } - trace!("Appservice URL \"{dest}\", Appservice ID: {}", registration.id); let hs_token = registration.hs_token.as_str(); @@ -38,11 +34,7 @@ where SendAccessToken::IfRequired(hs_token), &VERSIONS, ) - .map_err(|e| { - err!(BadServerResponse( - warn!(appservice = %registration.id, "Failed to find destination {dest}: {e:?}") - )) - })? + .map_err(|e| err!(BadServerResponse(warn!("Failed to find destination {dest}: {e}"))))? .map(BytesMut::freeze); let mut parts = http_request.uri().clone().into_parts(); @@ -59,7 +51,7 @@ where let reqwest_request = reqwest::Request::try_from(http_request)?; let mut response = client.execute(reqwest_request).await.map_err(|e| { - warn!("Could not send request to appservice \"{}\" at {dest}: {e:?}", registration.id); + warn!("Could not send request to appservice \"{}\" at {dest}: {e}", registration.id); e })?; @@ -79,7 +71,7 @@ where if !status.is_success() { debug_error!("Appservice response bytes: {:?}", utils::string_from_bytes(&body)); - return Err!(BadServerResponse(warn!( + return Err!(BadServerResponse(error!( "Appservice \"{}\" returned unsuccessful HTTP response {status} at {dest}", registration.id ))); @@ -92,8 +84,8 @@ where ); response.map(Some).map_err(|e| { - err!(BadServerResponse(warn!( - "Appservice \"{}\" returned invalid/malformed response bytes {dest}: {e}", + err!(BadServerResponse(error!( + "Appservice \"{}\" returned invalid response bytes {dest}: {e}", registration.id ))) }) diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index 1eb289fc..5265e64b 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -350,6 +350,7 @@ impl Service { token: &str, ) -> Result<()> { let key = (user_id, device_id); + // should not be None, but we shouldn't assert either lol... if self.db.userdeviceid_metadata.qry(&key).await.is_err() { return Err!(Database(error!( ?user_id, @@ -593,7 +594,7 @@ impl Service { key_id: &str, signature: (String, String), sender_id: &UserId, - ) -> Result { + ) -> Result<()> { let key = (target_id, key_id); let mut cross_signing_key: serde_json::Value = self @@ -601,27 +602,21 @@ impl Service { .keyid_key .qry(&key) .await - .map_err(|_| err!(Request(InvalidParam("Tried to sign nonexistent key"))))? + .map_err(|_| err!(Request(InvalidParam("Tried to sign nonexistent key."))))? .deserialized() - .map_err(|e| err!(Database(debug_warn!("key in keyid_key is invalid: {e:?}"))))?; + .map_err(|e| err!(Database("key in keyid_key is invalid. {e:?}")))?; let signatures = cross_signing_key .get_mut("signatures") - .ok_or_else(|| { - err!(Database(debug_warn!("key in keyid_key has no signatures field"))) - })? + .ok_or_else(|| err!(Database("key in keyid_key has no signatures field.")))? .as_object_mut() - .ok_or_else(|| { - err!(Database(debug_warn!("key in keyid_key has invalid signatures field."))) - })? + .ok_or_else(|| err!(Database("key in keyid_key has invalid signatures field.")))? .entry(sender_id.to_string()) .or_insert_with(|| serde_json::Map::new().into()); signatures .as_object_mut() - .ok_or_else(|| { - err!(Database(debug_warn!("signatures in keyid_key for a user is invalid."))) - })? + .ok_or_else(|| err!(Database("signatures in keyid_key for a user is invalid.")))? .insert(signature.0, signature.1.into()); let key = (target_id, key_id); diff --git a/tests/test_results/complement/test_results.jsonl b/tests/test_results/complement/test_results.jsonl index 97c2e1b1..c0e28750 100644 --- a/tests/test_results/complement/test_results.jsonl +++ b/tests/test_results/complement/test_results.jsonl @@ -491,7 +491,7 @@ {"Action":"fail","Test":"TestRoomCreationReportsEventsToMyself"} {"Action":"fail","Test":"TestRoomCreationReportsEventsToMyself/parallel"} {"Action":"pass","Test":"TestRoomCreationReportsEventsToMyself/parallel/Joining_room_twice_is_idempotent"} -{"Action":"fail","Test":"TestRoomCreationReportsEventsToMyself/parallel/Room_creation_reports_m.room.create_to_myself"} +{"Action":"pass","Test":"TestRoomCreationReportsEventsToMyself/parallel/Room_creation_reports_m.room.create_to_myself"} {"Action":"pass","Test":"TestRoomCreationReportsEventsToMyself/parallel/Room_creation_reports_m.room.member_to_myself"} {"Action":"pass","Test":"TestRoomCreationReportsEventsToMyself/parallel/Setting_room_topic_reports_m.room.topic_to_myself"} {"Action":"fail","Test":"TestRoomCreationReportsEventsToMyself/parallel/Setting_state_twice_is_idempotent"} @@ -527,17 +527,17 @@ {"Action":"pass","Test":"TestRoomMessagesLazyLoadingLocalUser"} {"Action":"pass","Test":"TestRoomReadMarkers"} {"Action":"pass","Test":"TestRoomReceipts"} -{"Action":"pass","Test":"TestRoomSpecificUsernameAtJoin"} -{"Action":"pass","Test":"TestRoomSpecificUsernameAtJoin/Bob_can_find_Alice_by_mxid"} -{"Action":"pass","Test":"TestRoomSpecificUsernameAtJoin/Bob_can_find_Alice_by_profile_display_name"} -{"Action":"pass","Test":"TestRoomSpecificUsernameAtJoin/Eve_can_find_Alice_by_mxid"} -{"Action":"pass","Test":"TestRoomSpecificUsernameAtJoin/Eve_can_find_Alice_by_profile_display_name"} +{"Action":"fail","Test":"TestRoomSpecificUsernameAtJoin"} +{"Action":"fail","Test":"TestRoomSpecificUsernameAtJoin/Bob_can_find_Alice_by_mxid"} +{"Action":"fail","Test":"TestRoomSpecificUsernameAtJoin/Bob_can_find_Alice_by_profile_display_name"} +{"Action":"fail","Test":"TestRoomSpecificUsernameAtJoin/Eve_can_find_Alice_by_mxid"} +{"Action":"fail","Test":"TestRoomSpecificUsernameAtJoin/Eve_can_find_Alice_by_profile_display_name"} {"Action":"pass","Test":"TestRoomSpecificUsernameAtJoin/Eve_cannot_find_Alice_by_room-specific_name_that_Eve_is_not_privy_to"} -{"Action":"pass","Test":"TestRoomSpecificUsernameChange"} -{"Action":"pass","Test":"TestRoomSpecificUsernameChange/Bob_can_find_Alice_by_mxid"} -{"Action":"pass","Test":"TestRoomSpecificUsernameChange/Bob_can_find_Alice_by_profile_display_name"} -{"Action":"pass","Test":"TestRoomSpecificUsernameChange/Eve_can_find_Alice_by_mxid"} -{"Action":"pass","Test":"TestRoomSpecificUsernameChange/Eve_can_find_Alice_by_profile_display_name"} +{"Action":"fail","Test":"TestRoomSpecificUsernameChange"} +{"Action":"fail","Test":"TestRoomSpecificUsernameChange/Bob_can_find_Alice_by_mxid"} +{"Action":"fail","Test":"TestRoomSpecificUsernameChange/Bob_can_find_Alice_by_profile_display_name"} +{"Action":"fail","Test":"TestRoomSpecificUsernameChange/Eve_can_find_Alice_by_mxid"} +{"Action":"fail","Test":"TestRoomSpecificUsernameChange/Eve_can_find_Alice_by_profile_display_name"} {"Action":"pass","Test":"TestRoomSpecificUsernameChange/Eve_cannot_find_Alice_by_room-specific_name_that_Eve_is_not_privy_to"} {"Action":"fail","Test":"TestRoomState"} {"Action":"fail","Test":"TestRoomState/Parallel"} @@ -589,7 +589,7 @@ {"Action":"fail","Test":"TestSync/parallel/Newly_joined_room_has_correct_timeline_in_incremental_sync"} {"Action":"fail","Test":"TestSync/parallel/Newly_joined_room_includes_presence_in_incremental_sync"} {"Action":"pass","Test":"TestSync/parallel/Newly_joined_room_is_included_in_an_incremental_sync"} -{"Action":"pass","Test":"TestSync/parallel/sync_should_succeed_even_if_the_sync_token_points_to_a_redaction_of_an_unknown_event"} +{"Action":"fail","Test":"TestSync/parallel/sync_should_succeed_even_if_the_sync_token_points_to_a_redaction_of_an_unknown_event"} {"Action":"pass","Test":"TestSyncFilter"} {"Action":"pass","Test":"TestSyncFilter/Can_create_filter"} {"Action":"pass","Test":"TestSyncFilter/Can_download_filter"}