Compare commits

...

21 commits

Author SHA1 Message Date
renovate[bot]
f46bfd1abc
Merge 63230501c9 into 4e5b87d0cd 2025-04-05 22:38:09 +03:30
June Clementine Strawberry
4e5b87d0cd
add missing condition for signatures upload failures
Some checks failed
CI and Artifacts / Test (push) Has been cancelled
CI and Artifacts / Build (push) Has been cancelled
CI and Artifacts / variables (push) Has been cancelled
Documentation and GitHub Pages / Documentation and GitHub Pages (push) Has been cancelled
CI and Artifacts / Docker publish (push) Has been cancelled
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-04 11:34:31 -04:00
Jason Volk
00f7745ec4 remove the db pool queue full warning
Some checks are pending
CI and Artifacts / Test (push) Waiting to run
CI and Artifacts / Build (push) Waiting to run
CI and Artifacts / variables (push) Waiting to run
CI and Artifacts / Docker publish (push) Blocked by required conditions
Documentation and GitHub Pages / Documentation and GitHub Pages (push) Waiting to run
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-04 02:59:54 +00:00
Jason Volk
d036394ec7 refactor incoming prev events loop; mitigate large future
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 22:40:40 +00:00
Jason Volk
6a073b4fa4 remove additional unnecessary Arc
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 22:40:40 +00:00
Jason Volk
b7109131e2 further simplify get_missing_events; various log calls
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 22:40:40 +00:00
June Clementine Strawberry
94b107b42b add some debug logging and misc cleanup to keys/signatures/upload
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-03 16:08:18 -04:00
Jason Volk
29d55b8036 move systemd stopping notification point
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 19:38:51 +00:00
Jason Volk
45fd3875c8 move runtime shutdown out of main; gather final stats
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 19:38:51 +00:00
Jason Volk
f9529937ce patch hyper-util due to conflicts with federation resolver hooks
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 19:38:51 +00:00
Jason Volk
0b56204f89 bump additional dependencies
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 19:38:51 +00:00
Jason Volk
58adb6fead upgrade hickory and hyper-util dependencies
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 19:38:51 +00:00
Jason Volk
5d1404e9df fix well-known using the hooked resolver
Signed-off-by: Jason Volk <jason@zemos.net>
2025-04-03 19:38:51 +00:00
June Clementine Strawberry
f14756fb76 leave room locally if room is banned, rescind knocks on deactivation too
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-03 12:21:16 -04:00
June Clementine Strawberry
24be579477 add appservice MSC4190 support
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-03 12:21:16 -04:00
June Clementine Strawberry
0e0b8cc403
fixup+update msc3266, add fed support, parallelise IO
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-03 00:56:37 -04:00
June Clementine Strawberry
1036f8dfa8
default shared history vis on unknown visibilities, drop needless error log
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-02 22:46:01 -04:00
June Clementine Strawberry
74012c5289
significantly improve get_missing_events fed code
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-02 22:44:44 -04:00
June Clementine Strawberry
ea246d91d9
remove pointless and buggy *_visibility in-memory caches
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-02 22:38:47 -04:00
June Clementine Strawberry
1b71b99c51
fix weird issue with acl c2s check
Signed-off-by: June Clementine Strawberry <june@3.dog>
2025-04-02 10:49:38 -04:00
renovate[bot]
63230501c9
Update opentelemetry-rust monorepo 2025-03-22 02:35:53 +00:00
41 changed files with 1305 additions and 771 deletions

476
Cargo.lock generated
View file

@ -142,6 +142,17 @@ dependencies = [
"zstd-safe", "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]] [[package]]
name = "async-stream" name = "async-stream"
version = "0.3.6" version = "0.3.6"
@ -221,9 +232,9 @@ dependencies = [
[[package]] [[package]]
name = "aws-lc-rs" name = "aws-lc-rs"
version = "1.12.6" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878"
dependencies = [ dependencies = [
"aws-lc-sys", "aws-lc-sys",
"zeroize", "zeroize",
@ -231,9 +242,9 @@ dependencies = [
[[package]] [[package]]
name = "aws-lc-sys" name = "aws-lc-sys"
version = "0.27.1" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f"
dependencies = [ dependencies = [
"bindgen 0.69.5", "bindgen 0.69.5",
"cc", "cc",
@ -652,9 +663,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.34" version = "4.5.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -662,9 +673,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.34" version = "4.5.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"clap_lex", "clap_lex",
@ -731,8 +742,8 @@ dependencies = [
"opentelemetry-jaeger", "opentelemetry-jaeger",
"opentelemetry_sdk", "opentelemetry_sdk",
"sentry", "sentry",
"sentry-tower 0.35.0", "sentry-tower",
"sentry-tracing 0.35.0", "sentry-tracing",
"tokio", "tokio",
"tokio-metrics", "tokio-metrics",
"tracing", "tracing",
@ -905,8 +916,8 @@ dependencies = [
"rustls", "rustls",
"sd-notify", "sd-notify",
"sentry", "sentry",
"sentry-tower 0.35.0", "sentry-tower",
"sentry-tracing 0.35.0", "sentry-tracing",
"serde_json", "serde_json",
"tokio", "tokio",
"tower 0.5.2", "tower 0.5.2",
@ -927,7 +938,7 @@ dependencies = [
"const-str", "const-str",
"either", "either",
"futures", "futures",
"hickory-resolver", "hickory-resolver 0.25.1",
"http", "http",
"image", "image",
"ipaddress", "ipaddress",
@ -1061,6 +1072,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]] [[package]]
name = "crokey" name = "crokey"
version = "1.1.1" version = "1.1.1"
@ -1437,9 +1454,9 @@ dependencies = [
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.1.0" version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide", "miniz_oxide",
@ -1584,6 +1601,19 @@ dependencies = [
"slab", "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]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -1769,6 +1799,34 @@ dependencies = [
"url", "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]] [[package]]
name = "hickory-resolver" name = "hickory-resolver"
version = "0.24.4" version = "0.24.4"
@ -1777,7 +1835,7 @@ checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"futures-util", "futures-util",
"hickory-proto", "hickory-proto 0.24.4",
"ipconfig", "ipconfig",
"lru-cache", "lru-cache",
"once_cell", "once_cell",
@ -1790,6 +1848,28 @@ dependencies = [
"tracing", "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]] [[package]]
name = "hmac" name = "hmac"
version = "0.12.1" version = "0.12.1"
@ -1816,7 +1896,7 @@ checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"windows", "windows 0.52.0",
] ]
[[package]] [[package]]
@ -1936,9 +2016,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper-timeout" name = "hyper-timeout"
version = "0.5.1" version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
dependencies = [ dependencies = [
"hyper", "hyper",
"hyper-util", "hyper-util",
@ -1949,9 +2029,8 @@ dependencies = [
[[package]] [[package]]
name = "hyper-util" name = "hyper-util"
version = "0.1.8" version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/girlbossceo/hyper-util?rev=e4ae7628fe4fcdacef9788c4c8415317a4489941#e4ae7628fe4fcdacef9788c4c8415317a4489941"
checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -1959,10 +2038,10 @@ dependencies = [
"http", "http",
"http-body", "http-body",
"hyper", "hyper",
"libc",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio", "tokio",
"tower 0.4.13",
"tower-service", "tower-service",
"tracing", "tracing",
] ]
@ -2256,10 +2335,11 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.32" version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
dependencies = [ dependencies = [
"getrandom 0.3.2",
"libc", "libc",
] ]
@ -2439,6 +2519,19 @@ dependencies = [
"futures-sink", "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]] [[package]]
name = "loop9" name = "loop9"
version = "0.1.5" version = "0.1.5"
@ -2609,6 +2702,25 @@ dependencies = [
"windows-sys 0.52.0", "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]] [[package]]
name = "new_debug_unreachable" name = "new_debug_unreachable"
version = "1.0.6" version = "1.0.6"
@ -2773,6 +2885,10 @@ name = "once_cell"
version = "1.21.3" version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
dependencies = [
"critical-section",
"portable-atomic",
]
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
@ -3052,6 +3168,12 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "portable-atomic"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
[[package]] [[package]]
name = "powerfmt" name = "powerfmt"
version = "0.2.0" version = "0.2.0"
@ -3452,9 +3574,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.9" version = "0.12.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"base64 0.22.1", "base64 0.22.1",
@ -3463,7 +3585,7 @@ dependencies = [
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2",
"hickory-resolver", "hickory-resolver 0.24.4",
"http", "http",
"http-body", "http-body",
"http-body-util", "http-body-util",
@ -3490,6 +3612,7 @@ dependencies = [
"tokio-rustls", "tokio-rustls",
"tokio-socks", "tokio-socks",
"tokio-util", "tokio-util",
"tower 0.5.2",
"tower-service", "tower-service",
"url", "url",
"wasm-bindgen", "wasm-bindgen",
@ -3531,7 +3654,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma" name = "ruma"
version = "0.10.1" version = "0.10.1"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"assign", "assign",
"js_int", "js_int",
@ -3551,7 +3674,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-appservice-api" name = "ruma-appservice-api"
version = "0.10.0" version = "0.10.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -3563,7 +3686,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-client-api" name = "ruma-client-api"
version = "0.18.0" version = "0.18.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"assign", "assign",
@ -3586,7 +3709,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-common" name = "ruma-common"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"base64 0.22.1", "base64 0.22.1",
@ -3618,7 +3741,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-events" name = "ruma-events"
version = "0.28.1" version = "0.28.1"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"indexmap 2.8.0", "indexmap 2.8.0",
@ -3643,7 +3766,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-federation-api" name = "ruma-federation-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"bytes", "bytes",
"headers", "headers",
@ -3665,7 +3788,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identifiers-validation" name = "ruma-identifiers-validation"
version = "0.9.5" version = "0.9.5"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"js_int", "js_int",
"thiserror 2.0.12", "thiserror 2.0.12",
@ -3674,7 +3797,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identity-service-api" name = "ruma-identity-service-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -3684,7 +3807,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-macros" name = "ruma-macros"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"proc-macro-crate", "proc-macro-crate",
@ -3699,7 +3822,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-push-gateway-api" name = "ruma-push-gateway-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -3711,7 +3834,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-signatures" name = "ruma-signatures"
version = "0.15.0" version = "0.15.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=d197318a2507d38ffe6ee524d0d52728ca72538a#d197318a2507d38ffe6ee524d0d52728ca72538a" source = "git+https://github.com/girlbossceo/ruwuma?rev=edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef#edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"ed25519-dalek", "ed25519-dalek",
@ -3893,6 +4016,12 @@ dependencies = [
"windows-sys 0.59.0", "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]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@ -3939,21 +4068,21 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
[[package]] [[package]]
name = "sentry" name = "sentry"
version = "0.36.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a7332159e544e34db06b251b1eda5e546bd90285c3f58d9c8ff8450b484e0da" checksum = "255914a8e53822abd946e2ce8baa41d4cded6b8e938913b7f7b9da5b7ab44335"
dependencies = [ dependencies = [
"httpdate", "httpdate",
"reqwest", "reqwest",
"rustls", "rustls",
"sentry-backtrace", "sentry-backtrace",
"sentry-contexts", "sentry-contexts",
"sentry-core 0.36.0", "sentry-core",
"sentry-debug-images", "sentry-debug-images",
"sentry-log", "sentry-log",
"sentry-panic", "sentry-panic",
"sentry-tower 0.36.0", "sentry-tower",
"sentry-tracing 0.36.0", "sentry-tracing",
"tokio", "tokio",
"ureq", "ureq",
"webpki-roots", "webpki-roots",
@ -3961,107 +4090,83 @@ dependencies = [
[[package]] [[package]]
name = "sentry-backtrace" name = "sentry-backtrace"
version = "0.36.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "565ec31ad37bab8e6d9f289f34913ed8768347b133706192f10606dabd5c6bc4" checksum = "00293cd332a859961f24fd69258f7e92af736feaeb91020cff84dac4188a4302"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"once_cell", "once_cell",
"regex", "regex",
"sentry-core 0.36.0", "sentry-core",
] ]
[[package]] [[package]]
name = "sentry-contexts" name = "sentry-contexts"
version = "0.36.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e860275f25f27e8c0c7726ce116c7d5c928c5bba2ee73306e52b20a752298ea6" checksum = "961990f9caa76476c481de130ada05614cd7f5aa70fb57c2142f0e09ad3fb2aa"
dependencies = [ dependencies = [
"hostname", "hostname",
"libc", "libc",
"os_info", "os_info",
"rustc_version", "rustc_version",
"sentry-core 0.36.0", "sentry-core",
"uname", "uname",
] ]
[[package]] [[package]]
name = "sentry-core" name = "sentry-core"
version = "0.35.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9f8b6dcd4fbae1e3e22b447f32670360b27e31b62ab040f7fb04e0f80c04d92" checksum = "1a6409d845707d82415c800290a5d63be5e3df3c2e417b0997c60531dfbd35ef"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"rand 0.8.5", "rand 0.8.5",
"sentry-types 0.35.0", "sentry-types",
"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",
"serde_json", "serde_json",
] ]
[[package]] [[package]]
name = "sentry-debug-images" name = "sentry-debug-images"
version = "0.36.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60bc2154e6df59beed0ac13d58f8dfaf5ad20a88548a53e29e4d92e8e835c2" checksum = "71ab5df4f3b64760508edfe0ba4290feab5acbbda7566a79d72673065888e5cc"
dependencies = [ dependencies = [
"findshlibs", "findshlibs",
"once_cell", "once_cell",
"sentry-core 0.36.0", "sentry-core",
] ]
[[package]] [[package]]
name = "sentry-log" name = "sentry-log"
version = "0.36.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c96d796cba1b3a0793e7f53edc420c61f9419fba8fb34ad5519f5c7d01af6b2" checksum = "693841da8dfb693af29105edfbea1d91348a13d23dd0a5d03761eedb9e450c46"
dependencies = [ dependencies = [
"log", "log",
"sentry-core 0.36.0", "sentry-core",
] ]
[[package]] [[package]]
name = "sentry-panic" name = "sentry-panic"
version = "0.36.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "105e3a956c8aa9dab1e4087b1657b03271bfc49d838c6ae9bfc7c58c802fd0ef" checksum = "609b1a12340495ce17baeec9e08ff8ed423c337c1a84dffae36a178c783623f3"
dependencies = [ dependencies = [
"sentry-backtrace", "sentry-backtrace",
"sentry-core 0.36.0", "sentry-core",
] ]
[[package]] [[package]]
name = "sentry-tower" name = "sentry-tower"
version = "0.35.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcdaf9b1939589476bd57751d12a9653bbfe356610fc476d03d7683189183ab7" checksum = "4b98005537e38ee3bc10e7d36e7febe9b8e573d03f2ddd85fcdf05d21f9abd6d"
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 = [ dependencies = [
"http", "http",
"pin-project", "pin-project",
"sentry-core 0.36.0", "sentry-core",
"tower-layer", "tower-layer",
"tower-service", "tower-service",
"url", "url",
@ -4069,49 +4174,21 @@ dependencies = [
[[package]] [[package]]
name = "sentry-tracing" name = "sentry-tracing"
version = "0.35.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "263f73c757ed7915d3e1e34625eae18cad498a95b4261603d4ce3f87b159a6f0" checksum = "49f4e86402d5c50239dc7d8fd3f6d5e048221d5fcb4e026d8d50ab57fe4644cb"
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 = [ dependencies = [
"sentry-backtrace", "sentry-backtrace",
"sentry-core 0.36.0", "sentry-core",
"tracing-core", "tracing-core",
"tracing-subscriber", "tracing-subscriber",
] ]
[[package]] [[package]]
name = "sentry-types" name = "sentry-types"
version = "0.35.0" version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a71ed3a389948a6a6d92b98e997a2723ca22f09660c5a7b7388ecd509a70a527" checksum = "3d3f117b8755dbede8260952de2aeb029e20f432e72634e8969af34324591631"
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 = [ dependencies = [
"debugid", "debugid",
"hex", "hex",
@ -4464,6 +4541,12 @@ dependencies = [
"version-compare", "version-compare",
] ]
[[package]]
name = "tagptr"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.16" version = "0.12.16"
@ -5367,7 +5450,17 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [ dependencies = [
"windows-core", "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-targets 0.52.6", "windows-targets 0.52.6",
] ]
@ -5381,16 +5474,57 @@ dependencies = [
] ]
[[package]] [[package]]
name = "windows-registry" name = "windows-core"
version = "0.2.0" version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [ dependencies = [
"windows-result", "windows-implement",
"windows-strings", "windows-interface",
"windows-result 0.2.0",
"windows-strings 0.1.0",
"windows-targets 0.52.6", "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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
dependencies = [
"windows-result 0.3.2",
"windows-strings 0.3.1",
"windows-targets 0.53.0",
]
[[package]] [[package]]
name = "windows-result" name = "windows-result"
version = "0.2.0" version = "0.2.0"
@ -5400,16 +5534,34 @@ dependencies = [
"windows-targets 0.52.6", "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]] [[package]]
name = "windows-strings" name = "windows-strings"
version = "0.1.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [ dependencies = [
"windows-result", "windows-result 0.2.0",
"windows-targets 0.52.6", "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]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"
@ -5461,13 +5613,29 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6", "windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6", "windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6", "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm", "windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6", "windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6", "windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6", "windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 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]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.48.5" version = "0.48.5"
@ -5480,6 +5648,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.48.5" version = "0.48.5"
@ -5492,6 +5666,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.48.5" version = "0.48.5"
@ -5504,12 +5684,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]] [[package]]
name = "windows_i686_gnullvm" name = "windows_i686_gnullvm"
version = "0.52.6" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.48.5" version = "0.48.5"
@ -5522,6 +5714,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.48.5" version = "0.48.5"
@ -5534,6 +5732,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 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]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.48.5" version = "0.48.5"
@ -5546,6 +5750,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 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]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"
@ -5558,6 +5768,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 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]] [[package]]
name = "winnow" name = "winnow"
version = "0.7.4" version = "0.7.4"

View file

@ -141,12 +141,12 @@ features = [
] ]
[workspace.dependencies.rustls] [workspace.dependencies.rustls]
version = "0.23.19" version = "0.23.25"
default-features = false default-features = false
features = ["aws_lc_rs"] features = ["aws_lc_rs"]
[workspace.dependencies.reqwest] [workspace.dependencies.reqwest]
version = "0.12.9" version = "0.12.15"
default-features = false default-features = false
features = [ features = [
"rustls-tls-native-roots", "rustls-tls-native-roots",
@ -204,7 +204,7 @@ features = [
# logging # logging
[workspace.dependencies.log] [workspace.dependencies.log]
version = "0.4.22" version = "0.4.27"
default-features = false default-features = false
[workspace.dependencies.tracing] [workspace.dependencies.tracing]
version = "0.1.41" version = "0.1.41"
@ -224,7 +224,7 @@ default-features = false
# used for conduwuit's CLI and admin room command parsing # used for conduwuit's CLI and admin room command parsing
[workspace.dependencies.clap] [workspace.dependencies.clap]
version = "4.5.23" version = "4.5.35"
default-features = false default-features = false
features = [ features = [
"derive", "derive",
@ -284,8 +284,7 @@ features = [
] ]
[workspace.dependencies.hyper-util] [workspace.dependencies.hyper-util]
# hyper-util >=0.1.9 seems to have DNS issues version = "0.1.11"
version = "=0.1.8"
default-features = false default-features = false
features = [ features = [
"server-auto", "server-auto",
@ -306,8 +305,13 @@ default-features = false
features = ["env", "toml"] features = ["env", "toml"]
[workspace.dependencies.hickory-resolver] [workspace.dependencies.hickory-resolver]
version = "0.24.2" version = "0.25.1"
default-features = false default-features = false
features = [
"serde",
"system-config",
"tokio",
]
# Used for conduwuit::Error type # Used for conduwuit::Error type
[workspace.dependencies.thiserror] [workspace.dependencies.thiserror]
@ -316,7 +320,7 @@ default-features = false
# Used when hashing the state # Used when hashing the state
[workspace.dependencies.ring] [workspace.dependencies.ring]
version = "0.17.8" version = "0.17.14"
default-features = false default-features = false
# Used to make working with iterators easier, was already a transitive depdendency # Used to make working with iterators easier, was already a transitive depdendency
@ -346,7 +350,7 @@ version = "0.1.2"
[workspace.dependencies.ruma] [workspace.dependencies.ruma]
git = "https://github.com/girlbossceo/ruwuma" git = "https://github.com/girlbossceo/ruwuma"
#branch = "conduwuit-changes" #branch = "conduwuit-changes"
rev = "d197318a2507d38ffe6ee524d0d52728ca72538a" rev = "edbdc79e560d01d9e4a76f7421e70ea4fd4c54ef"
features = [ features = [
"compat", "compat",
"rand", "rand",
@ -405,7 +409,7 @@ default-features = false
# optional opentelemetry, performance measurements, flamegraphs, etc for performance measurements and monitoring # optional opentelemetry, performance measurements, flamegraphs, etc for performance measurements and monitoring
[workspace.dependencies.opentelemetry] [workspace.dependencies.opentelemetry]
version = "0.21.0" version = "0.29.0"
[workspace.dependencies.tracing-flame] [workspace.dependencies.tracing-flame]
version = "0.2.0" version = "0.2.0"
@ -414,16 +418,16 @@ version = "0.2.0"
version = "0.22.0" version = "0.22.0"
[workspace.dependencies.opentelemetry_sdk] [workspace.dependencies.opentelemetry_sdk]
version = "0.21.2" version = "0.29.0"
features = ["rt-tokio"] features = ["rt-tokio"]
[workspace.dependencies.opentelemetry-jaeger] [workspace.dependencies.opentelemetry-jaeger]
version = "0.20.0" version = "0.22.0"
features = ["rt-tokio"] features = ["rt-tokio"]
# optional sentry metrics for crash/panic reporting # optional sentry metrics for crash/panic reporting
[workspace.dependencies.sentry] [workspace.dependencies.sentry]
version = "0.36.0" version = "0.37.0"
default-features = false default-features = false
features = [ features = [
"backtrace", "backtrace",
@ -439,9 +443,9 @@ features = [
] ]
[workspace.dependencies.sentry-tracing] [workspace.dependencies.sentry-tracing]
version = "0.35.0" version = "0.37.0"
[workspace.dependencies.sentry-tower] [workspace.dependencies.sentry-tower]
version = "0.35.0" version = "0.37.0"
# jemalloc usage # jemalloc usage
[workspace.dependencies.tikv-jemalloc-sys] [workspace.dependencies.tikv-jemalloc-sys]
@ -475,7 +479,7 @@ default-features = false
features = ["resource"] features = ["resource"]
[workspace.dependencies.sd-notify] [workspace.dependencies.sd-notify]
version = "0.4.3" version = "0.4.5"
default-features = false default-features = false
[workspace.dependencies.hardened_malloc-rs] [workspace.dependencies.hardened_malloc-rs]
@ -492,7 +496,7 @@ version = "0.4.3"
default-features = false default-features = false
[workspace.dependencies.termimad] [workspace.dependencies.termimad]
version = "0.31.1" version = "0.31.2"
default-features = false default-features = false
[workspace.dependencies.checked_ops] [workspace.dependencies.checked_ops]
@ -566,10 +570,16 @@ rev = "fe4aebeeaae435af60087ddd56b573a2e0be671d"
git = "https://github.com/girlbossceo/async-channel" git = "https://github.com/girlbossceo/async-channel"
rev = "92e5e74063bf2a3b10414bcc8a0d68b235644280" rev = "92e5e74063bf2a3b10414bcc8a0d68b235644280"
# adds affinity masks for selecting more than one core at a time
[patch.crates-io.core_affinity] [patch.crates-io.core_affinity]
git = "https://github.com/girlbossceo/core_affinity_rs" git = "https://github.com/girlbossceo/core_affinity_rs"
rev = "9c8e51510c35077df888ee72a36b4b05637147da" 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"
# #
# Our crates # Our crates
# #

View file

@ -195,14 +195,6 @@
# #
#servernameevent_data_cache_capacity = varies by system #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. # This item is undocumented. Please contribute documentation for it.
# #
#stateinfo_cache_capacity = varies by system #stateinfo_cache_capacity = varies by system

View file

@ -318,14 +318,14 @@ pub(crate) async fn register_route(
// Success! // Success!
}, },
| _ => match body.json_body { | _ => match body.json_body {
| Some(json) => { | Some(ref json) => {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
services.uiaa.create( services.uiaa.create(
&UserId::parse_with_server_name("", services.globals.server_name()) &UserId::parse_with_server_name("", services.globals.server_name())
.unwrap(), .unwrap(),
"".into(), "".into(),
&uiaainfo, &uiaainfo,
&json, json,
); );
return Err(Error::Uiaa(uiaainfo)); return Err(Error::Uiaa(uiaainfo));
}, },
@ -373,8 +373,12 @@ pub(crate) async fn register_route(
) )
.await?; .await?;
// Inhibit login does not work for guests if (!is_guest && body.inhibit_login)
if !is_guest && body.inhibit_login { || body
.appservice_info
.as_ref()
.is_some_and(|appservice| appservice.registration.device_management)
{
return Ok(register::v3::Response { return Ok(register::v3::Response {
access_token: None, access_token: None,
user_id, user_id,

View file

@ -22,7 +22,13 @@ pub(crate) async fn appservice_ping(
))); )));
} }
if appservice_info.registration.url.is_none() { if appservice_info.registration.url.is_none()
|| appservice_info
.registration
.url
.as_ref()
.is_some_and(|url| url.is_empty() || url == "null")
{
return Err!(Request(UrlNotSet( return Err!(Request(UrlNotSet(
"Appservice does not have a URL set, there is nothing to ping." "Appservice does not have a URL set, there is nothing to ping."
))); )));

View file

@ -1,9 +1,9 @@
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp; use axum_client_ip::InsecureClientIp;
use conduwuit::{Err, err}; use conduwuit::{Err, debug, err};
use futures::StreamExt; use futures::StreamExt;
use ruma::{ use ruma::{
MilliSecondsSinceUnixEpoch, MilliSecondsSinceUnixEpoch, OwnedDeviceId,
api::client::{ api::client::{
device::{self, delete_device, delete_devices, get_device, get_devices, update_device}, device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
error::ErrorKind, error::ErrorKind,
@ -12,7 +12,7 @@ use ruma::{
}; };
use super::SESSION_ID_LENGTH; use super::SESSION_ID_LENGTH;
use crate::{Error, Result, Ruma, utils}; use crate::{Error, Result, Ruma, client::DEVICE_ID_LENGTH, utils};
/// # `GET /_matrix/client/r0/devices` /// # `GET /_matrix/client/r0/devices`
/// ///
@ -59,26 +59,58 @@ pub(crate) async fn update_device_route(
InsecureClientIp(client): InsecureClientIp, InsecureClientIp(client): InsecureClientIp,
body: Ruma<update_device::v3::Request>, body: Ruma<update_device::v3::Request>,
) -> Result<update_device::v3::Response> { ) -> Result<update_device::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user();
let appservice = body.appservice_info.as_ref();
let mut device = services match services
.users .users
.get_device_metadata(sender_user, &body.device_id) .get_device_metadata(sender_user, &body.device_id)
.await .await
.map_err(|_| err!(Request(NotFound("Device not found."))))?; {
| 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()));
device.display_name.clone_from(&body.display_name); services
device.last_seen_ip.clone_from(&Some(client.to_string())); .users
device .update_device_metadata(sender_user, &body.device_id, &device)
.last_seen_ts .await?;
.clone_from(&Some(MilliSecondsSinceUnixEpoch::now()));
services Ok(update_device::v3::Response {})
.users },
.update_device_metadata(sender_user, &body.device_id, &device) | Err(_) => {
.await?; let Some(appservice) = appservice else {
return Err!(Request(NotFound("Device not found.")));
};
if !appservice.registration.device_management {
return Err!(Request(NotFound("Device not found.")));
}
Ok(update_device::v3::Response {}) 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 {});
},
}
} }
/// # `DELETE /_matrix/client/r0/devices/{deviceId}` /// # `DELETE /_matrix/client/r0/devices/{deviceId}`
@ -95,8 +127,21 @@ pub(crate) async fn delete_device_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_device::v3::Request>, body: Ruma<delete_device::v3::Request>,
) -> Result<delete_device::v3::Response> { ) -> Result<delete_device::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let (sender_user, sender_device) = body.sender();
let sender_device = body.sender_device.as_ref().expect("user is authenticated"); 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 {});
}
// UIAA // UIAA
let mut uiaainfo = UiaaInfo { let mut uiaainfo = UiaaInfo {
@ -120,11 +165,11 @@ pub(crate) async fn delete_device_route(
// Success! // Success!
}, },
| _ => match body.json_body { | _ => match body.json_body {
| Some(json) => { | Some(ref json) => {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
services services
.uiaa .uiaa
.create(sender_user, sender_device, &uiaainfo, &json); .create(sender_user, sender_device, &uiaainfo, json);
return Err!(Uiaa(uiaainfo)); return Err!(Uiaa(uiaainfo));
}, },
@ -142,11 +187,12 @@ pub(crate) async fn delete_device_route(
Ok(delete_device::v3::Response {}) Ok(delete_device::v3::Response {})
} }
/// # `PUT /_matrix/client/r0/devices/{deviceId}` /// # `POST /_matrix/client/v3/delete_devices`
/// ///
/// Deletes the given device. /// Deletes the given list of devices.
/// ///
/// - Requires UIAA to verify user password /// - Requires UIAA to verify user password unless from an appservice with
/// MSC4190 enabled.
/// ///
/// For each device: /// For each device:
/// - Invalidates access token /// - Invalidates access token
@ -158,8 +204,20 @@ pub(crate) async fn delete_devices_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_devices::v3::Request>, body: Ruma<delete_devices::v3::Request>,
) -> Result<delete_devices::v3::Response> { ) -> Result<delete_devices::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let (sender_user, sender_device) = body.sender();
let sender_device = body.sender_device.as_ref().expect("user is authenticated"); 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 {});
}
// UIAA // UIAA
let mut uiaainfo = UiaaInfo { let mut uiaainfo = UiaaInfo {
@ -183,11 +241,11 @@ pub(crate) async fn delete_devices_route(
// Success! // Success!
}, },
| _ => match body.json_body { | _ => match body.json_body {
| Some(json) => { | Some(ref json) => {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH)); uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
services services
.uiaa .uiaa
.create(sender_user, sender_device, &uiaainfo, &json); .create(sender_user, sender_device, &uiaainfo, json);
return Err(Error::Uiaa(uiaainfo)); return Err(Error::Uiaa(uiaainfo));
}, },

View file

@ -9,7 +9,8 @@ use ruma::{
client::{ client::{
error::ErrorKind, error::ErrorKind,
keys::{ keys::{
claim_keys, get_key_changes, get_keys, upload_keys, upload_signatures, claim_keys, get_key_changes, get_keys, upload_keys,
upload_signatures::{self, v3::Failure},
upload_signing_keys, upload_signing_keys,
}, },
uiaa::{AuthFlow, AuthType, UiaaInfo}, uiaa::{AuthFlow, AuthType, UiaaInfo},
@ -308,53 +309,83 @@ async fn check_for_new_keys(
/// # `POST /_matrix/client/r0/keys/signatures/upload` /// # `POST /_matrix/client/r0/keys/signatures/upload`
/// ///
/// Uploads end-to-end key signatures from the sender user. /// Uploads end-to-end key signatures from the sender user.
///
/// TODO: clean this timo-code up more. 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( pub(crate) async fn upload_signatures_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<upload_signatures::v3::Request>, body: Ruma<upload_signatures::v3::Request>,
) -> Result<upload_signatures::v3::Response> { ) -> Result<upload_signatures::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); use upload_signatures::v3::FailureErrorCode::*;
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 mut failures: BTreeMap<OwnedUserId, BTreeMap<String, Failure>> = BTreeMap::new();
let mut failure_reasons: BTreeMap<String, Failure> = BTreeMap::new();
let failure = Failure {
errcode: InvalidSignature,
error: String::new(),
};
for (user_id, keys) in &body.signed_keys { for (user_id, keys) in &body.signed_keys {
for (key_id, key) in keys { for (key_id, key) in keys {
let key = serde_json::to_value(key) let Ok(key) = serde_json::to_value(key)
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid key JSON"))?; .inspect_err(|e| debug_warn!(?key_id, "Invalid \"key\" JSON: {e}"))
else {
let mut failure = failure.clone();
failure.error = String::from("Invalid \"key\" JSON");
failure_reasons.insert(key_id.to_owned(), failure);
continue;
};
for signature in key let Some(signatures) = key.get("signatures") else {
.get("signatures") let mut failure = failure.clone();
.ok_or(Error::BadRequest(ErrorKind::InvalidParam, "Missing signatures field."))? failure.error = String::from("Missing \"signatures\" field");
.get(sender_user.to_string()) failure_reasons.insert(key_id.to_owned(), failure);
.ok_or(Error::BadRequest( continue;
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(),
);
services let Some(sender_user_val) = signatures.get(sender_user.to_string()) else {
let mut failure = failure.clone();
failure.error = String::from("Invalid user in signatures field");
failure_reasons.insert(key_id.to_owned(), failure);
continue;
};
let Some(sender_user_object) = sender_user_val.as_object() else {
let mut failure = failure.clone();
failure.error = String::from("signatures field is not a JSON object");
failure_reasons.insert(key_id.to_owned(), failure);
continue;
};
for (signature, val) in sender_user_object.clone() {
let signature = (signature, val.to_string());
if let Err(e) = services
.users .users
.sign_key(user_id, key_id, signature, sender_user) .sign_key(user_id, key_id, signature, sender_user)
.await?; .await
.inspect_err(|e| debug_warn!("{e}"))
{
let mut failure = failure.clone();
failure.error = format!("Error signing key: {e}");
failure_reasons.insert(key_id.to_owned(), failure);
continue;
}
} }
} }
if !failure_reasons.is_empty() {
failures.insert(user_id.to_owned(), failure_reasons.clone());
}
} }
Ok(upload_signatures::v3::Response { Ok(upload_signatures::v3::Response { failures })
failures: BTreeMap::new(), // TODO: integrate
})
} }
/// # `POST /_matrix/client/r0/keys/changes` /// # `POST /_matrix/client/r0/keys/changes`

View file

@ -475,9 +475,9 @@ pub(crate) async fn leave_room_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<leave_room::v3::Request>, body: Ruma<leave_room::v3::Request>,
) -> Result<leave_room::v3::Response> { ) -> Result<leave_room::v3::Response> {
leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone()).await?; leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone())
.await
Ok(leave_room::v3::Response::new()) .map(|()| leave_room::v3::Response::new())
} }
/// # `POST /_matrix/client/r0/rooms/{roomId}/invite` /// # `POST /_matrix/client/r0/rooms/{roomId}/invite`
@ -1763,8 +1763,8 @@ pub(crate) async fn invite_helper(
Ok(()) Ok(())
} }
// Make a user leave all their joined rooms, forgets all rooms, and ignores // Make a user leave all their joined rooms, rescinds knocks, forgets all rooms,
// errors // and ignores errors
pub async fn leave_all_rooms(services: &Services, user_id: &UserId) { pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
let rooms_joined = services let rooms_joined = services
.rooms .rooms
@ -1778,7 +1778,17 @@ pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
.rooms_invited(user_id) .rooms_invited(user_id)
.map(|(r, _)| r); .map(|(r, _)| r);
let all_rooms: Vec<_> = rooms_joined.chain(rooms_invited).collect().await; 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;
for room_id in all_rooms { for room_id in all_rooms {
// ignore errors // ignore errors
@ -1795,7 +1805,40 @@ pub async fn leave_room(
user_id: &UserId, user_id: &UserId,
room_id: &RoomId, room_id: &RoomId,
reason: Option<String>, reason: Option<String>,
) -> Result<()> { ) -> 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(());
}
// Ask a remote server if we don't have this room and are not knocking on it // Ask a remote server if we don't have this room and are not knocking on it
if !services if !services
.rooms .rooms
@ -1828,7 +1871,7 @@ pub async fn leave_room(
.update_membership( .update_membership(
room_id, room_id,
user_id, user_id,
RoomMemberEventContent::new(MembershipState::Leave), default_member_content,
user_id, user_id,
last_state, last_state,
None, None,
@ -1848,26 +1891,23 @@ pub async fn leave_room(
) )
.await .await
else { else {
// Fix for broken rooms debug_warn!(
warn!(
"Trying to leave a room you are not a member of, marking room as left locally." "Trying to leave a room you are not a member of, marking room as left locally."
); );
services return services
.rooms .rooms
.state_cache .state_cache
.update_membership( .update_membership(
room_id, room_id,
user_id, user_id,
RoomMemberEventContent::new(MembershipState::Leave), default_member_content,
user_id, user_id,
None, None,
None, None,
true, true,
) )
.await?; .await;
return Ok(());
}; };
services services
@ -1897,7 +1937,7 @@ async fn remote_leave_room(
room_id: &RoomId, room_id: &RoomId,
) -> Result<()> { ) -> Result<()> {
let mut make_leave_response_and_server = let mut make_leave_response_and_server =
Err!(BadServerResponse("No server available to assist in leaving.")); Err!(BadServerResponse("No remote server available to assist in leaving {room_id}."));
let mut servers: HashSet<OwnedServerName> = services let mut servers: HashSet<OwnedServerName> = services
.rooms .rooms
@ -1977,20 +2017,25 @@ async fn remote_leave_room(
let (make_leave_response, remote_server) = make_leave_response_and_server?; let (make_leave_response, remote_server) = make_leave_response_and_server?;
let Some(room_version_id) = make_leave_response.room_version else { let Some(room_version_id) = make_leave_response.room_version else {
return Err!(BadServerResponse("Remote room version is not supported by conduwuit")); return Err!(BadServerResponse(warn!(
"No room version was returned by {remote_server} for {room_id}, room version is \
likely not supported by conduwuit"
)));
}; };
if !services.server.supported_room_version(&room_version_id) { if !services.server.supported_room_version(&room_version_id) {
return Err!(BadServerResponse( return Err!(BadServerResponse(warn!(
"Remote room version {room_version_id} is not supported by conduwuit" "Remote room version {room_version_id} for {room_id} is not supported by conduwuit",
)); )));
} }
let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>( let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>(
make_leave_response.event.get(), make_leave_response.event.get(),
) )
.map_err(|e| { .map_err(|e| {
err!(BadServerResponse("Invalid make_leave event json received from server: {e:?}")) err!(BadServerResponse(warn!(
"Invalid make_leave event json received from {remote_server} for {room_id}: {e:?}"
)))
})?; })?;
// TODO: Is origin needed? // TODO: Is origin needed?

View file

@ -2,9 +2,14 @@ mod aliases;
mod create; mod create;
mod event; mod event;
mod initial_sync; mod initial_sync;
mod summary;
mod upgrade; mod upgrade;
pub(crate) use self::{ pub(crate) use self::{
aliases::get_room_aliases_route, create::create_room_route, event::get_room_event_route, aliases::get_room_aliases_route,
initial_sync::room_initial_sync_route, upgrade::upgrade_room_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,
}; };

View file

@ -0,0 +1,308 @@
use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduwuit::{
Err, Result, debug_warn,
utils::{IterStream, future::TryExtExt},
};
use futures::{FutureExt, StreamExt, future::join3, stream::FuturesUnordered};
use ruma::{
OwnedRoomId, 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<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_summary::msc3266::Request>,
) -> Result<RumaResponse<get_summary::msc3266::Response>> {
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<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_summary::msc3266::Request>,
) -> Result<get_summary::msc3266::Response> {
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<get_summary::msc3266::Response> {
if services.rooms.metadata.exists(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,
membership: if sender_user.is_none() {
None
} else {
Some(MembershipState::Leave)
},
encryption: room.encryption,
allowed_room_ids: room.allowed_room_ids,
})
}
async fn local_room_summary_response(
services: &Services,
room_id: &RoomId,
sender_user: Option<&UserId>,
) -> Result<get_summary::msc3266::Response> {
let join_rule = services.rooms.state_accessor.get_space_join_rule(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, allowed_room_ids), world_readable, guest_can_join) =
join3(join_rule, world_readable, guest_can_join).await;
user_can_see_summary(
services,
room_id,
&join_rule,
guest_can_join,
world_readable,
&allowed_room_ids,
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 (
canonical_alias,
name,
num_joined_members,
topic,
avatar_url,
room_type,
room_version,
encryption,
) = futures::join!(
canonical_alias,
name,
num_joined_members,
topic,
avatar_url,
room_type,
room_version,
encryption,
);
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,
join_rule,
room_type,
room_version,
membership: if let Some(sender_user) = sender_user {
services
.rooms
.state_accessor
.get_member(room_id, sender_user)
.await
.map_or(Some(MembershipState::Leave), |content| Some(content.membership))
} else {
None
},
encryption,
allowed_room_ids,
})
}
/// 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<SpaceHierarchyParentSummary> {
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 {
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,
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(
services: &Services,
room_id: &RoomId,
join_rule: &SpaceRoomJoinRule,
guest_can_join: bool,
world_readable: bool,
allowed_room_ids: &[OwnedRoomId],
sender_user: Option<&UserId>,
) -> Result {
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
.iter()
.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)
|| matches!(&join_rule, &Public | &Knock | &KnockRestricted)
|| 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 matches!(join_rule, Public | Knock | KnockRestricted) || world_readable {
return Ok(());
}
Err!(Request(Forbidden(
"Room is not world readable or publicly accessible/joinable, authentication is \
required"
)))
},
}
}

View file

@ -103,7 +103,7 @@ pub(crate) async fn upgrade_room_route(
// Use the m.room.tombstone event as the predecessor // Use the m.room.tombstone event as the predecessor
let predecessor = Some(ruma::events::room::create::PreviousRoom::new( let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
body.room_id.clone(), body.room_id.clone(),
(*tombstone_event_id).to_owned(), Some(tombstone_event_id),
)); ));
// Send a m.room.create event containing a predecessor field and the applicable // Send a m.room.create event containing a predecessor field and the applicable

View file

@ -229,6 +229,9 @@ async fn allowed_to_send_state_event(
if acl_content.deny.contains(&String::from("*")) if acl_content.deny.contains(&String::from("*"))
&& !acl_content.is_allowed(services.globals.server_name()) && !acl_content.is_allowed(services.globals.server_name())
&& !acl_content
.allow
.contains(&services.globals.server_name().to_string())
{ {
return Err!(Request(BadJson(debug_warn!( return Err!(Request(BadJson(debug_warn!(
?room_id, ?room_id,
@ -240,6 +243,9 @@ async fn allowed_to_send_state_event(
if !acl_content.allow.contains(&String::from("*")) if !acl_content.allow.contains(&String::from("*"))
&& !acl_content.is_allowed(services.globals.server_name()) && !acl_content.is_allowed(services.globals.server_name())
&& !acl_content
.allow
.contains(&services.globals.server_name().to_string())
{ {
return Err!(Request(BadJson(debug_warn!( return Err!(Request(BadJson(debug_warn!(
?room_id, ?room_id,

View file

@ -15,6 +15,7 @@ use conduwuit::{
math::ruma_from_u64, math::ruma_from_u64,
stream::{BroadbandExt, Tools, TryExpect, WidebandExt}, stream::{BroadbandExt, Tools, TryExpect, WidebandExt},
}, },
warn,
}; };
use conduwuit_service::{ use conduwuit_service::{
Services, Services,
@ -428,9 +429,12 @@ async fn handle_left_room(
return Ok(None); return Ok(None);
} }
if !services.rooms.metadata.exists(room_id).await { if !services.rooms.metadata.exists(room_id).await
|| services.rooms.metadata.is_disabled(room_id).await
|| services.rooms.metadata.is_banned(room_id).await
{
// This is just a rejected invite, not a room we know // This is just a rejected invite, not a room we know
// Insert a leave event anyways // Insert a leave event anyways for the client
let event = PduEvent { let event = PduEvent {
event_id: EventId::new(services.globals.server_name()), event_id: EventId::new(services.globals.server_name()),
sender: sender_user.to_owned(), sender: sender_user.to_owned(),
@ -489,7 +493,7 @@ async fn handle_left_room(
.room_state_get_id(room_id, &StateEventType::RoomMember, sender_user.as_str()) .room_state_get_id(room_id, &StateEventType::RoomMember, sender_user.as_str())
.await .await
else { else {
error!("Left room but no left state event"); warn!("Left {room_id} but no left state event");
return Ok(None); return Ok(None);
}; };
@ -499,7 +503,7 @@ async fn handle_left_room(
.pdu_shortstatehash(&left_event_id) .pdu_shortstatehash(&left_event_id)
.await .await
else { else {
error!(event_id = %left_event_id, "Leave event has no state"); warn!(event_id = %left_event_id, "Leave event has no state in {room_id}");
return Ok(None); return Ok(None);
}; };

View file

@ -438,7 +438,10 @@ pub(crate) async fn sync_events_v4_route(
let mut known_subscription_rooms = BTreeSet::new(); let mut known_subscription_rooms = BTreeSet::new();
for (room_id, room) in &body.room_subscriptions { for (room_id, room) in &body.room_subscriptions {
if !services.rooms.metadata.exists(room_id).await { if !services.rooms.metadata.exists(room_id).await
|| services.rooms.metadata.is_disabled(room_id).await
|| services.rooms.metadata.is_banned(room_id).await
{
continue; continue;
} }
let todo_room = let todo_room =

View file

@ -214,7 +214,10 @@ async fn fetch_subscriptions(
) { ) {
let mut known_subscription_rooms = BTreeSet::new(); let mut known_subscription_rooms = BTreeSet::new();
for (room_id, room) in &body.room_subscriptions { for (room_id, room) in &body.room_subscriptions {
if !services.rooms.metadata.exists(room_id).await { if !services.rooms.metadata.exists(room_id).await
|| services.rooms.metadata.is_disabled(room_id).await
|| services.rooms.metadata.is_banned(room_id).await
{
continue; continue;
} }
let todo_room = let todo_room =

View file

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp; use axum_client_ip::InsecureClientIp;
use conduwuit::Err; use conduwuit::{Err, Error, Result};
use futures::StreamExt; use futures::StreamExt;
use ruma::{ use ruma::{
OwnedRoomId, OwnedRoomId,
@ -14,16 +14,14 @@ use ruma::{
delete_profile_key, delete_timezone_key, get_profile_key, get_timezone_key, delete_profile_key, delete_timezone_key, get_profile_key, get_timezone_key,
set_profile_key, set_timezone_key, set_profile_key, set_timezone_key,
}, },
room::get_summary,
}, },
federation, federation,
}, },
events::room::member::MembershipState,
presence::PresenceState, presence::PresenceState,
}; };
use super::{update_avatar_url, update_displayname}; use super::{update_avatar_url, update_displayname};
use crate::{Error, Result, Ruma, RumaResponse}; use crate::Ruma;
/// # `GET /_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms` /// # `GET /_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms`
/// ///
@ -38,13 +36,10 @@ pub(crate) async fn get_mutual_rooms_route(
InsecureClientIp(client): InsecureClientIp, InsecureClientIp(client): InsecureClientIp,
body: Ruma<mutual_rooms::unstable::Request>, body: Ruma<mutual_rooms::unstable::Request>,
) -> Result<mutual_rooms::unstable::Response> { ) -> Result<mutual_rooms::unstable::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user();
if sender_user == &body.user_id { if sender_user == body.user_id {
return Err(Error::BadRequest( return Err!(Request(Unknown("You cannot request rooms in common with yourself.")));
ErrorKind::Unknown,
"You cannot request rooms in common with yourself.",
));
} }
if !services.users.exists(&body.user_id).await { if !services.users.exists(&body.user_id).await {
@ -65,129 +60,6 @@ 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<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_summary::msc3266::Request>,
) -> Result<RumaResponse<get_summary::msc3266::Response>> {
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<crate::State>,
InsecureClientIp(client): InsecureClientIp,
body: Ruma<get_summary::msc3266::Request>,
) -> Result<get_summary::msc3266::Response> {
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` /// # `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. /// Deletes the `tz` (timezone) of a user, as per MSC4133 and MSC4175.

View file

@ -6,11 +6,17 @@ use conduwuit::{
utils::{IterStream, ReadyExt, stream::TryTools}, utils::{IterStream, ReadyExt, stream::TryTools},
}; };
use futures::{FutureExt, StreamExt, TryStreamExt}; use futures::{FutureExt, StreamExt, TryStreamExt};
use ruma::{MilliSecondsSinceUnixEpoch, api::federation::backfill::get_backfill, uint}; use ruma::{MilliSecondsSinceUnixEpoch, api::federation::backfill::get_backfill};
use super::AccessCheck; use super::AccessCheck;
use crate::Ruma; 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/<room_id>` /// # `GET /_matrix/federation/v1/backfill/<room_id>`
/// ///
/// Retrieves events from before the sender joined the room, if the room's /// Retrieves events from before the sender joined the room, if the room's
@ -30,9 +36,9 @@ pub(crate) async fn get_backfill_route(
let limit = body let limit = body
.limit .limit
.min(uint!(100))
.try_into() .try_into()
.expect("UInt could not be converted to usize"); .unwrap_or(LIMIT_DEFAULT)
.min(LIMIT_MAX);
let from = body let from = body
.v .v

View file

@ -1,13 +1,15 @@
use axum::extract::State; use axum::extract::State;
use conduwuit::{Error, Result}; use conduwuit::{Result, debug, debug_error, utils::to_canonical_object};
use ruma::{ use ruma::api::federation::event::get_missing_events;
CanonicalJsonValue, EventId, RoomId,
api::{client::error::ErrorKind, federation::event::get_missing_events},
};
use super::AccessCheck; use super::AccessCheck;
use crate::Ruma; 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}` /// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
/// ///
/// Retrieves events that the sender is missing. /// Retrieves events that the sender is missing.
@ -24,7 +26,11 @@ pub(crate) async fn get_missing_events_route(
.check() .check()
.await?; .await?;
let limit = body.limit.try_into()?; let limit = body
.limit
.try_into()
.unwrap_or(LIMIT_DEFAULT)
.min(LIMIT_MAX);
let mut queued_events = body.latest_events.clone(); let mut queued_events = body.latest_events.clone();
// the vec will never have more entries the limit // the vec will never have more entries the limit
@ -32,60 +38,52 @@ pub(crate) async fn get_missing_events_route(
let mut i: usize = 0; let mut i: usize = 0;
while i < queued_events.len() && events.len() < limit { while i < queued_events.len() && events.len() < limit {
if let Ok(pdu) = services 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
.rooms .rooms
.timeline .state_accessor
.get_pdu_json(&queued_events[i]) .server_can_see_event(body.origin(), &body.room_id, &queued_events[i])
.await .await
{ {
let room_id_str = pdu debug!(
.get("room_id") ?body.origin,
.and_then(|val| val.as_str()) "Server cannot see {:?} in {:?}, skipping", pdu.event_id, pdu.room_id
.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;
} }
i = i.saturating_add(1);
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);
} }
Ok(get_missing_events::v1::Response { events }) Ok(get_missing_events::v1::Response { events })

View file

@ -252,14 +252,6 @@ pub struct Config {
#[serde(default = "default_servernameevent_data_cache_capacity")] #[serde(default = "default_servernameevent_data_cache_capacity")]
pub servernameevent_data_cache_capacity: u32, 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 /// default: varies by system
#[serde(default = "default_stateinfo_cache_capacity")] #[serde(default = "default_stateinfo_cache_capacity")]
pub stateinfo_cache_capacity: u32, pub stateinfo_cache_capacity: u32,
@ -2035,10 +2027,6 @@ fn default_servernameevent_data_cache_capacity() -> u32 {
parallelism_scaled_u32(100_000).saturating_add(500_000) 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_stateinfo_cache_capacity() -> u32 { parallelism_scaled_u32(100) }
fn default_roomid_spacehierarchy_cache_capacity() -> u32 { parallelism_scaled_u32(1000) } fn default_roomid_spacehierarchy_cache_capacity() -> u32 { parallelism_scaled_u32(1000) }

View file

@ -69,10 +69,6 @@ impl Server {
return Err!("Reloading not enabled"); 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) { if self.reloading.swap(true, Ordering::AcqRel) {
return Err!("Reloading already in progress"); return Err!("Reloading already in progress");
} }
@ -98,10 +94,6 @@ impl Server {
} }
pub fn shutdown(&self) -> Result { 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) { if self.stopping.swap(true, Ordering::AcqRel) {
return Err!("Shutdown already in progress"); return Err!("Shutdown already in progress");
} }
@ -144,7 +136,16 @@ impl Server {
} }
#[inline] #[inline]
pub fn running(&self) -> bool { !self.stopping.load(Ordering::Acquire) } 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) }
#[inline] #[inline]
pub fn is_ours(&self, name: &str) -> bool { name == self.config.server_name } pub fn is_ours(&self, name: &str) -> bool { name == self.config.server_name }

View file

@ -12,7 +12,7 @@ use std::{
use async_channel::{QueueStrategy, Receiver, RecvError, Sender}; use async_channel::{QueueStrategy, Receiver, RecvError, Sender};
use conduwuit::{ use conduwuit::{
Error, Result, Server, debug, debug_warn, err, error, implement, Error, Result, Server, debug, err, error, implement,
result::DebugInspect, result::DebugInspect,
smallvec::SmallVec, smallvec::SmallVec,
trace, trace,
@ -245,13 +245,6 @@ async fn execute(&self, queue: &Sender<Cmd>, cmd: Cmd) -> Result {
self.queued_max.fetch_max(queue.len(), Ordering::Relaxed); self.queued_max.fetch_max(queue.len(), Ordering::Relaxed);
} }
if queue.is_full() {
debug_warn!(
capacity = ?queue.capacity(),
"pool queue is full"
);
}
queue queue
.send(cmd) .send(cmd)
.await .await

View file

@ -16,15 +16,14 @@ use server::Server;
rustc_flags_capture! {} rustc_flags_capture! {}
fn main() -> Result<(), Error> { fn main() -> Result {
let args = clap::parse(); let args = clap::parse();
let runtime = runtime::new(&args)?; let runtime = runtime::new(&args)?;
let server = Server::new(&args, Some(runtime.handle()))?; let server = Server::new(&args, Some(runtime.handle()))?;
runtime.spawn(signal::signal(server.clone())); runtime.spawn(signal::signal(server.clone()));
runtime.block_on(async_main(&server))?; runtime.block_on(async_main(&server))?;
runtime::shutdown(&server, runtime);
// explicit drop here to trace thread and tls dtors
drop(runtime);
#[cfg(unix)] #[cfg(unix)]
if server.server.restarting.load(Ordering::Acquire) { if server.server.restarting.load(Ordering::Acquire) {

View file

@ -1,7 +1,7 @@
use std::{ use std::{
iter::once, iter::once,
sync::{ sync::{
OnceLock, Arc, OnceLock,
atomic::{AtomicUsize, Ordering}, atomic::{AtomicUsize, Ordering},
}, },
thread, thread,
@ -11,17 +11,18 @@ use std::{
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] #[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
use conduwuit_core::result::LogDebugErr; use conduwuit_core::result::LogDebugErr;
use conduwuit_core::{ use conduwuit_core::{
Result, is_true, Result, debug, is_true,
utils::sys::compute::{nth_core_available, set_affinity}, utils::sys::compute::{nth_core_available, set_affinity},
}; };
use tokio::runtime::Builder; use tokio::runtime::Builder;
use crate::clap::Args; use crate::{clap::Args, server::Server};
const WORKER_NAME: &str = "conduwuit:worker"; const WORKER_NAME: &str = "conduwuit:worker";
const WORKER_MIN: usize = 2; const WORKER_MIN: usize = 2;
const WORKER_KEEPALIVE: u64 = 36; const WORKER_KEEPALIVE: u64 = 36;
const MAX_BLOCKING_THREADS: usize = 1024; const MAX_BLOCKING_THREADS: usize = 1024;
const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(10000);
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))] #[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
const DISABLE_MUZZY_THRESHOLD: usize = 4; const DISABLE_MUZZY_THRESHOLD: usize = 4;
@ -83,6 +84,42 @@ fn enable_histogram(builder: &mut Builder, args: &Args) {
.metrics_poll_time_histogram_configuration(linear); .metrics_poll_time_histogram_configuration(linear);
} }
#[cfg(tokio_unstable)]
#[tracing::instrument(name = "stop", level = "info", skip_all)]
pub(super) fn shutdown(server: &Arc<Server>, 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<Server>, runtime: tokio::runtime::Runtime) {
debug!(
timeout = ?SHUTDOWN_TIMEOUT,
"Waiting for runtime..."
);
runtime.shutdown_timeout(SHUTDOWN_TIMEOUT);
}
#[tracing::instrument( #[tracing::instrument(
name = "fork", name = "fork",
level = "debug", level = "debug",

View file

@ -77,6 +77,10 @@ pub(crate) async fn start(server: Arc<Server>) -> Result<Arc<Services>> {
pub(crate) async fn stop(services: Arc<Services>) -> Result<()> { pub(crate) async fn stop(services: Arc<Services>) -> Result<()> {
debug!("Shutting down..."); 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 // Wait for all completions before dropping or we'll lose them to the module
// unload and explode. // unload and explode.
services.stop().await; services.stop().await;

View file

@ -56,7 +56,7 @@ impl crate::Service for Service {
.build()?, .build()?,
well_known: base(config)? well_known: base(config)?
.dns_resolver(resolver.resolver.hooked.clone()) .dns_resolver(resolver.resolver.clone())
.connect_timeout(Duration::from_secs(config.well_known_conn_timeout)) .connect_timeout(Duration::from_secs(config.well_known_conn_timeout))
.read_timeout(Duration::from_secs(config.well_known_timeout)) .read_timeout(Duration::from_secs(config.well_known_timeout))
.timeout(Duration::from_secs(config.well_known_timeout)) .timeout(Duration::from_secs(config.well_known_timeout))

View file

@ -5,7 +5,7 @@ use std::{
use conduwuit::{Err, Result, debug, debug_info, err, error, trace}; use conduwuit::{Err, Result, debug, debug_info, err, error, trace};
use futures::{FutureExt, TryFutureExt}; use futures::{FutureExt, TryFutureExt};
use hickory_resolver::error::ResolveError; use hickory_resolver::ResolveError;
use ipaddress::IPAddress; use ipaddress::IPAddress;
use ruma::ServerName; use ruma::ServerName;
@ -334,25 +334,28 @@ impl super::Service {
} }
fn handle_resolve_error(e: &ResolveError, host: &'_ str) -> Result<()> { fn handle_resolve_error(e: &ResolveError, host: &'_ str) -> Result<()> {
use hickory_resolver::error::ResolveErrorKind; use hickory_resolver::{ResolveErrorKind::Proto, proto::ProtoErrorKind};
match *e.kind() { match e.kind() {
| ResolveErrorKind::NoRecordsFound { .. } => { | Proto(e) => match e.kind() {
// Raise to debug_warn if we can find out the result wasn't from cache | ProtoErrorKind::NoRecordsFound { .. } => {
debug!(%host, "No DNS records found: {e}"); // Raise to debug_warn if we can find out the result wasn't from cache
Ok(()) debug!(%host, "No DNS records found: {e}");
}, Ok(())
| ResolveErrorKind::Timeout => { },
Err!(warn!(%host, "DNS {e}")) | ProtoErrorKind::Timeout => {
}, Err!(warn!(%host, "DNS {e}"))
| ResolveErrorKind::NoConnections => { },
error!( | ProtoErrorKind::NoConnections => {
"Your DNS server is overloaded and has ran out of connections. It is \ error!(
strongly recommended you remediate this issue to ensure proper federation \ "Your DNS server is overloaded and has ran out of connections. It is \
connectivity." 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}")), | _ => Err!(error!(%host, "DNS error: {e}")),
} }

View file

@ -2,19 +2,19 @@ use std::{net::SocketAddr, sync::Arc, time::Duration};
use conduwuit::{Result, Server, err}; use conduwuit::{Result, Server, err};
use futures::FutureExt; use futures::FutureExt;
use hickory_resolver::{TokioAsyncResolver, lookup_ip::LookupIp}; use hickory_resolver::{TokioResolver, lookup_ip::LookupIp};
use reqwest::dns::{Addrs, Name, Resolve, Resolving}; use reqwest::dns::{Addrs, Name, Resolve, Resolving};
use super::cache::{Cache, CachedOverride}; use super::cache::{Cache, CachedOverride};
pub struct Resolver { pub struct Resolver {
pub(crate) resolver: Arc<TokioAsyncResolver>, pub(crate) resolver: Arc<TokioResolver>,
pub(crate) hooked: Arc<Hooked>, pub(crate) hooked: Arc<Hooked>,
server: Arc<Server>, server: Arc<Server>,
} }
pub(crate) struct Hooked { pub(crate) struct Hooked {
resolver: Arc<TokioAsyncResolver>, resolver: Arc<TokioResolver>,
cache: Arc<Cache>, cache: Arc<Cache>,
server: Arc<Server>, server: Arc<Server>,
} }
@ -42,7 +42,7 @@ impl Resolver {
let mut ns = sys_conf.clone(); let mut ns = sys_conf.clone();
if config.query_over_tcp_only { if config.query_over_tcp_only {
ns.protocol = hickory_resolver::config::Protocol::Tcp; ns.protocol = hickory_resolver::proto::xfer::Protocol::Tcp;
} }
ns.trust_negative_responses = !config.query_all_nameservers; ns.trust_negative_responses = !config.query_all_nameservers;
@ -51,6 +51,7 @@ impl Resolver {
} }
opts.cache_size = config.dns_cache_entries as usize; 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_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain));
opts.negative_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 30)); opts.negative_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 30));
opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl)); opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl));
@ -60,8 +61,7 @@ impl Resolver {
opts.try_tcp_on_error = config.dns_tcp_fallback; opts.try_tcp_on_error = config.dns_tcp_fallback;
opts.num_concurrent_reqs = 1; opts.num_concurrent_reqs = 1;
opts.edns0 = true; opts.edns0 = true;
opts.shuffle_dns_servers = true; opts.case_randomization = true;
opts.rotate = true;
opts.ip_strategy = match config.ip_lookup_strategy { opts.ip_strategy = match config.ip_lookup_strategy {
| 1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only, | 1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only,
| 2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only, | 2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only,
@ -69,9 +69,13 @@ impl Resolver {
| 4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4, | 4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4,
| _ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6, | _ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6,
}; };
opts.authentic_data = false;
let resolver = Arc::new(TokioAsyncResolver::tokio(conf, opts)); 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());
Ok(Arc::new(Self { Ok(Arc::new(Self {
resolver: resolver.clone(), resolver: resolver.clone(),
hooked: Arc::new(Hooked { resolver, cache, server: server.clone() }), hooked: Arc::new(Hooked { resolver, cache, server: server.clone() }),
@ -105,7 +109,7 @@ impl Resolve for Hooked {
async fn hooked_resolve( async fn hooked_resolve(
cache: Arc<Cache>, cache: Arc<Cache>,
server: Arc<Server>, server: Arc<Server>,
resolver: Arc<TokioAsyncResolver>, resolver: Arc<TokioResolver>,
name: Name, name: Name,
) -> Result<Addrs, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<Addrs, Box<dyn std::error::Error + Send + Sync>> {
match cache.get_override(name.as_str()).await { match cache.get_override(name.as_str()).await {
@ -129,7 +133,7 @@ async fn hooked_resolve(
async fn resolve_to_reqwest( async fn resolve_to_reqwest(
server: Arc<Server>, server: Arc<Server>,
resolver: Arc<TokioAsyncResolver>, resolver: Arc<TokioResolver>,
name: Name, name: Name,
) -> ResolvingResult { ) -> ResolvingResult {
use std::{io, io::ErrorKind::Interrupted}; use std::{io, io::ErrorKind::Interrupted};

View file

@ -1,6 +1,5 @@
use std::{ use std::{
collections::{BTreeMap, HashSet, VecDeque, hash_map}, collections::{BTreeMap, HashSet, VecDeque, hash_map},
sync::Arc,
time::Instant, time::Instant,
}; };
@ -8,7 +7,6 @@ use conduwuit::{
PduEvent, debug, debug_error, debug_warn, implement, pdu, trace, PduEvent, debug, debug_error, debug_warn, implement, pdu, trace,
utils::continue_exponential_backoff_secs, warn, utils::continue_exponential_backoff_secs, warn,
}; };
use futures::TryFutureExt;
use ruma::{ use ruma::{
CanonicalJsonValue, OwnedEventId, RoomId, ServerName, api::federation::event::get_event, CanonicalJsonValue, OwnedEventId, RoomId, ServerName, api::federation::event::get_event,
}; };
@ -31,7 +29,7 @@ pub(super) async fn fetch_and_handle_outliers<'a>(
events: &'a [OwnedEventId], events: &'a [OwnedEventId],
create_event: &'a PduEvent, create_event: &'a PduEvent,
room_id: &'a RoomId, room_id: &'a RoomId,
) -> Vec<(Arc<PduEvent>, Option<BTreeMap<String, CanonicalJsonValue>>)> { ) -> Vec<(PduEvent, Option<BTreeMap<String, CanonicalJsonValue>>)> {
let back_off = |id| match self let back_off = |id| match self
.services .services
.globals .globals
@ -53,7 +51,7 @@ pub(super) async fn fetch_and_handle_outliers<'a>(
// a. Look in the main timeline (pduid_pdu tree) // a. Look in the main timeline (pduid_pdu tree)
// b. Look at outlier pdu tree // b. Look at outlier pdu tree
// (get_pdu_json checks both) // (get_pdu_json checks both)
if let Ok(local_pdu) = self.services.timeline.get_pdu(id).map_ok(Arc::new).await { if let Ok(local_pdu) = self.services.timeline.get_pdu(id).await {
trace!("Found {id} in db"); trace!("Found {id} in db");
events_with_auth_events.push((id, Some(local_pdu), vec![])); events_with_auth_events.push((id, Some(local_pdu), vec![]));
continue; continue;

View file

@ -1,7 +1,4 @@
use std::{ use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
collections::{BTreeMap, HashMap, HashSet, VecDeque},
sync::Arc,
};
use conduwuit::{ use conduwuit::{
PduEvent, Result, debug_warn, err, implement, PduEvent, Result, debug_warn, err, implement,
@ -31,7 +28,7 @@ pub(super) async fn fetch_prev(
initial_set: Vec<OwnedEventId>, initial_set: Vec<OwnedEventId>,
) -> Result<( ) -> Result<(
Vec<OwnedEventId>, Vec<OwnedEventId>,
HashMap<OwnedEventId, (Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>, HashMap<OwnedEventId, (PduEvent, BTreeMap<String, CanonicalJsonValue>)>,
)> { )> {
let mut graph: HashMap<OwnedEventId, _> = HashMap::with_capacity(initial_set.len()); let mut graph: HashMap<OwnedEventId, _> = HashMap::with_capacity(initial_set.len());
let mut eventid_info = HashMap::new(); let mut eventid_info = HashMap::new();

View file

@ -3,9 +3,12 @@ use std::{
time::Instant, time::Instant,
}; };
use conduwuit::{Err, Result, debug, debug::INFO_SPAN_LEVEL, err, implement, warn}; use conduwuit::{
Err, Result, debug, debug::INFO_SPAN_LEVEL, defer, err, implement, utils::stream::IterStream,
warn,
};
use futures::{ use futures::{
FutureExt, FutureExt, TryFutureExt, TryStreamExt,
future::{OptionFuture, try_join5}, future::{OptionFuture, try_join5},
}; };
use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UserId, events::StateEventType}; use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UserId, events::StateEventType};
@ -86,7 +89,7 @@ pub async fn handle_incoming_pdu<'a>(
.state_accessor .state_accessor
.room_state_get(room_id, &StateEventType::RoomCreate, ""); .room_state_get(room_id, &StateEventType::RoomCreate, "");
let (meta_exists, is_disabled, (), (), create_event) = try_join5( let (meta_exists, is_disabled, (), (), ref create_event) = try_join5(
meta_exists, meta_exists,
is_disabled, is_disabled,
origin_acl_check, origin_acl_check,
@ -104,7 +107,7 @@ pub async fn handle_incoming_pdu<'a>(
} }
let (incoming_pdu, val) = self 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?; .await?;
// 8. if not timeline event: stop // 8. if not timeline event: stop
@ -129,66 +132,71 @@ pub async fn handle_incoming_pdu<'a>(
let (sorted_prev_events, mut eventid_info) = self let (sorted_prev_events, mut eventid_info) = self
.fetch_prev( .fetch_prev(
origin, origin,
&create_event, create_event,
room_id, room_id,
first_ts_in_room, first_ts_in_room,
incoming_pdu.prev_events.clone(), incoming_pdu.prev_events.clone(),
) )
.await?; .await?;
debug!(events = ?sorted_prev_events, "Got previous events"); debug!(
for prev_id in sorted_prev_events { events = ?sorted_prev_events,
self.services.server.check_running()?; "Handling previous events"
if let Err(e) = self );
.handle_prev_pdu(
sorted_prev_events
.iter()
.try_stream()
.map_ok(AsRef::as_ref)
.try_for_each(|prev_id| {
self.handle_prev_pdu(
origin, origin,
event_id, event_id,
room_id, room_id,
&mut eventid_info, eventid_info.remove(prev_id),
&create_event, create_event,
first_ts_in_room, first_ts_in_room,
&prev_id, prev_id,
) )
.await .inspect_err(move |e| {
{ warn!("Prev {prev_id} failed: {e}");
use hash_map::Entry; match self
.services
let now = Instant::now(); .globals
warn!("Prev event {prev_id} failed: {e}"); .bad_event_ratelimiter
.write()
match self .expect("locked")
.services .entry(prev_id.into())
.globals {
.bad_event_ratelimiter | hash_map::Entry::Vacant(e) => {
.write() e.insert((Instant::now(), 1));
.expect("locked") },
.entry(prev_id) | hash_map::Entry::Occupied(mut e) => {
{ let tries = e.get().1.saturating_add(1);
| Entry::Vacant(e) => { *e.get_mut() = (Instant::now(), tries);
e.insert((now, 1)); },
}, }
| Entry::Occupied(mut e) => { })
*e.get_mut() = (now, e.get().1.saturating_add(1)); .map(|_| self.services.server.check_running())
}, })
} .boxed()
} .await?;
}
// Done with prev events, now handling the incoming event // Done with prev events, now handling the incoming event
let start_time = Instant::now(); let start_time = Instant::now();
self.federation_handletime self.federation_handletime
.write() .write()
.expect("locked") .expect("locked")
.insert(room_id.to_owned(), (event_id.to_owned(), start_time)); .insert(room_id.into(), (event_id.to_owned(), start_time));
let r = self defer! {{
.upgrade_outlier_to_timeline_pdu(incoming_pdu, val, &create_event, origin, room_id) self.federation_handletime
.await; .write()
.expect("locked")
.remove(room_id);
}};
self.federation_handletime self.upgrade_outlier_to_timeline_pdu(incoming_pdu, val, create_event, origin, room_id)
.write() .boxed()
.expect("locked") .await
.remove(&room_id.to_owned());
r
} }

View file

@ -1,12 +1,9 @@
use std::{ use std::collections::{BTreeMap, HashMap, hash_map};
collections::{BTreeMap, HashMap, hash_map},
sync::Arc,
};
use conduwuit::{ use conduwuit::{
Err, Error, PduEvent, Result, debug, debug_info, err, implement, state_res, trace, warn, Err, Error, PduEvent, Result, debug, debug_info, err, implement, state_res, trace, warn,
}; };
use futures::{TryFutureExt, future::ready}; use futures::future::ready;
use ruma::{ use ruma::{
CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, ServerName, CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, ServerName,
api::client::error::ErrorKind, events::StateEventType, api::client::error::ErrorKind, events::StateEventType,
@ -24,7 +21,7 @@ pub(super) async fn handle_outlier_pdu<'a>(
room_id: &'a RoomId, room_id: &'a RoomId,
mut value: CanonicalJsonObject, mut value: CanonicalJsonObject,
auth_events_known: bool, auth_events_known: bool,
) -> Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)> { ) -> Result<(PduEvent, BTreeMap<String, CanonicalJsonValue>)> {
// 1. Remove unsigned field // 1. Remove unsigned field
value.remove("unsigned"); value.remove("unsigned");
@ -95,7 +92,7 @@ pub(super) async fn handle_outlier_pdu<'a>(
// Build map of auth events // Build map of auth events
let mut auth_events = HashMap::with_capacity(incoming_pdu.auth_events.len()); let mut auth_events = HashMap::with_capacity(incoming_pdu.auth_events.len());
for id in &incoming_pdu.auth_events { for id in &incoming_pdu.auth_events {
let Ok(auth_event) = self.services.timeline.get_pdu(id).map_ok(Arc::new).await else { let Ok(auth_event) = self.services.timeline.get_pdu(id).await else {
warn!("Could not find auth event {id}"); warn!("Could not find auth event {id}");
continue; continue;
}; };
@ -123,15 +120,10 @@ pub(super) async fn handle_outlier_pdu<'a>(
// The original create event must be in the auth events // The original create event must be in the auth events
if !matches!( if !matches!(
auth_events auth_events.get(&(StateEventType::RoomCreate, String::new().into())),
.get(&(StateEventType::RoomCreate, String::new().into()))
.map(AsRef::as_ref),
Some(_) | None Some(_) | None
) { ) {
return Err(Error::BadRequest( return Err!(Request(InvalidParam("Incoming event refers to wrong create event.")));
ErrorKind::InvalidParam,
"Incoming event refers to wrong create event.",
));
} }
let state_fetch = |ty: &StateEventType, sk: &str| { let state_fetch = |ty: &StateEventType, sk: &str| {
@ -161,5 +153,5 @@ pub(super) async fn handle_outlier_pdu<'a>(
trace!("Added pdu as outlier."); trace!("Added pdu as outlier.");
Ok((Arc::new(incoming_pdu), val)) Ok((incoming_pdu, val))
} }

View file

@ -1,14 +1,10 @@
use std::{ use std::{collections::BTreeMap, time::Instant};
collections::{BTreeMap, HashMap},
sync::Arc,
time::Instant,
};
use conduwuit::{ use conduwuit::{
Err, PduEvent, Result, debug, debug::INFO_SPAN_LEVEL, implement, Err, PduEvent, Result, debug, debug::INFO_SPAN_LEVEL, defer, implement,
utils::continue_exponential_backoff_secs, utils::continue_exponential_backoff_secs,
}; };
use ruma::{CanonicalJsonValue, EventId, OwnedEventId, RoomId, ServerName, UInt}; use ruma::{CanonicalJsonValue, EventId, RoomId, ServerName, UInt};
#[implement(super::Service)] #[implement(super::Service)]
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
@ -24,13 +20,10 @@ pub(super) async fn handle_prev_pdu<'a>(
origin: &'a ServerName, origin: &'a ServerName,
event_id: &'a EventId, event_id: &'a EventId,
room_id: &'a RoomId, room_id: &'a RoomId,
eventid_info: &mut HashMap< eventid_info: Option<(PduEvent, BTreeMap<String, CanonicalJsonValue>)>,
OwnedEventId, create_event: &'a PduEvent,
(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>),
>,
create_event: &PduEvent,
first_ts_in_room: UInt, first_ts_in_room: UInt,
prev_id: &EventId, prev_id: &'a EventId,
) -> Result { ) -> Result {
// Check for disabled again because it might have changed // Check for disabled again because it might have changed
if self.services.metadata.is_disabled(room_id).await { if self.services.metadata.is_disabled(room_id).await {
@ -61,31 +54,35 @@ pub(super) async fn handle_prev_pdu<'a>(
} }
} }
if let Some((pdu, json)) = eventid_info.remove(prev_id) { let Some((pdu, json)) = eventid_info else {
// Skip old events return Ok(());
if pdu.origin_server_ts < first_ts_in_room { };
return Ok(());
}
let start_time = Instant::now(); // Skip old events
self.federation_handletime if pdu.origin_server_ts < first_ts_in_room {
.write() return Ok(());
.expect("locked")
.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.federation_handletime
.write()
.expect("locked")
.remove(&room_id.to_owned());
debug!(
elapsed = ?start_time.elapsed(),
"Handled prev_event",
);
} }
let start_time = Instant::now();
self.federation_handletime
.write()
.expect("locked")
.insert(room_id.into(), ((*prev_id).to_owned(), start_time));
defer! {{
self.federation_handletime
.write()
.expect("locked")
.remove(room_id);
}};
self.upgrade_outlier_to_timeline_pdu(pdu, json, create_event, origin, room_id)
.await?;
debug!(
elapsed = ?start_time.elapsed(),
"Handled prev_event",
);
Ok(()) Ok(())
} }

View file

@ -2,7 +2,6 @@ use std::{
borrow::Borrow, borrow::Borrow,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
iter::Iterator, iter::Iterator,
sync::Arc,
}; };
use conduwuit::{ use conduwuit::{
@ -20,7 +19,7 @@ use crate::rooms::short::ShortStateHash;
#[tracing::instrument(name = "state", level = "debug", skip_all)] #[tracing::instrument(name = "state", level = "debug", skip_all)]
pub(super) async fn state_at_incoming_degree_one( pub(super) async fn state_at_incoming_degree_one(
&self, &self,
incoming_pdu: &Arc<PduEvent>, incoming_pdu: &PduEvent,
) -> Result<Option<HashMap<u64, OwnedEventId>>> { ) -> Result<Option<HashMap<u64, OwnedEventId>>> {
let prev_event = &incoming_pdu.prev_events[0]; let prev_event = &incoming_pdu.prev_events[0];
let Ok(prev_event_sstatehash) = self let Ok(prev_event_sstatehash) = self
@ -67,7 +66,7 @@ pub(super) async fn state_at_incoming_degree_one(
#[tracing::instrument(name = "state", level = "debug", skip_all)] #[tracing::instrument(name = "state", level = "debug", skip_all)]
pub(super) async fn state_at_incoming_resolved( pub(super) async fn state_at_incoming_resolved(
&self, &self,
incoming_pdu: &Arc<PduEvent>, incoming_pdu: &PduEvent,
room_id: &RoomId, room_id: &RoomId,
room_version_id: &RoomVersionId, room_version_id: &RoomVersionId,
) -> Result<Option<HashMap<u64, OwnedEventId>>> { ) -> Result<Option<HashMap<u64, OwnedEventId>>> {

View file

@ -18,7 +18,7 @@ use crate::rooms::{
#[implement(super::Service)] #[implement(super::Service)]
pub(super) async fn upgrade_outlier_to_timeline_pdu( pub(super) async fn upgrade_outlier_to_timeline_pdu(
&self, &self,
incoming_pdu: Arc<PduEvent>, incoming_pdu: PduEvent,
val: BTreeMap<String, CanonicalJsonValue>, val: BTreeMap<String, CanonicalJsonValue>,
create_event: &PduEvent, create_event: &PduEvent,
origin: &ServerName, origin: &ServerName,

View file

@ -27,7 +27,6 @@ use ruma::{
}, },
events::{ events::{
StateEventType, StateEventType,
room::join_rules::{JoinRule, RoomJoinRulesEventContent},
space::child::{HierarchySpaceChildEvent, SpaceChildEventContent}, space::child::{HierarchySpaceChildEvent, SpaceChildEventContent},
}, },
serde::Raw, serde::Raw,
@ -306,25 +305,18 @@ async fn get_room_summary(
children_state: Vec<Raw<HierarchySpaceChildEvent>>, children_state: Vec<Raw<HierarchySpaceChildEvent>>,
identifier: &Identifier<'_>, identifier: &Identifier<'_>,
) -> Result<SpaceHierarchyParentSummary, Error> { ) -> Result<SpaceHierarchyParentSummary, Error> {
let join_rule = self let (join_rule, allowed_room_ids) = self
.services .services
.state_accessor .state_accessor
.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "") .get_space_join_rule(room_id)
.await .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 let is_accessible_child = self
.is_accessible_child(room_id, &join_rule, identifier, &allowed_room_ids) .is_accessible_child(room_id, &join_rule, identifier, &allowed_room_ids)
.await; .await;
if !is_accessible_child { 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(); let name = self.services.state_accessor.get_name(room_id).ok();
@ -355,6 +347,14 @@ async fn get_room_summary(
.get_avatar(room_id) .get_avatar(room_id)
.map(|res| res.into_option().unwrap_or_default().url); .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 ( let (
canonical_alias, canonical_alias,
name, name,
@ -364,6 +364,8 @@ async fn get_room_summary(
guest_can_join, guest_can_join,
avatar_url, avatar_url,
room_type, room_type,
room_version,
encryption,
) = futures::join!( ) = futures::join!(
canonical_alias, canonical_alias,
name, name,
@ -372,7 +374,9 @@ async fn get_room_summary(
world_readable, world_readable,
guest_can_join, guest_can_join,
avatar_url, avatar_url,
room_type room_type,
room_version,
encryption,
); );
Ok(SpaceHierarchyParentSummary { Ok(SpaceHierarchyParentSummary {
@ -387,9 +391,9 @@ async fn get_room_summary(
allowed_room_ids, allowed_room_ids,
join_rule, join_rule,
room_id: room_id.to_owned(), room_id: room_id.to_owned(),
num_joined_members: num_joined_members num_joined_members: num_joined_members.try_into().unwrap_or_default(),
.try_into() encryption,
.expect("user count should not be that big"), room_version,
}) })
} }
@ -487,6 +491,8 @@ async fn cache_insert(
join_rule, join_rule,
room_type, room_type,
allowed_room_ids, allowed_room_ids,
encryption,
room_version,
} = child; } = child;
let summary = SpaceHierarchyParentSummary { let summary = SpaceHierarchyParentSummary {
@ -506,6 +512,8 @@ async fn cache_insert(
.map(PduEvent::into_stripped_spacechild_state_event) .map(PduEvent::into_stripped_spacechild_state_event)
.collect() .collect()
.await, .await,
encryption,
room_version,
}; };
cache.insert(current_room.to_owned(), Some(CachedSpaceHierarchySummary { summary })); cache.insert(current_room.to_owned(), Some(CachedSpaceHierarchySummary { summary }));
@ -527,7 +535,9 @@ impl From<CachedSpaceHierarchySummary> for SpaceHierarchyRoomsChunk {
join_rule, join_rule,
room_type, room_type,
children_state, children_state,
.. allowed_room_ids,
encryption,
room_version,
} = value.summary; } = value.summary;
Self { Self {
@ -542,6 +552,9 @@ impl From<CachedSpaceHierarchySummary> for SpaceHierarchyRoomsChunk {
join_rule, join_rule,
room_type, room_type,
children_state, children_state,
encryption,
room_version,
allowed_room_ids,
} }
} }
} }
@ -562,7 +575,9 @@ pub fn summary_to_chunk(summary: SpaceHierarchyParentSummary) -> SpaceHierarchyR
join_rule, join_rule,
room_type, room_type,
children_state, children_state,
.. allowed_room_ids,
encryption,
room_version,
} = summary; } = summary;
SpaceHierarchyRoomsChunk { SpaceHierarchyRoomsChunk {
@ -577,5 +592,8 @@ pub fn summary_to_chunk(summary: SpaceHierarchyParentSummary) -> SpaceHierarchyR
join_rule, join_rule,
room_type, room_type,
children_state, children_state,
encryption,
room_version,
allowed_room_ids,
} }
} }

View file

@ -3,21 +3,13 @@ mod server_can;
mod state; mod state;
mod user_can; mod user_can;
use std::{ use std::sync::Arc;
fmt::Write,
sync::{Arc, Mutex as StdMutex, Mutex},
};
use async_trait::async_trait; use async_trait::async_trait;
use conduwuit::{ use conduwuit::{Result, err};
Result, err, utils,
utils::math::{Expected, usize_from_f64},
};
use database::Map; use database::Map;
use lru_cache::LruCache;
use ruma::{ use ruma::{
EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, OwnedRoomId, RoomId, UserId,
OwnedUserId, RoomId, UserId,
events::{ events::{
StateEventType, StateEventType,
room::{ room::{
@ -37,11 +29,9 @@ use ruma::{
space::SpaceRoomJoinRule, space::SpaceRoomJoinRule,
}; };
use crate::{Dep, rooms, rooms::short::ShortStateHash}; use crate::{Dep, rooms};
pub struct Service { pub struct Service {
pub server_visibility_cache: Mutex<LruCache<(OwnedServerName, ShortStateHash), bool>>,
pub user_visibility_cache: Mutex<LruCache<(OwnedUserId, ShortStateHash), bool>>,
services: Services, services: Services,
db: Data, db: Data,
} }
@ -61,19 +51,7 @@ struct Data {
#[async_trait] #[async_trait]
impl crate::Service for Service { impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> { fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
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 { 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 { services: Services {
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"), state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"), timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
@ -88,44 +66,6 @@ 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!()) } fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
} }
@ -189,22 +129,34 @@ impl Service {
.map(|c: RoomTopicEventContent| c.topic) .map(|c: RoomTopicEventContent| c.topic)
} }
/// Returns the join rule (`SpaceRoomJoinRule`) for a given room /// Returns the space join rule (`SpaceRoomJoinRule`) for a given room and
pub async fn get_join_rule( /// any allowed room IDs if available. Will default to Invite and empty vec
/// if doesnt exist or invalid,
pub async fn get_space_join_rule(
&self, &self,
room_id: &RoomId, room_id: &RoomId,
) -> Result<(SpaceRoomJoinRule, Vec<OwnedRoomId>)> { ) -> (SpaceRoomJoinRule, Vec<OwnedRoomId>) {
self.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "") self.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "")
.await .await
.map(|c: RoomJoinRulesEventContent| { .map_or_else(
(c.join_rule.clone().into(), self.allowed_room_ids(c.join_rule)) |_| (SpaceRoomJoinRule::Invite, vec![]),
}) |c: RoomJoinRulesEventContent| {
.or_else(|_| Ok((SpaceRoomJoinRule::Invite, vec![]))) (c.join_rule.clone().into(), self.allowed_room_ids(c.join_rule))
},
)
}
/// 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 {
self.room_state_get_content(room_id, &StateEventType::RoomJoinRules, "")
.await
.map_or_else(|_| JoinRule::Invite, |c: RoomJoinRulesEventContent| (c.join_rule))
} }
/// Returns an empty vec if not a restricted room /// Returns an empty vec if not a restricted room
pub fn allowed_room_ids(&self, join_rule: JoinRule) -> Vec<OwnedRoomId> { pub fn allowed_room_ids(&self, join_rule: JoinRule) -> Vec<OwnedRoomId> {
let mut room_ids = Vec::with_capacity(1); let mut room_ids = Vec::with_capacity(1); // restricted rooms generally only have 1 allowed room ID
if let JoinRule::Restricted(r) | JoinRule::KnockRestricted(r) = join_rule { if let JoinRule::Restricted(r) | JoinRule::KnockRestricted(r) = join_rule {
for rule in r.allow { for rule in r.allow {
if let AllowRule::RoomMembership(RoomMembership { room_id: membership }) = rule { if let AllowRule::RoomMembership(RoomMembership { room_id: membership }) = rule {

View file

@ -1,4 +1,4 @@
use conduwuit::{error, implement, utils::stream::ReadyExt}; use conduwuit::{implement, utils::stream::ReadyExt};
use futures::StreamExt; use futures::StreamExt;
use ruma::{ use ruma::{
EventId, RoomId, ServerName, EventId, RoomId, ServerName,
@ -22,15 +22,6 @@ pub async fn server_can_see_event(
return true; 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 let history_visibility = self
.state_get_content(shortstatehash, &StateEventType::RoomHistoryVisibility, "") .state_get_content(shortstatehash, &StateEventType::RoomHistoryVisibility, "")
.await .await
@ -44,8 +35,7 @@ pub async fn server_can_see_event(
.room_members(room_id) .room_members(room_id)
.ready_filter(|member| member.server_name() == origin); .ready_filter(|member| member.server_name() == origin);
let visibility = match history_visibility { match history_visibility {
| HistoryVisibility::WorldReadable | HistoryVisibility::Shared => true,
| HistoryVisibility::Invited => { | HistoryVisibility::Invited => {
// Allow if any member on requesting server was AT LEAST invited, else deny // Allow if any member on requesting server was AT LEAST invited, else deny
current_server_members current_server_members
@ -58,16 +48,6 @@ pub async fn server_can_see_event(
.any(|member| self.user_was_joined(shortstatehash, member)) .any(|member| self.user_was_joined(shortstatehash, member))
.await .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
} }

View file

@ -1,4 +1,4 @@
use conduwuit::{Err, Error, Result, error, implement, pdu::PduBuilder}; use conduwuit::{Err, Result, implement, pdu::PduBuilder};
use ruma::{ use ruma::{
EventId, RoomId, UserId, EventId, RoomId, UserId,
events::{ events::{
@ -76,8 +76,8 @@ pub async fn user_can_redact(
|| redacting_event || redacting_event
.as_ref() .as_ref()
.is_ok_and(|redacting_event| redacting_event.sender == sender)), .is_ok_and(|redacting_event| redacting_event.sender == sender)),
| _ => Err(Error::bad_database( | _ => Err!(Database(
"No m.room.power_levels or m.room.create events in database for room", "No m.room.power_levels or m.room.create events in database for room"
)), )),
} }
}, },
@ -98,15 +98,6 @@ pub async fn user_can_see_event(
return true; 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 currently_member = self.services.state_cache.is_joined(user_id, room_id).await;
let history_visibility = self let history_visibility = self
@ -116,9 +107,7 @@ pub async fn user_can_see_event(
c.history_visibility c.history_visibility
}); });
let visibility = match history_visibility { match history_visibility {
| HistoryVisibility::WorldReadable => true,
| HistoryVisibility::Shared => currently_member,
| HistoryVisibility::Invited => { | HistoryVisibility::Invited => {
// Allow if any member on requesting server was AT LEAST invited, else deny // Allow if any member on requesting server was AT LEAST invited, else deny
self.user_was_invited(shortstatehash, user_id).await self.user_was_invited(shortstatehash, user_id).await
@ -127,18 +116,9 @@ pub async fn user_can_see_event(
// Allow if any member on requested server was joined, else deny // Allow if any member on requested server was joined, else deny
self.user_was_joined(shortstatehash, user_id).await self.user_was_joined(shortstatehash, user_id).await
}, },
| _ => { | HistoryVisibility::WorldReadable => true,
error!("Unknown history visibility {history_visibility}"); | HistoryVisibility::Shared | _ => currently_member,
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 /// Whether a user is allowed to see an event, based on

View file

@ -40,6 +40,7 @@ struct Services {
account_data: Dep<account_data::Service>, account_data: Dep<account_data::Service>,
config: Dep<config::Service>, config: Dep<config::Service>,
globals: Dep<globals::Service>, globals: Dep<globals::Service>,
metadata: Dep<rooms::metadata::Service>,
state_accessor: Dep<rooms::state_accessor::Service>, state_accessor: Dep<rooms::state_accessor::Service>,
users: Dep<users::Service>, users: Dep<users::Service>,
} }
@ -73,6 +74,7 @@ impl crate::Service for Service {
account_data: args.depend::<account_data::Service>("account_data"), account_data: args.depend::<account_data::Service>("account_data"),
config: args.depend::<config::Service>("config"), config: args.depend::<config::Service>("config"),
globals: args.depend::<globals::Service>("globals"), globals: args.depend::<globals::Service>("globals"),
metadata: args.depend::<rooms::metadata::Service>("rooms::metadata"),
state_accessor: args state_accessor: args
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"), .depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
users: args.depend::<users::Service>("users"), users: args.depend::<users::Service>("users"),
@ -271,7 +273,9 @@ impl Service {
self.mark_as_left(user_id, room_id); self.mark_as_left(user_id, room_id);
if self.services.globals.user_is_local(user_id) if self.services.globals.user_is_local(user_id)
&& self.services.config.forget_forced_upon_leave && (self.services.config.forget_forced_upon_leave
|| self.services.metadata.is_banned(room_id).await
|| self.services.metadata.is_disabled(room_id).await)
{ {
self.forget(room_id, user_id); self.forget(room_id, user_id);
} }

View file

@ -25,6 +25,10 @@ where
return Ok(None); return Ok(None);
}; };
if dest == *"null" || dest.is_empty() {
return Ok(None);
}
trace!("Appservice URL \"{dest}\", Appservice ID: {}", registration.id); trace!("Appservice URL \"{dest}\", Appservice ID: {}", registration.id);
let hs_token = registration.hs_token.as_str(); let hs_token = registration.hs_token.as_str();
@ -34,7 +38,11 @@ where
SendAccessToken::IfRequired(hs_token), SendAccessToken::IfRequired(hs_token),
&VERSIONS, &VERSIONS,
) )
.map_err(|e| err!(BadServerResponse(warn!("Failed to find destination {dest}: {e}"))))? .map_err(|e| {
err!(BadServerResponse(
warn!(appservice = %registration.id, "Failed to find destination {dest}: {e:?}")
))
})?
.map(BytesMut::freeze); .map(BytesMut::freeze);
let mut parts = http_request.uri().clone().into_parts(); let mut parts = http_request.uri().clone().into_parts();
@ -51,7 +59,7 @@ where
let reqwest_request = reqwest::Request::try_from(http_request)?; let reqwest_request = reqwest::Request::try_from(http_request)?;
let mut response = client.execute(reqwest_request).await.map_err(|e| { 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 e
})?; })?;
@ -71,7 +79,7 @@ where
if !status.is_success() { if !status.is_success() {
debug_error!("Appservice response bytes: {:?}", utils::string_from_bytes(&body)); debug_error!("Appservice response bytes: {:?}", utils::string_from_bytes(&body));
return Err!(BadServerResponse(error!( return Err!(BadServerResponse(warn!(
"Appservice \"{}\" returned unsuccessful HTTP response {status} at {dest}", "Appservice \"{}\" returned unsuccessful HTTP response {status} at {dest}",
registration.id registration.id
))); )));
@ -84,8 +92,8 @@ where
); );
response.map(Some).map_err(|e| { response.map(Some).map_err(|e| {
err!(BadServerResponse(error!( err!(BadServerResponse(warn!(
"Appservice \"{}\" returned invalid response bytes {dest}: {e}", "Appservice \"{}\" returned invalid/malformed response bytes {dest}: {e}",
registration.id registration.id
))) )))
}) })

View file

@ -350,7 +350,6 @@ impl Service {
token: &str, token: &str,
) -> Result<()> { ) -> Result<()> {
let key = (user_id, device_id); 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() { if self.db.userdeviceid_metadata.qry(&key).await.is_err() {
return Err!(Database(error!( return Err!(Database(error!(
?user_id, ?user_id,
@ -594,7 +593,7 @@ impl Service {
key_id: &str, key_id: &str,
signature: (String, String), signature: (String, String),
sender_id: &UserId, sender_id: &UserId,
) -> Result<()> { ) -> Result {
let key = (target_id, key_id); let key = (target_id, key_id);
let mut cross_signing_key: serde_json::Value = self let mut cross_signing_key: serde_json::Value = self
@ -602,21 +601,27 @@ impl Service {
.keyid_key .keyid_key
.qry(&key) .qry(&key)
.await .await
.map_err(|_| err!(Request(InvalidParam("Tried to sign nonexistent key."))))? .map_err(|_| err!(Request(InvalidParam("Tried to sign nonexistent key"))))?
.deserialized() .deserialized()
.map_err(|e| err!(Database("key in keyid_key is invalid. {e:?}")))?; .map_err(|e| err!(Database(debug_warn!("key in keyid_key is invalid: {e:?}"))))?;
let signatures = cross_signing_key let signatures = cross_signing_key
.get_mut("signatures") .get_mut("signatures")
.ok_or_else(|| err!(Database("key in keyid_key has no signatures field.")))? .ok_or_else(|| {
err!(Database(debug_warn!("key in keyid_key has no signatures field")))
})?
.as_object_mut() .as_object_mut()
.ok_or_else(|| err!(Database("key in keyid_key has invalid signatures field.")))? .ok_or_else(|| {
err!(Database(debug_warn!("key in keyid_key has invalid signatures field.")))
})?
.entry(sender_id.to_string()) .entry(sender_id.to_string())
.or_insert_with(|| serde_json::Map::new().into()); .or_insert_with(|| serde_json::Map::new().into());
signatures signatures
.as_object_mut() .as_object_mut()
.ok_or_else(|| err!(Database("signatures in keyid_key for a user is invalid.")))? .ok_or_else(|| {
err!(Database(debug_warn!("signatures in keyid_key for a user is invalid.")))
})?
.insert(signature.0, signature.1.into()); .insert(signature.0, signature.1.into());
let key = (target_id, key_id); let key = (target_id, key_id);