Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot] 7ce2f3edb7 chore(deps): lock file maintenance 2024-07-27 19:32:34 +00:00
40 changed files with 465 additions and 660 deletions
+2 -2
View File
@@ -29,8 +29,8 @@ concurrency:
env: env:
# sccache only on main repo # sccache only on main repo
SCCACHE_GHA_ENABLED: "${{ (github.event.pull_request.draft != true) && (vars.DOCKER_USERNAME != '') && (vars.GITLAB_USERNAME != '') && (vars.SCCACHE_ENDPOINT != '') && (github.event.pull_request.user.login != 'renovate[bot]') && 'true' || 'false' }}" SCCACHE_GHA_ENABLED: "${{ (github.event.pull_request.draft != true) && (vars.DOCKER_USERNAME != '') && (vars.GITLAB_USERNAME != '') && (vars.SCCACHE_ENDPOINT != '') && (github.event.pull_request.user.login != 'renovate[bot]') && 'true' || 'false' }}"
RUSTC_WRAPPER: "${{ (github.event.pull_request.draft != true) && (vars.DOCKER_USERNAME != '') && (vars.GITLAB_USERNAME != '') && (vars.SCCACHE_ENDPOINT != '') && (github.event.pull_request.user.login != 'renovate[bot]') && 'sccache' || '' }}" RUSTC_WRAPPER: "${{ (github.event.pull_request.draft != true) && (vars.DOCKER_USERNAME != '') && (vars.GITLAB_USERNAME != '') && (vars.SCCACHE_ENDPOINT != '') && (github.event.pull_request.user.login != 'renovate[bot]') && 'sccache' }}"
SCCACHE_BUCKET: "${{ (github.event.pull_request.draft != true) && (vars.DOCKER_USERNAME != '') && (vars.GITLAB_USERNAME != '') && (vars.SCCACHE_ENDPOINT != '') && (github.event.pull_request.user.login != 'renovate[bot]') && 'sccache' || '' }}" SCCACHE_BUCKET: "${{ (github.event.pull_request.draft != true) && (vars.DOCKER_USERNAME != '') && (vars.GITLAB_USERNAME != '') && (vars.SCCACHE_ENDPOINT != '') && (github.event.pull_request.user.login != 'renovate[bot]') && 'sccache' }}"
SCCACHE_S3_USE_SSL: ${{ vars.SCCACHE_S3_USE_SSL }} SCCACHE_S3_USE_SSL: ${{ vars.SCCACHE_S3_USE_SSL }}
SCCACHE_REGION: ${{ vars.SCCACHE_REGION }} SCCACHE_REGION: ${{ vars.SCCACHE_REGION }}
SCCACHE_ENDPOINT: ${{ vars.SCCACHE_ENDPOINT }} SCCACHE_ENDPOINT: ${{ vars.SCCACHE_ENDPOINT }}
Generated
+195 -81
View File
@@ -153,6 +153,34 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "axum"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core 0.3.4",
"bitflags 1.3.2",
"bytes",
"futures-util",
"http 0.2.12",
"http-body 0.4.6",
"hyper 0.14.30",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"sync_wrapper 0.1.2",
"tower",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "axum" name = "axum"
version = "0.7.5" version = "0.7.5"
@@ -160,13 +188,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum-core", "axum-core 0.4.3",
"bytes", "bytes",
"futures-util", "futures-util",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"http-body-util", "http-body-util",
"hyper", "hyper 1.4.1",
"hyper-util", "hyper-util",
"itoa", "itoa",
"matchit", "matchit",
@@ -193,11 +221,28 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72188bed20deb981f3a4a9fe674e5980fd9e9c2bd880baa94715ad5d60d64c67" checksum = "72188bed20deb981f3a4a9fe674e5980fd9e9c2bd880baa94715ad5d60d64c67"
dependencies = [ dependencies = [
"axum", "axum 0.7.5",
"forwarded-header-value", "forwarded-header-value",
"serde", "serde",
] ]
[[package]]
name = "axum-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http 0.2.12",
"http-body 0.4.6",
"mime",
"rustversion",
"tower-layer",
"tower-service",
]
[[package]] [[package]]
name = "axum-core" name = "axum-core"
version = "0.4.3" version = "0.4.3"
@@ -207,8 +252,8 @@ dependencies = [
"async-trait", "async-trait",
"bytes", "bytes",
"futures-util", "futures-util",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"http-body-util", "http-body-util",
"mime", "mime",
"pin-project-lite", "pin-project-lite",
@@ -225,13 +270,13 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733"
dependencies = [ dependencies = [
"axum", "axum 0.7.5",
"axum-core", "axum-core 0.4.3",
"bytes", "bytes",
"futures-util", "futures-util",
"headers", "headers",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"http-body-util", "http-body-util",
"mime", "mime",
"pin-project-lite", "pin-project-lite",
@@ -250,10 +295,10 @@ dependencies = [
"arc-swap", "arc-swap",
"bytes", "bytes",
"futures-util", "futures-util",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"http-body-util", "http-body-util",
"hyper", "hyper 1.4.1",
"hyper-util", "hyper-util",
"pin-project-lite", "pin-project-lite",
"rustls 0.21.12", "rustls 0.21.12",
@@ -272,7 +317,7 @@ checksum = "7ea4cd08ae2a5f075d28fa31190163c8106a1d2d3189442494bae22b39040a0d"
dependencies = [ dependencies = [
"axum-server", "axum-server",
"bytes", "bytes",
"http", "http 1.1.0",
"http-body-util", "http-body-util",
"pin-project", "pin-project",
"tokio", "tokio",
@@ -594,7 +639,7 @@ dependencies = [
name = "conduit_api" name = "conduit_api"
version = "0.4.6" version = "0.4.6"
dependencies = [ dependencies = [
"axum", "axum 0.7.5",
"axum-client-ip", "axum-client-ip",
"axum-extra", "axum-extra",
"base64 0.22.1", "base64 0.22.1",
@@ -605,9 +650,9 @@ dependencies = [
"const-str", "const-str",
"futures-util", "futures-util",
"hmac", "hmac",
"http", "http 1.1.0",
"http-body-util", "http-body-util",
"hyper", "hyper 1.4.1",
"image", "image",
"ipaddress", "ipaddress",
"jsonwebtoken", "jsonwebtoken",
@@ -629,7 +674,7 @@ name = "conduit_core"
version = "0.4.6" version = "0.4.6"
dependencies = [ dependencies = [
"argon2", "argon2",
"axum", "axum 0.7.5",
"bytes", "bytes",
"cargo_toml", "cargo_toml",
"checked_ops", "checked_ops",
@@ -640,7 +685,7 @@ dependencies = [
"either", "either",
"figment", "figment",
"hardened_malloc-rs", "hardened_malloc-rs",
"http", "http 1.1.0",
"http-body-util", "http-body-util",
"image", "image",
"ipaddress", "ipaddress",
@@ -696,7 +741,7 @@ dependencies = [
name = "conduit_router" name = "conduit_router"
version = "0.4.6" version = "0.4.6"
dependencies = [ dependencies = [
"axum", "axum 0.7.5",
"axum-client-ip", "axum-client-ip",
"axum-server", "axum-server",
"axum-server-dual-protocol", "axum-server-dual-protocol",
@@ -706,9 +751,9 @@ dependencies = [
"conduit_core", "conduit_core",
"conduit_service", "conduit_service",
"const-str", "const-str",
"http", "http 1.1.0",
"http-body-util", "http-body-util",
"hyper", "hyper 1.4.1",
"hyper-util", "hyper-util",
"log", "log",
"ruma", "ruma",
@@ -736,7 +781,7 @@ dependencies = [
"cyborgtime", "cyborgtime",
"futures-util", "futures-util",
"hickory-resolver", "hickory-resolver",
"http", "http 1.1.0",
"image", "image",
"ipaddress", "ipaddress",
"itertools 0.13.0", "itertools 0.13.0",
@@ -761,9 +806,9 @@ dependencies = [
[[package]] [[package]]
name = "console-api" name = "console-api"
version = "0.8.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86ed14aa9c9f927213c6e4f3ef75faaad3406134efe84ba2cb7983431d5f0931" checksum = "a257c22cd7e487dd4a13d413beabc512c5052f0bc048db0da6a84c3d8a6142fd"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"prost", "prost",
@@ -774,9 +819,9 @@ dependencies = [
[[package]] [[package]]
name = "console-subscriber" name = "console-subscriber"
version = "0.4.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e3a111a37f3333946ebf9da370ba5c5577b18eb342ec683eb488dd21980302" checksum = "31c4cc54bae66f7d9188996404abdf7fdfa23034ef8e43478c8810828abad758"
dependencies = [ dependencies = [
"console-api", "console-api",
"crossbeam-channel", "crossbeam-channel",
@@ -784,7 +829,6 @@ dependencies = [
"futures-task", "futures-task",
"hdrhistogram", "hdrhistogram",
"humantime", "humantime",
"hyper-util",
"prost", "prost",
"prost-types", "prost-types",
"serde", "serde",
@@ -1328,6 +1372,25 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.12",
"indexmap 2.2.6",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.4.5" version = "0.4.5"
@@ -1339,7 +1402,7 @@ dependencies = [
"fnv", "fnv",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"http", "http 1.1.0",
"indexmap 2.2.6", "indexmap 2.2.6",
"slab", "slab",
"tokio", "tokio",
@@ -1387,7 +1450,7 @@ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"bytes", "bytes",
"headers-core", "headers-core",
"http", "http 1.1.0",
"httpdate", "httpdate",
"mime", "mime",
"sha1", "sha1",
@@ -1399,7 +1462,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4"
dependencies = [ dependencies = [
"http", "http 1.1.0",
] ]
[[package]] [[package]]
@@ -1516,6 +1579,17 @@ dependencies = [
"syn 2.0.72", "syn 2.0.72",
] ]
[[package]]
name = "http"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]] [[package]]
name = "http" name = "http"
version = "1.1.0" version = "1.1.0"
@@ -1536,6 +1610,17 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "http-body"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [
"bytes",
"http 0.2.12",
"pin-project-lite",
]
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "1.0.1" version = "1.0.1"
@@ -1543,7 +1628,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http 1.1.0",
] ]
[[package]] [[package]]
@@ -1554,8 +1639,8 @@ checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-util", "futures-util",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"pin-project-lite", "pin-project-lite",
] ]
@@ -1577,6 +1662,30 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.4.1" version = "1.4.1"
@@ -1586,9 +1695,9 @@ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"h2", "h2 0.4.5",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"httparse", "httparse",
"httpdate", "httpdate",
"itoa", "itoa",
@@ -1605,8 +1714,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http", "http 1.1.0",
"hyper", "hyper 1.4.1",
"hyper-util", "hyper-util",
"rustls 0.23.12", "rustls 0.23.12",
"rustls-native-certs", "rustls-native-certs",
@@ -1619,15 +1728,14 @@ dependencies = [
[[package]] [[package]]
name = "hyper-timeout" name = "hyper-timeout"
version = "0.5.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
dependencies = [ dependencies = [
"hyper", "hyper 0.14.30",
"hyper-util",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
"tower-service", "tokio-io-timeout",
] ]
[[package]] [[package]]
@@ -1639,9 +1747,9 @@ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"hyper", "hyper 1.4.1",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio", "tokio",
@@ -2586,9 +2694,9 @@ dependencies = [
[[package]] [[package]]
name = "prost" name = "prost"
version = "0.13.1" version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29"
dependencies = [ dependencies = [
"bytes", "bytes",
"prost-derive", "prost-derive",
@@ -2596,12 +2704,12 @@ dependencies = [
[[package]] [[package]]
name = "prost-derive" name = "prost-derive"
version = "0.13.1" version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"itertools 0.13.0", "itertools 0.12.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.72", "syn 2.0.72",
@@ -2609,9 +2717,9 @@ dependencies = [
[[package]] [[package]]
name = "prost-types" name = "prost-types"
version = "0.13.1" version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0"
dependencies = [ dependencies = [
"prost", "prost",
] ]
@@ -2796,12 +2904,12 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2 0.4.5",
"hickory-resolver", "hickory-resolver",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"http-body-util", "http-body-util",
"hyper", "hyper 1.4.1",
"hyper-rustls", "hyper-rustls",
"hyper-util", "hyper-util",
"ipnet", "ipnet",
@@ -2901,7 +3009,7 @@ dependencies = [
"assign", "assign",
"bytes", "bytes",
"date_header", "date_header",
"http", "http 1.1.0",
"js_int", "js_int",
"js_option", "js_option",
"maplit", "maplit",
@@ -2924,7 +3032,7 @@ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes", "bytes",
"form_urlencoded", "form_urlencoded",
"http", "http 1.1.0",
"indexmap 2.2.6", "indexmap 2.2.6",
"js_int", "js_int",
"konst", "konst",
@@ -3032,7 +3140,7 @@ version = "0.3.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=c76e2873c1593a3308d4ba3e0e4a1db65acf8536#c76e2873c1593a3308d4ba3e0e4a1db65acf8536" source = "git+https://github.com/girlbossceo/ruwuma?rev=c76e2873c1593a3308d4ba3e0e4a1db65acf8536#c76e2873c1593a3308d4ba3e0e4a1db65acf8536"
dependencies = [ dependencies = [
"headers", "headers",
"http", "http 1.1.0",
"http-auth", "http-auth",
"ruma-common", "ruma-common",
"thiserror", "thiserror",
@@ -3411,7 +3519,7 @@ version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c90802b38c899a2c9e557dff25ad186362eddf755d5f5244001b172dd03bead" checksum = "6c90802b38c899a2c9e557dff25ad186362eddf755d5f5244001b172dd03bead"
dependencies = [ dependencies = [
"http", "http 1.1.0",
"pin-project", "pin-project",
"sentry-core", "sentry-core",
"tower-layer", "tower-layer",
@@ -3483,12 +3591,11 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.121" version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr",
"ryu", "ryu",
"serde", "serde",
] ]
@@ -3964,6 +4071,16 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "tokio-io-timeout"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
dependencies = [
"pin-project-lite",
"tokio",
]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.4.0" version = "2.4.0"
@@ -4010,9 +4127,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-socks" name = "tokio-socks"
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 = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f"
dependencies = [ dependencies = [
"either", "either",
"futures-util", "futures-util",
@@ -4091,26 +4208,23 @@ dependencies = [
[[package]] [[package]]
name = "tonic" name = "tonic"
version = "0.12.1" version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13"
dependencies = [ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
"axum", "axum 0.6.20",
"base64 0.22.1", "base64 0.21.7",
"bytes", "bytes",
"h2", "h2 0.3.26",
"http", "http 0.2.12",
"http-body", "http-body 0.4.6",
"http-body-util", "hyper 0.14.30",
"hyper",
"hyper-timeout", "hyper-timeout",
"hyper-util",
"percent-encoding", "percent-encoding",
"pin-project", "pin-project",
"prost", "prost",
"socket2",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tower", "tower",
@@ -4150,8 +4264,8 @@ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"futures-util", "futures-util",
"http", "http 1.1.0",
"http-body", "http-body 1.0.1",
"http-body-util", "http-body-util",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
+4 -19
View File
@@ -33,7 +33,6 @@ version = "0.2.8"
[workspace.dependencies.cargo_toml] [workspace.dependencies.cargo_toml]
version = "0.20" version = "0.20"
default-features = false
features = ["features"] features = ["features"]
[workspace.dependencies.toml] [workspace.dependencies.toml]
@@ -97,7 +96,6 @@ features = ["typed-header", "tracing"]
[workspace.dependencies.axum-server] [workspace.dependencies.axum-server]
version = "0.6.0" version = "0.6.0"
default-features = false
features = ["tls-rustls"] features = ["tls-rustls"]
[workspace.dependencies.axum-client-ip] [workspace.dependencies.axum-client-ip]
@@ -105,12 +103,10 @@ version = "0.6.0"
[workspace.dependencies.tower] [workspace.dependencies.tower]
version = "0.4.13" version = "0.4.13"
default-features = false
features = ["util"] features = ["util"]
[workspace.dependencies.tower-http] [workspace.dependencies.tower-http]
version = "0.5.2" version = "0.5.2"
default-features = false
features = [ features = [
"add-extension", "add-extension",
"cors", "cors",
@@ -133,12 +129,10 @@ features = [
[workspace.dependencies.serde] [workspace.dependencies.serde]
version = "1.0.204" version = "1.0.204"
default-features = false
features = ["rc"] features = ["rc"]
[workspace.dependencies.serde_json] [workspace.dependencies.serde_json]
version = "1.0.121" version = "1.0.120"
default-features = false
features = ["raw_value"] features = ["raw_value"]
# Used for appservice registration files # Used for appservice registration files
@@ -206,8 +200,7 @@ version = "0.3.30"
default-features = false default-features = false
[workspace.dependencies.tokio] [workspace.dependencies.tokio]
version = "1.39.2" version = "1.39.1"
default-features = false
features = [ features = [
"fs", "fs",
"net", "net",
@@ -228,7 +221,6 @@ version = "0.8.5"
# Validating urls in config, was already a transitive dependency # Validating urls in config, was already a transitive dependency
[workspace.dependencies.url] [workspace.dependencies.url]
version = "2.5.0" version = "2.5.0"
default-features = false
features = ["serde"] features = ["serde"]
# standard date and time tools # standard date and time tools
@@ -239,7 +231,6 @@ default-features = false
[workspace.dependencies.hyper] [workspace.dependencies.hyper]
version = "1.4.1" version = "1.4.1"
default-features = false
features = [ features = [
"server", "server",
"http1", "http1",
@@ -248,7 +239,6 @@ features = [
[workspace.dependencies.hyper-util] [workspace.dependencies.hyper-util]
version = "0.1.6" version = "0.1.6"
default-features = false
features = [ features = [
"client", "client",
"server-auto", "server-auto",
@@ -260,13 +250,11 @@ features = [
# to support multiple variations of setting a config option # to support multiple variations of setting a config option
[workspace.dependencies.either] [workspace.dependencies.either]
version = "1.11.0" version = "1.11.0"
default-features = false
features = ["serde"] features = ["serde"]
# Used for reading the configuration from conduwuit.toml & environment variables # Used for reading the configuration from conduwuit.toml & environment variables
[workspace.dependencies.figment] [workspace.dependencies.figment]
version = "0.10.18" version = "0.10.18"
default-features = false
features = ["env", "toml"] features = ["env", "toml"]
[workspace.dependencies.hickory-resolver] [workspace.dependencies.hickory-resolver]
@@ -408,11 +396,10 @@ default-features = false
features = ["use_std"] features = ["use_std"]
[workspace.dependencies.console-subscriber] [workspace.dependencies.console-subscriber]
version = "0.4" version = "0.3"
[workspace.dependencies.nix] [workspace.dependencies.nix]
version = "0.29.0" version = "0.29.0"
default-features = false
features = ["resource"] features = ["resource"]
[workspace.dependencies.sd-notify] [workspace.dependencies.sd-notify]
@@ -440,7 +427,6 @@ version = "0.1"
[workspace.dependencies.syn] [workspace.dependencies.syn]
version = "2.0.72" version = "2.0.72"
default-features = false
features = ["full", "extra-traits"] features = ["full", "extra-traits"]
[workspace.dependencies.quote] [workspace.dependencies.quote]
@@ -815,7 +801,7 @@ perf = { level = "warn", priority = -1 }
################### ###################
#restriction = "warn" #restriction = "warn"
#allow_attributes = "warn" # UNSTABLE allow_attributes = "warn"
arithmetic_side_effects = "warn" arithmetic_side_effects = "warn"
as_conversions = "warn" as_conversions = "warn"
as_underscore = "warn" as_underscore = "warn"
@@ -865,7 +851,6 @@ style = { level = "warn", priority = -1 }
## some sadness ## some sadness
# trivial assertions are quite alright # trivial assertions are quite alright
assertions_on_constants = { level = "allow", priority = 1 } assertions_on_constants = { level = "allow", priority = 1 }
module_inception = { level = "allow", priority = 1 }
################### ###################
suspicious = { level = "warn", priority = -1 } suspicious = { level = "warn", priority = -1 }
+3 -5
View File
@@ -224,11 +224,9 @@ registration_token = "change this token for something specific to your server"
# No default. # No default.
# forbidden_alias_names = [] # forbidden_alias_names = []
# List of forbidden server names that we will block incoming AND outgoing federation with, and block client room joins / remote user invites. # List of forbidden server names that we will block all client room joins, incoming federated room directory requests, incoming federated invites for, and incoming federated joins. This check is applied on the room ID, room alias, sender server name, and sender user's server name.
# # Basically "global" ACLs. For our user (client) checks, admin users are allowed.
# This check is applied on the room ID, room alias, sender server name, sender user's server name, inbound federation X-Matrix origin, and outbound federation handler. # No default.
#
# Basically "global" ACLs. No default.
# forbidden_remote_server_names = [] # forbidden_remote_server_names = []
# List of forbidden server names that we will block all outgoing federated room directory requests for. Useful for preventing our users from wandering into bad servers or spaces. # List of forbidden server names that we will block all outgoing federated room directory requests for. Useful for preventing our users from wandering into bad servers or spaces.
+1
View File
@@ -16,6 +16,7 @@ case "$1" in
--home "$CONDUWUIT_DATABASE_PATH" \ --home "$CONDUWUIT_DATABASE_PATH" \
--disabled-login \ --disabled-login \
--shell "/usr/sbin/nologin" \ --shell "/usr/sbin/nologin" \
--verbose \
conduwuit conduwuit
fi fi
-1
View File
@@ -10,7 +10,6 @@
- [Docker](deploying/docker.md) - [Docker](deploying/docker.md)
- [Arch Linux](deploying/arch-linux.md) - [Arch Linux](deploying/arch-linux.md)
- [Debian](deploying/debian.md) - [Debian](deploying/debian.md)
- [FreeBSD](deploying/freebsd.md)
- [TURN](turn.md) - [TURN](turn.md)
- [Appservices](appservices.md) - [Appservices](appservices.md)
- [Maintenance](maintenance.md) - [Maintenance](maintenance.md)
+4 -24
View File
@@ -4,35 +4,15 @@ This chapter describes various ways to configure conduwuit.
## Basics ## Basics
conduwuit uses a config file for the majority of the settings, but also supports setting individual config options via commandline. Conduwuit uses a config file for the majority of the settings. Please refer to the
[example config file](./configuration/examples.md#example-configuration) for all of those settings.
Please refer to the [example config file](./configuration/examples.md#example-configuration) for all of those settings. The config file to use can either be specified on the command line when running conduwuit by specifying the
The config file to use can be specified on the commandline when running conduwuit by specifying the
`-c`, `--config` flag. Alternatively, you can use the environment variable `CONDUWUIT_CONFIG` to specify the config `-c`, `--config` flag. Alternatively, you can use the environment variable `CONDUWUIT_CONFIG` to specify the config
file to used. Conduit's environment variables are supported for backwards compatibility. file to used.
## Option commandline flag
conduwuit supports setting individual config options in TOML format from the `-O` / `--option` flag. For example, you can set your server name via `-O server_name=\"example.com\"`.
Note that the config is parsed as TOML, and shells like bash will remove quotes. So unfortunately it is required to escape quotes if the config option takes a string.
This does not apply to options that take booleans or numbers:
- `--option allow_registration=true` works ✅
- `-O max_request_size=99999999` works ✅
- `-O server_name=example.com` does not work ❌
- `--option log=\"debug\"` works ✅
- `--option server_name='"example.com'"` works ✅
## Environment variables ## Environment variables
All of the settings that are found in the config file can be specified by using environment variables. All of the settings that are found in the config file can be specified by using environment variables.
The environment variable names should be all caps and prefixed with `CONDUWUIT_`. The environment variable names should be all caps and prefixed with `CONDUWUIT_`.
For example, if the setting you are changing is `max_request_size`, then the environment variable to set is For example, if the setting you are changing is `max_request_size`, then the environment variable to set is
`CONDUWUIT_MAX_REQUEST_SIZE`. `CONDUWUIT_MAX_REQUEST_SIZE`.
To modify config options not in the `[global]` context such as `[global.well_known]`, use the `__` suffix split: `CONDUWUIT_WELL_KNOWN__SERVER`
Conduit's environment variables are supported for backwards compatibility (e.g. `CONDUIT_SERVER_NAME`).
-8
View File
@@ -1,8 +0,0 @@
# conduwuit for FreeBSD
conduwuit at the moment does not provide FreeBSD builds. Building conduwuit on FreeBSD requires a specific environment variable to use the
system prebuilt RocksDB library instead of rust-rocksdb / rust-librocksdb-sys which does *not* work and will cause a build error or coredump.
Use the following environment variable: `ROCKSDB_LIB_DIR=/usr/local/lib`
Such example commandline with it can be: `ROCKSDB_LIB_DIR=/usr/local/lib cargo build --release`
+4 -2
View File
@@ -9,12 +9,14 @@
You may simply download the binary that fits your machine. Run `uname -m` to see what you need. You may simply download the binary that fits your machine. Run `uname -m` to see what you need.
Prebuilt fully static musl binaries can be downloaded from the latest tagged release [here](https://github.com/girlbossceo/conduwuit/releases/latest) or `main` CI branch workflow artifact output. These also include Debian packages. These binaries have jemalloc and io_uring statically linked and included with them. Prebuilt binaries can be downloaded from the latest tagged release [here](https://github.com/girlbossceo/conduwuit/releases/latest).
The latest tagged release also includes the Debian packages.
Alternatively, you may compile the binary yourself. We recommend using [Lix](https://lix.systems) to build conduwuit as this has the most guaranteed Alternatively, you may compile the binary yourself. We recommend using [Lix](https://lix.systems) to build conduwuit as this has the most guaranteed
reproducibiltiy and easiest to get a build environment and output going. reproducibiltiy and easiest to get a build environment and output going.
Otherwise, follow standard Rust project build guides (installing git and cloning the repo, getting the Rust toolchain via rustup, installing LLVM toolchain + libclang for RocksDB, installing liburing for io_uring and RocksDB, etc). Otherwise, follow standard Rust project build guides (installing git and cloning the repo, getting the Rust toolchain via rustup, installing LLVM toolchain + libclang, installing liburing for io_uring and RocksDB, etc).
## Adding a conduwuit user ## Adding a conduwuit user
+2 -11
View File
@@ -8,17 +8,6 @@
> >
> If there are things like Compose file issues or Dockerhub image issues, those can still be mentioned as long as they're something we can fix. > If there are things like Compose file issues or Dockerhub image issues, those can still be mentioned as long as they're something we can fix.
## General potential issues
#### Potential DNS issues when using Docker
Docker has issues with its default DNS setup that may cause DNS to not be properly functional when running conduwuit, resulting in federation issues.
The symptoms of this have shown in excessively long room joins (30+ minutes) from very long DNS timeouts, log entries of "mismatching responding nameservers", and/or partial or non-functional inbound/outbound federation.
This is **not** a conduwuit issue, and is purely a Docker issue. It is not sustainable for heavy DNS activity which is normal for Matrix federation. The workarounds for this are:
- Use DNS over TCP via the config option `query_over_tcp_only = true`
- Don't use Docker's default DNS setup and instead allow the container to use and communicate with your host's DNS servers (host's `/etc/resolv.conf`)
## Rocksdb / database issues ## Rocksdb / database issues
#### Direct IO #### Direct IO
@@ -49,6 +38,8 @@ With this in mind:
- Leave your conduwuit running in `PointInTime` for at least 30-60 minutes so as much possible corruption is restored - Leave your conduwuit running in `PointInTime` for at least 30-60 minutes so as much possible corruption is restored
- If all goes will, you should be able to restore back to using `TolerateCorruptedTailRecords` and you have successfully recovered your database - If all goes will, you should be able to restore back to using `TolerateCorruptedTailRecords` and you have successfully recovered your database
## Media
## Debugging ## Debugging
Note that users should not really be debugging things. If you find yourself debugging and find the issue, please let us know and/or how we can fix it. Various debug commands can be found in `!admin debug`. Note that users should not really be debugging things. If you find yourself debugging and find the issue, please let us know and/or how we can fix it. Various debug commands can be found in `!admin debug`.
-4
View File
@@ -137,11 +137,7 @@
# Useful for editing the book locally # Useful for editing the book locally
mdbook mdbook
# used for rust caching in CI to speed it up
sccache sccache
# needed so we can get rid of gcc and other unused deps that bloat OCI images
removeReferencesTo
]) ])
++ scope.main.buildInputs ++ scope.main.buildInputs
++ scope.main.propagatedBuildInputs ++ scope.main.propagatedBuildInputs
+3 -15
View File
@@ -7,7 +7,6 @@
, liburing , liburing
, pkgsBuildHost , pkgsBuildHost
, rocksdb , rocksdb
, removeReferencesTo
, rust , rust
, rust-jemalloc-sys , rust-jemalloc-sys
, stdenv , stdenv
@@ -95,8 +94,8 @@ buildDepsOnlyEnv =
else if stdenv.targetPlatform.isAarch64 else if stdenv.targetPlatform.isAarch64
then lib.subtractLists [ "-DPORTABLE=1" ] old.cmakeFlags then lib.subtractLists [ "-DPORTABLE=1" ] old.cmakeFlags
++ lib.optionals stdenv.targetPlatform.isAarch64 [ ++ lib.optionals stdenv.targetPlatform.isAarch64 [
# cortex-a73 == ARMv8-A # cortex-a55 == ARMv8.2-a
"-DPORTABLE=armv8-a" "-DPORTABLE=armv8.2-a"
] ]
else old.cmakeFlags; else old.cmakeFlags;
}); });
@@ -129,7 +128,7 @@ buildPackageEnv = {
+ lib.optionalString stdenv.targetPlatform.isx86_64 + lib.optionalString stdenv.targetPlatform.isx86_64
" -Ctarget-cpu=x86-64-v2" " -Ctarget-cpu=x86-64-v2"
+ lib.optionalString stdenv.targetPlatform.isAarch64 + lib.optionalString stdenv.targetPlatform.isAarch64
" -Ctarget-cpu=cortex-a73"; # cortex-a73 == ARMv8-A " -Ctarget-cpu=cortex-a55"; # cortex-a55 == ARMv8.2-a
}; };
@@ -155,7 +154,6 @@ commonAttrs = {
}; };
dontStrip = profile == "dev" || profile == "test"; dontStrip = profile == "dev" || profile == "test";
dontPatchELF = profile == "dev" || profile == "test";
buildInputs = lib.optional (featureEnabled "jemalloc") rust-jemalloc-sys'; buildInputs = lib.optional (featureEnabled "jemalloc") rust-jemalloc-sys';
@@ -170,9 +168,6 @@ commonAttrs = {
# differing values for `NIX_CFLAGS_COMPILE`, which contributes to spurious # differing values for `NIX_CFLAGS_COMPILE`, which contributes to spurious
# rebuilds of bindgen and its depedents. # rebuilds of bindgen and its depedents.
jq jq
# needed so we can get rid of gcc and other unused deps that bloat OCI images
removeReferencesTo
] ]
++ lib.optionals stdenv.isDarwin [ ++ lib.optionals stdenv.isDarwin [
# https://github.com/NixOS/nixpkgs/issues/206242 # https://github.com/NixOS/nixpkgs/issues/206242
@@ -182,13 +177,6 @@ commonAttrs = {
# https://discourse.nixos.org/t/compile-a-rust-binary-on-macos-dbcrossbar/8612 # https://discourse.nixos.org/t/compile-a-rust-binary-on-macos-dbcrossbar/8612
pkgsBuildHost.darwin.apple_sdk.frameworks.Security pkgsBuildHost.darwin.apple_sdk.frameworks.Security
]; ];
# for some reason gcc and other weird deps are added to OCI images and bloats it up
#
# <https://github.com/input-output-hk/haskell.nix/issues/829>
postInstall = with pkgsBuildHost; ''
find "$out" -type f -exec remove-references-to -t ${stdenv.cc} -t ${gcc} -t ${libgcc} -t ${linuxHeaders} -t ${libidn2} -t ${libunistring} '{}' +
'';
}; };
in in
+2 -11
View File
@@ -149,32 +149,23 @@ pub(super) async fn get_remote_pdu_list(
.filter_map(|pdu| EventId::parse(pdu).ok()) .filter_map(|pdu| EventId::parse(pdu).ok())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut failed_count: usize = 0;
let mut success_count: usize = 0;
for pdu in list { for pdu in list {
if force { if force {
if let Err(e) = self.get_remote_pdu(Box::from(pdu), server.clone()).await { if let Err(e) = self.get_remote_pdu(Box::from(pdu), server.clone()).await {
failed_count = failed_count.saturating_add(1);
self.services self.services
.admin .admin
.send_message(RoomMessageEventContent::text_plain(format!( .send_message(RoomMessageEventContent::text_plain(format!(
"Failed to get remote PDU, ignoring error: {e}" "Failed to get remote PDU, ignoring error: {e}"
))) )))
.await; .await;
warn!("Failed to get remote PDU, ignoring error: {e}"); warn!(%e, "Failed to get remote PDU, ignoring error");
} else {
success_count = success_count.saturating_add(1);
} }
} else { } else {
self.get_remote_pdu(Box::from(pdu), server.clone()).await?; self.get_remote_pdu(Box::from(pdu), server.clone()).await?;
success_count = success_count.saturating_add(1);
} }
} }
Ok(RoomMessageEventContent::text_plain(format!( Ok(RoomMessageEventContent::text_plain("Fetched list of remote PDUs."))
"Fetched {success_count} remote PDUs successfully with {failed_count} failures"
)))
} }
#[admin_command] #[admin_command]
+5 -34
View File
@@ -1,7 +1,7 @@
use std::{panic::AssertUnwindSafe, sync::Arc, time::Instant}; use std::{panic::AssertUnwindSafe, sync::Arc, time::Instant};
use clap::{CommandFactory, Parser}; use clap::{CommandFactory, Parser};
use conduit::{checked, error, trace, utils::string::common_prefix, Error, Result}; use conduit::{error, trace, utils::string::common_prefix, Error, Result};
use futures_util::future::FutureExt; use futures_util::future::FutureExt;
use ruma::{ use ruma::{
events::{ events::{
@@ -60,11 +60,8 @@ fn reply(mut content: RoomMessageEventContent, reply_id: Option<OwnedEventId>) -
// Parse and process a message from the admin room // Parse and process a message from the admin room
async fn process(services: Arc<Services>, msg: &str) -> CommandOutput { async fn process(services: Arc<Services>, msg: &str) -> CommandOutput {
let lines = msg.lines().filter(|l| !l.trim().is_empty()); let mut lines = msg.lines().filter(|l| !l.trim().is_empty());
let command = lines let command = lines.next().expect("each string has at least one line");
.clone()
.next()
.expect("each string has at least one line");
let (parsed, body) = match parse_command(command) { let (parsed, body) = match parse_command(command) {
Ok(parsed) => parsed, Ok(parsed) => parsed,
Err(error) => { Err(error) => {
@@ -74,12 +71,12 @@ async fn process(services: Arc<Services>, msg: &str) -> CommandOutput {
}, },
}; };
let body = parse_body(AdminCommand::command(), &body, lines.skip(1).collect()).expect("trailing body parsed"); let timer = Instant::now();
let body: Vec<&str> = body.iter().map(String::as_str).collect();
let context = Command { let context = Command {
services: &services, services: &services,
body: &body, body: &body,
}; };
let timer = Instant::now();
let result = Box::pin(admin::process(parsed, &context)).await; let result = Box::pin(admin::process(parsed, &context)).await;
let elapsed = timer.elapsed(); let elapsed = timer.elapsed();
conduit::debug!(?command, ok = result.is_ok(), "command processed in {elapsed:?}"); conduit::debug!(?command, ok = result.is_ok(), "command processed in {elapsed:?}");
@@ -98,32 +95,6 @@ fn parse_command(command_line: &str) -> Result<(AdminCommand, Vec<String>), Stri
Ok((com, argv)) Ok((com, argv))
} }
fn parse_body<'a>(mut cmd: clap::Command, body: &'a [String], lines: Vec<&'a str>) -> Result<Vec<&'a str>> {
let mut start = 1;
'token: for token in body.iter().skip(1) {
let cmd_ = cmd.clone();
for sub in cmd_.get_subcommands() {
if sub.get_name() == *token {
start = checked!(start + 1)?;
cmd = sub.clone();
continue 'token;
}
}
// positional arguments have to be skipped too
let num_posargs = cmd_.get_positionals().count();
start = checked!(start + num_posargs)?;
break;
}
Ok(body
.iter()
.skip(start)
.map(String::as_str)
.chain(lines)
.collect::<Vec<&'a str>>())
}
fn complete_command(mut cmd: clap::Command, line: &str) -> String { fn complete_command(mut cmd: clap::Command, line: &str) -> String {
let argv = parse_line(line); let argv = parse_line(line);
let mut ret = Vec::<String>::with_capacity(argv.len().saturating_add(1)); let mut ret = Vec::<String>::with_capacity(argv.len().saturating_add(1));
+2 -2
View File
@@ -35,13 +35,13 @@ pub(super) async fn list_features(
}; };
if enabled && !available { if enabled && !available {
let features = info::rustc::features().join(delim); let features = info::rustc::features().join(delim);
let out = format!("`\n{features}\n`"); let out = format!("```\n{features}\n```");
return Ok(RoomMessageEventContent::text_markdown(out)); return Ok(RoomMessageEventContent::text_markdown(out));
} }
if available && !enabled { if available && !enabled {
let features = info::cargo::features().join(delim); let features = info::cargo::features().join(delim);
let out = format!("`\n{features}\n`"); let out = format!("```\n{features}\n```");
return Ok(RoomMessageEventContent::text_markdown(out)); return Ok(RoomMessageEventContent::text_markdown(out));
} }
+3 -7
View File
@@ -286,13 +286,9 @@ pub(crate) async fn register_route(
let token = utils::random_string(TOKEN_LENGTH); let token = utils::random_string(TOKEN_LENGTH);
// Create device for this account // Create device for this account
services.users.create_device( services
&user_id, .users
&device_id, .create_device(&user_id, &device_id, &token, body.initial_device_display_name.clone())?;
&token,
body.initial_device_display_name.clone(),
Some(client.to_string()),
)?;
debug_info!(%user_id, %device_id, "User account was created"); debug_info!(%user_id, %device_id, "User account was created");
+1 -3
View File
@@ -21,13 +21,11 @@ pub(crate) async fn get_context_route(
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let sender_device = body.sender_device.as_ref().expect("user is authenticated"); let sender_device = body.sender_device.as_ref().expect("user is authenticated");
// some clients, at least element, seem to require knowledge of redundant
// members for "inline" profiles on the timeline to work properly
let (lazy_load_enabled, lazy_load_send_redundant) = match &body.filter.lazy_load_options { let (lazy_load_enabled, lazy_load_send_redundant) = match &body.filter.lazy_load_options {
LazyLoadOptions::Enabled { LazyLoadOptions::Enabled {
include_redundant_members, include_redundant_members,
} => (true, *include_redundant_members), } => (true, *include_redundant_members),
LazyLoadOptions::Disabled => (false, cfg!(feature = "element_hacks")), LazyLoadOptions::Disabled => (false, false),
}; };
let mut lazy_loaded = HashSet::new(); let mut lazy_loaded = HashSet::new();
+21 -8
View File
@@ -5,19 +5,19 @@ use std::{io::Cursor, time::Duration};
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp; use axum_client_ip::InsecureClientIp;
use conduit::{ use conduit::{
debug, debug_info, debug_warn, err, info, debug, debug_warn, error,
utils::{ utils::{
self, self,
content_disposition::{content_disposition_type, make_content_disposition, sanitise_filename}, content_disposition::{content_disposition_type, make_content_disposition, sanitise_filename},
math::ruma_from_usize, math::ruma_from_usize,
}, },
warn, Err, Error, Result, warn, Error, Result,
}; };
use image::io::Reader as ImgReader; use image::io::Reader as ImgReader;
use ipaddress::IPAddress; use ipaddress::IPAddress;
use reqwest::Url; use reqwest::Url;
use ruma::api::client::{ use ruma::api::client::{
error::ErrorKind, error::{ErrorKind, RetryAfter},
media::{ media::{
create_content, get_content, get_content_as_filename, get_content_thumbnail, get_media_config, create_content, get_content, get_content_as_filename, get_content_thumbnail, get_media_config,
get_media_preview, get_media_preview,
@@ -77,22 +77,35 @@ pub(crate) async fn get_media_preview_route(
let url = &body.url; let url = &body.url;
if !url_preview_allowed(&services, url) { if !url_preview_allowed(&services, url) {
debug_info!(%sender_user, "URL is not allowed to be previewed: {url}"); warn!(%sender_user, "URL is not allowed to be previewed: {url}");
return Err(Error::BadRequest(ErrorKind::forbidden(), "URL is not allowed to be previewed")); return Err(Error::BadRequest(ErrorKind::forbidden(), "URL is not allowed to be previewed"));
} }
match get_url_preview(&services, url).await { match get_url_preview(&services, url).await {
Ok(preview) => { Ok(preview) => {
let res = serde_json::value::to_raw_value(&preview).map_err(|e| { let res = serde_json::value::to_raw_value(&preview).map_err(|e| {
warn!(%sender_user, "Failed to convert UrlPreviewData into a serde json value: {e}"); error!(%sender_user, "Failed to convert UrlPreviewData into a serde json value: {e}");
err!(Request(Unknown("Failed to generate a URL preview"))) Error::BadRequest(
ErrorKind::LimitExceeded {
retry_after: Some(RetryAfter::Delay(Duration::from_secs(5))),
},
"Failed to generate a URL preview, try again later.",
)
})?; })?;
Ok(get_media_preview::v3::Response::from_raw_value(res)) Ok(get_media_preview::v3::Response::from_raw_value(res))
}, },
Err(e) => { Err(e) => {
info!(%sender_user, "Failed to generate a URL preview: {e}"); warn!(%sender_user, "Failed to generate a URL preview: {e}");
Err!(Request(Unknown("Failed to generate a URL preview")))
// there doesn't seem to be an agreed-upon error code in the spec.
// the only response codes in the preview_url spec page are 200 and 429.
Err(Error::BadRequest(
ErrorKind::LimitExceeded {
retry_after: Some(RetryAfter::Delay(Duration::from_secs(5))),
},
"Failed to generate a URL preview, try again later.",
))
}, },
} }
} }
+34 -96
View File
@@ -1,7 +1,7 @@
use std::{cmp::max, collections::BTreeMap}; use std::{cmp::max, collections::BTreeMap};
use axum::extract::State; use axum::extract::State;
use conduit::{debug_info, debug_warn, err}; use conduit::{debug_info, debug_warn};
use ruma::{ use ruma::{
api::client::{ api::client::{
error::ErrorKind, error::ErrorKind,
@@ -20,7 +20,6 @@ use ruma::{
tombstone::RoomTombstoneEventContent, tombstone::RoomTombstoneEventContent,
topic::RoomTopicEventContent, topic::RoomTopicEventContent,
}, },
space::child::SpaceChildEventContent,
StateEventType, TimelineEventType, StateEventType, TimelineEventType,
}, },
int, int,
@@ -476,7 +475,10 @@ pub(crate) async fn get_room_event_route(
.rooms .rooms
.timeline .timeline
.get_pdu(&body.event_id)? .get_pdu(&body.event_id)?
.ok_or_else(|| err!(Request(NotFound("Event {} not found.", &body.event_id))))?; .ok_or_else(|| {
warn!("Event not found, event ID: {:?}", &body.event_id);
Error::BadRequest(ErrorKind::NotFound, "Event not found.")
})?;
if !services if !services
.rooms .rooms
@@ -619,15 +621,23 @@ pub(crate) async fn upgrade_room_route(
V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => { V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | V10 => {
create_event_content.insert( create_event_content.insert(
"creator".into(), "creator".into(),
json!(&sender_user) json!(&sender_user).try_into().map_err(|e| {
.try_into() info!("Error forming creation event: {e}");
.map_err(|_| err!(Request(BadJson("Error forming creation event"))))?, Error::BadRequest(ErrorKind::BadJson, "Error forming creation event")
})?,
); );
}, },
_ => { V11 => {
// "creator" key no longer exists in V11+ rooms // "creator" key no longer exists in V11 rooms
create_event_content.remove("creator"); create_event_content.remove("creator");
}, },
_ => {
warn!("Unexpected or unsupported room version {}", body.new_version);
return Err(Error::BadRequest(
ErrorKind::BadJson,
"Unexpected or unsupported room version found",
));
},
} }
} }
@@ -635,100 +645,26 @@ pub(crate) async fn upgrade_room_route(
"room_version".into(), "room_version".into(),
json!(&body.new_version) json!(&body.new_version)
.try_into() .try_into()
.map_err(|_| err!(Request(BadJson("Error forming creation event"))))?, .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
); );
create_event_content.insert( create_event_content.insert(
"predecessor".into(), "predecessor".into(),
json!(predecessor) json!(predecessor)
.try_into() .try_into()
.map_err(|_| err!(Request(BadJson("Error forming creation event"))))?, .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
); );
// if the room was a space: // Validate creation event content
// - migrate m.space.child and/or m.space.parent if serde_json::from_str::<CanonicalJsonObject>(
// - add space type to replacement room m.room.create to_raw_value(&create_event_content)
// .expect("Error forming creation event")
// as apart of MSC4168 .get(),
if services )
.rooms .is_err()
.state_accessor
.get_room_type(&body.room_id)
.unwrap_or(None)
.is_some_and(|room_type| room_type == ruma::room::RoomType::Space)
{ {
create_event_content.insert( return Err(Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"));
"type".into(),
json!(ruma::room::RoomType::Space)
.try_into()
.map_err(|_| err!(Request(BadJson("Error forming creation event"))))?,
);
if let Some(event_content) = services
.rooms
.state_accessor
.room_state_get(&body.room_id, &StateEventType::SpaceChild, body.room_id.as_str())
.unwrap_or(None)
{
// space contents that are empty are not apart of the space
if !event_content.content.get().is_empty() {
// remove all but us from via
let mut new_content: SpaceChildEventContent = serde_json::from_str(event_content.content.get())
.map_err(|_| err!(Database(error!("Invalid m.space.child content in database"))))?;
new_content.via = vec![services.globals.config.server_name.clone()];
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder {
event_type: StateEventType::SpaceChild.to_string().into(),
content: to_raw_value(&new_content).expect("we just created it"),
unsigned: None,
state_key: Some(replacement_room.to_string()),
redacts: None,
},
sender_user,
&replacement_room,
&state_lock,
)
.await?;
}
}
if let Some(event_content) = services
.rooms
.state_accessor
.room_state_get(&body.room_id, &StateEventType::SpaceParent, body.room_id.as_str())
.unwrap_or(None)
{
// space contents that are empty are not apart of the space
if !event_content.content.get().is_empty() {
// remove all but us from via
let mut new_content: SpaceChildEventContent = serde_json::from_str(event_content.content.get())
.map_err(|_| err!(Database(error!("Invalid m.space.child content in database"))))?;
new_content.via = vec![services.globals.config.server_name.clone()];
services
.rooms
.timeline
.build_and_append_pdu(
PduBuilder {
event_type: StateEventType::SpaceParent.to_string().into(),
content: to_raw_value(&new_content).expect("we just created it"),
unsigned: None,
state_key: Some(replacement_room.to_string()),
redacts: None,
},
sender_user,
&replacement_room,
&state_lock,
)
.await?;
}
}
} }
// m.room.create
services services
.rooms .rooms
.timeline .timeline
@@ -822,11 +758,11 @@ pub(crate) async fn upgrade_room_route(
.rooms .rooms
.state_accessor .state_accessor
.room_state_get(&body.room_id, &StateEventType::RoomPowerLevels, "")? .room_state_get(&body.room_id, &StateEventType::RoomPowerLevels, "")?
.ok_or_else(|| err!(Database(error!("Found room without m.room.create event."))))? .ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.content .content
.get(), .get(),
) )
.map_err(|_| err!(Database(error!("Invalid room event in database."))))?; .map_err(|_| Error::bad_database("Invalid room event in database."))?;
// Setting events_default and invite to the greater of 50 and users_default + 1 // Setting events_default and invite to the greater of 50 and users_default + 1
let new_level = max( let new_level = max(
@@ -834,7 +770,9 @@ pub(crate) async fn upgrade_room_route(
power_levels_event_content power_levels_event_content
.users_default .users_default
.checked_add(int!(1)) .checked_add(int!(1))
.ok_or_else(|| err!(Request(BadJson("users_default power levels event content is not valid"))))?, .ok_or_else(|| {
Error::BadRequest(ErrorKind::BadJson, "users_default power levels event content is not valid")
})?,
); );
power_levels_event_content.events_default = new_level; power_levels_event_content.events_default = new_level;
power_levels_event_content.invite = new_level; power_levels_event_content.invite = new_level;
@@ -898,7 +836,7 @@ fn default_power_levels_content(
if let Some(power_level_content_override) = power_level_content_override { if let Some(power_level_content_override) = power_level_content_override {
let json: JsonObject = serde_json::from_str(power_level_content_override.json().get()) let json: JsonObject = serde_json::from_str(power_level_content_override.json().get())
.map_err(|_| err!(Request(BadJson("Invalid power_level_content_override"))))?; .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid power_level_content_override."))?;
for (key, value) in json { for (key, value) in json {
power_levels_content[key] = value; power_levels_content[key] = value;
+6 -15
View File
@@ -1,5 +1,4 @@
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use ruma::{ use ruma::{
api::client::{ api::client::{
error::ErrorKind, error::ErrorKind,
@@ -57,9 +56,8 @@ pub(crate) async fn get_login_types_route(
/// Note: You can use [`GET /// Note: You can use [`GET
/// /_matrix/client/r0/login`](fn.get_supported_versions_route.html) to see /// /_matrix/client/r0/login`](fn.get_supported_versions_route.html) to see
/// supported login types. /// supported login types.
#[tracing::instrument(skip_all, fields(%client), name = "login")]
pub(crate) async fn login_route( pub(crate) async fn login_route(
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp, body: Ruma<login::v3::Request>, State(services): State<crate::State>, body: Ruma<login::v3::Request>,
) -> Result<login::v3::Response> { ) -> Result<login::v3::Response> {
// Validate login method // Validate login method
// TODO: Other login methods // TODO: Other login methods
@@ -178,13 +176,9 @@ pub(crate) async fn login_route(
if device_exists { if device_exists {
services.users.set_token(&user_id, &device_id, &token)?; services.users.set_token(&user_id, &device_id, &token)?;
} else { } else {
services.users.create_device( services
&user_id, .users
&device_id, .create_device(&user_id, &device_id, &token, body.initial_device_display_name.clone())?;
&token,
body.initial_device_display_name.clone(),
Some(client.to_string()),
)?;
} }
// send client well-known if specified so the client knows to reconfigure itself // send client well-known if specified so the client knows to reconfigure itself
@@ -220,9 +214,8 @@ pub(crate) async fn login_route(
/// last seen ts) /// last seen ts)
/// - Forgets to-device events /// - Forgets to-device events
/// - Triggers device list updates /// - Triggers device list updates
#[tracing::instrument(skip_all, fields(%client), name = "logout")]
pub(crate) async fn logout_route( pub(crate) async fn logout_route(
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp, body: Ruma<logout::v3::Request>, State(services): State<crate::State>, body: Ruma<logout::v3::Request>,
) -> Result<logout::v3::Response> { ) -> Result<logout::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let sender_device = body.sender_device.as_ref().expect("user is authenticated"); let sender_device = body.sender_device.as_ref().expect("user is authenticated");
@@ -248,10 +241,8 @@ pub(crate) async fn logout_route(
/// Note: This is equivalent to calling [`GET /// Note: This is equivalent to calling [`GET
/// /_matrix/client/r0/logout`](fn.logout_route.html) from each device of this /// /_matrix/client/r0/logout`](fn.logout_route.html) from each device of this
/// user. /// user.
#[tracing::instrument(skip_all, fields(%client), name = "logout")]
pub(crate) async fn logout_all_route( pub(crate) async fn logout_all_route(
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp, State(services): State<crate::State>, body: Ruma<logout_all::v3::Request>,
body: Ruma<logout_all::v3::Request>,
) -> Result<logout_all::v3::Response> { ) -> Result<logout_all::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
+3 -5
View File
@@ -106,13 +106,11 @@ pub(crate) async fn sync_events_route(
.unwrap_or_default(), .unwrap_or_default(),
}; };
// some clients, at least element, seem to require knowledge of redundant
// members for "inline" profiles on the timeline to work properly
let (lazy_load_enabled, lazy_load_send_redundant) = match filter.room.state.lazy_load_options { let (lazy_load_enabled, lazy_load_send_redundant) = match filter.room.state.lazy_load_options {
LazyLoadOptions::Enabled { LazyLoadOptions::Enabled {
include_redundant_members, include_redundant_members: redundant,
} => (true, include_redundant_members), } => (true, redundant),
LazyLoadOptions::Disabled => (false, cfg!(feature = "element_hacks")), LazyLoadOptions::Disabled => (false, false),
}; };
let full_state = body.full_state; let full_state = body.full_state;
+1 -6
View File
@@ -2,7 +2,7 @@ use std::time::{Duration, SystemTime};
use axum::extract::State; use axum::extract::State;
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use conduit::{utils, Err}; use conduit::utils;
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use ruma::{api::client::voip::get_turn_server_info, SecondsSinceUnixEpoch, UserId}; use ruma::{api::client::voip::get_turn_server_info, SecondsSinceUnixEpoch, UserId};
use sha1::Sha1; use sha1::Sha1;
@@ -19,11 +19,6 @@ type HmacSha1 = Hmac<Sha1>;
pub(crate) async fn turn_server_route( pub(crate) async fn turn_server_route(
State(services): State<crate::State>, body: Ruma<get_turn_server_info::v3::Request>, State(services): State<crate::State>, body: Ruma<get_turn_server_info::v3::Request>,
) -> Result<get_turn_server_info::v3::Response> { ) -> Result<get_turn_server_info::v3::Response> {
// MSC4166: return M_NOT_FOUND 404 if no TURN URIs are specified in any way
if services.server.config.turn_uris.is_empty() {
return Err!(Request(NotFound("Not Found")));
}
let turn_secret = services.globals.turn_secret().clone(); let turn_secret = services.globals.turn_secret().clone();
let (username, password) = if !turn_secret.is_empty() { let (username, password) = if !turn_secret.is_empty() {
+2 -13
View File
@@ -6,7 +6,7 @@ use axum_extra::{
typed_header::TypedHeaderRejectionReason, typed_header::TypedHeaderRejectionReason,
TypedHeader, TypedHeader,
}; };
use conduit::{debug_info, warn, Err, Error, Result}; use conduit::{warn, Err, Error, Result};
use http::uri::PathAndQuery; use http::uri::PathAndQuery;
use ruma::{ use ruma::{
api::{client::error::ErrorKind, AuthScheme, Metadata}, api::{client::error::ErrorKind, AuthScheme, Metadata},
@@ -185,7 +185,7 @@ fn auth_appservice(services: &Services, request: &Request, info: Box<Registratio
async fn auth_server( async fn auth_server(
services: &Services, request: &mut Request, json_body: &Option<CanonicalJsonValue>, services: &Services, request: &mut Request, json_body: &Option<CanonicalJsonValue>,
) -> Result<Auth> { ) -> Result<Auth> {
if !services.server.config.allow_federation { if !services.globals.allow_federation() {
return Err!(Config("allow_federation", "Federation is disabled.")); return Err!(Config("allow_federation", "Federation is disabled."));
} }
@@ -206,17 +206,6 @@ async fn auth_server(
})?; })?;
let origin = &x_matrix.origin; let origin = &x_matrix.origin;
if services
.server
.config
.forbidden_remote_server_names
.contains(origin)
{
debug_info!("Refusing to accept inbound federation request to {origin}");
return Err!(Request(Forbidden("Federation with this homeserver is not allowed.")));
}
let signatures = let signatures =
BTreeMap::from_iter([(x_matrix.key.clone(), CanonicalJsonValue::String(x_matrix.sig.to_string()))]); BTreeMap::from_iter([(x_matrix.key.clone(), CanonicalJsonValue::String(x_matrix.sig.to_string()))]);
let signatures = BTreeMap::from_iter([( let signatures = BTreeMap::from_iter([(
+2 -2
View File
@@ -1,7 +1,7 @@
use std::ffi::OsStr; use std::ffi::OsStr;
use super::{path, Library}; use super::{path, Library};
use crate::{Err, Result}; use crate::{Error, Result};
const OPEN_FLAGS: i32 = libloading::os::unix::RTLD_LAZY | libloading::os::unix::RTLD_GLOBAL; const OPEN_FLAGS: i32 = libloading::os::unix::RTLD_LAZY | libloading::os::unix::RTLD_GLOBAL;
@@ -16,7 +16,7 @@ pub fn from_path(path: &OsStr) -> Result<Library> {
let lib = unsafe { Library::open(Some(path), OPEN_FLAGS) }; let lib = unsafe { Library::open(Some(path), OPEN_FLAGS) };
if let Err(e) = lib { if let Err(e) = lib {
let name = path::to_name(path)?; let name = path::to_name(path)?;
return Err!("Loading module {name:?} failed: {e}"); return Err(Error::Err(format!("Loading module {name:?} failed: {e}")));
} }
Ok(lib.expect("module loaded")) Ok(lib.expect("module loaded"))
+1 -1
View File
@@ -119,7 +119,7 @@ impl PduEvent {
// deliberately allowing for the possibility of negative age // deliberately allowing for the possibility of negative age
let now: i128 = MilliSecondsSinceUnixEpoch::now().get().into(); let now: i128 = MilliSecondsSinceUnixEpoch::now().get().into();
let then: i128 = self.origin_server_ts.into(); let then: i128 = self.origin_server_ts.into();
let this_age = now.saturating_sub(then); let this_age: i128 = now.saturating_sub(then);
unsigned.insert("age".to_owned(), to_raw_value(&this_age).unwrap()); unsigned.insert("age".to_owned(), to_raw_value(&this_age).unwrap());
self.unsigned = Some(to_raw_value(&unsigned).expect("unsigned is valid")); self.unsigned = Some(to_raw_value(&unsigned).expect("unsigned is valid"));
+5 -19
View File
@@ -1,11 +1,10 @@
use std::{ use std::{
collections::{BTreeSet, HashMap}, collections::{BTreeSet, HashMap},
fmt::Write, fmt::Write,
path::PathBuf,
sync::{atomic::AtomicU32, Arc, Mutex, RwLock}, sync::{atomic::AtomicU32, Arc, Mutex, RwLock},
}; };
use conduit::{debug, error, info, utils::time::rfc2822_from_seconds, warn, Err, Result, Server}; use conduit::{debug, error, info, utils::time::rfc2822_from_seconds, warn, Result, Server};
use rocksdb::{ use rocksdb::{
backup::{BackupEngine, BackupEngineOptions}, backup::{BackupEngine, BackupEngineOptions},
perf::get_memory_usage_stats, perf::get_memory_usage_stats,
@@ -51,7 +50,10 @@ impl Engine {
let load_time = std::time::Instant::now(); let load_time = std::time::Instant::now();
if config.rocksdb_repair { if config.rocksdb_repair {
repair(&db_opts, &config.database_path)?; warn!("Starting database repair. This may take a long time...");
if let Err(e) = Db::repair(&db_opts, &config.database_path) {
error!("Repair failed: {e:?}");
}
} }
debug!("Listing column families in database"); debug!("Listing column families in database");
@@ -75,7 +77,6 @@ impl Engine {
let db = res.or_else(or_else)?; let db = res.or_else(or_else)?;
info!( info!(
columns = cfs.len(),
sequence = %db.latest_sequence_number(), sequence = %db.latest_sequence_number(),
time = ?load_time.elapsed(), time = ?load_time.elapsed(),
"Opened database." "Opened database."
@@ -242,16 +243,6 @@ impl Engine {
} }
} }
pub(crate) fn repair(db_opts: &Options, path: &PathBuf) -> Result<()> {
warn!("Starting database repair. This may take a long time...");
match Db::repair(db_opts, path) {
Ok(()) => info!("Database repair successful."),
Err(e) => return Err!("Repair failed: {e:?}"),
}
Ok(())
}
impl Drop for Engine { impl Drop for Engine {
#[cold] #[cold]
fn drop(&mut self) { fn drop(&mut self) {
@@ -268,10 +259,5 @@ impl Drop for Engine {
debug!("Joining background threads..."); debug!("Joining background threads...");
self.env.join_all_threads(); self.env.join_all_threads();
info!(
sequence = %self.db.latest_sequence_number(),
"Closing database..."
);
} }
} }
+2 -4
View File
@@ -9,13 +9,11 @@ pub(super) fn flags_capture(args: TokenStream) -> TokenStream {
}; };
let flag = std::env::args().collect::<Vec<_>>(); let flag = std::env::args().collect::<Vec<_>>();
let flag_len = flag.len();
let ret = quote! { let ret = quote! {
pub static RUSTC_FLAGS: [&str; #flag_len] = [#( #flag ),*];
#[conduit_core::ctor] #[conduit_core::ctor]
fn _set_rustc_flags() { fn _set_rustc_flags() {
conduit_core::info::rustc::FLAGS.lock().expect("locked").insert(#crate_name, &RUSTC_FLAGS); let flags = &[#( #flag ),*];
conduit_core::info::rustc::FLAGS.lock().expect("locked").insert(#crate_name, flags);
} }
// static strings have to be yanked on module unload // static strings have to be yanked on module unload
+13 -41
View File
@@ -1,27 +1,18 @@
#![cfg(conduit_mods)] #![cfg(conduit_mods)]
#[no_link]
extern crate conduit_service;
use std::{ use std::{
future::Future, future::Future,
pin::Pin, pin::Pin,
sync::{atomic::Ordering, Arc}, sync::{atomic::Ordering, Arc},
}; };
use conduit::{debug, error, mods, Error, Result}; use conduit::{mods, Error, Result};
use conduit_service::Services; use tracing::{debug, error};
use crate::Server; use crate::Server;
type StartFuncResult = Pin<Box<dyn Future<Output = Result<Arc<Services>>> + Send>>; type RunFuncResult = Pin<Box<dyn Future<Output = Result<(), Error>>>>;
type StartFuncProto = fn(&Arc<conduit::Server>) -> StartFuncResult; type RunFuncProto = fn(&Arc<conduit::Server>) -> RunFuncResult;
type RunFuncResult = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type RunFuncProto = fn(&Arc<Services>) -> RunFuncResult;
type StopFuncResult = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
type StopFuncProto = fn(Arc<Services>) -> StopFuncResult;
const RESTART_THRESH: &str = "conduit_service"; const RESTART_THRESH: &str = "conduit_service";
const MODULE_NAMES: &[&str] = &[ const MODULE_NAMES: &[&str] = &[
@@ -42,25 +33,15 @@ pub(crate) async fn run(server: &Arc<Server>, starts: bool) -> Result<(bool, boo
let main_lock = server.mods.read().await; let main_lock = server.mods.read().await;
let main_mod = (*main_lock).last().expect("main module loaded"); let main_mod = (*main_lock).last().expect("main module loaded");
if starts { if starts {
let start = main_mod.get::<StartFuncProto>("start")?; let start = main_mod.get::<RunFuncProto>("start")?;
match start(&server.server).await { if let Err(error) = start(&server.server).await {
Ok(services) => server.services.lock().await.insert(services), error!("Starting server: {error}");
Err(error) => { return Err(error);
error!("Starting server: {error}"); }
return Err(error);
},
};
} }
server.server.stopping.store(false, Ordering::Release); server.server.stopping.store(false, Ordering::Release);
let run = main_mod.get::<RunFuncProto>("run")?; let run = main_mod.get::<RunFuncProto>("run")?;
if let Err(error) = run(server if let Err(error) = run(&server.server).await {
.services
.lock()
.await
.as_ref()
.expect("services initialized"))
.await
{
error!("Running server: {error}"); error!("Running server: {error}");
return Err(error); return Err(error);
} }
@@ -68,17 +49,8 @@ pub(crate) async fn run(server: &Arc<Server>, starts: bool) -> Result<(bool, boo
let stops = !reloads || stale(server).await? <= restart_thresh(); let stops = !reloads || stale(server).await? <= restart_thresh();
let starts = reloads && stops; let starts = reloads && stops;
if stops { if stops {
let stop = main_mod.get::<StopFuncProto>("stop")?; let stop = main_mod.get::<RunFuncProto>("stop")?;
if let Err(error) = stop( if let Err(error) = stop(&server.server).await {
server
.services
.lock()
.await
.take()
.expect("services initialized"),
)
.await
{
error!("Stopping server: {error}"); error!("Stopping server: {error}");
return Err(error); return Err(error);
} }
@@ -131,7 +103,7 @@ pub(crate) async fn close(server: &Arc<Server>, force: bool) -> Result<usize, Er
async fn stale_count(server: &Arc<Server>) -> usize { async fn stale_count(server: &Arc<Server>) -> usize {
let watermark = stale(server).await.unwrap_or(available()); let watermark = stale(server).await.unwrap_or(available());
available().saturating_sub(watermark) available() - watermark
} }
async fn stale(server: &Arc<Server>) -> Result<usize, Error> { async fn stale(server: &Arc<Server>) -> Result<usize, Error> {
+5 -14
View File
@@ -5,7 +5,7 @@ mod grant;
use std::{ use std::{
future::Future, future::Future,
pin::Pin, pin::Pin,
sync::{Arc, RwLock as StdRwLock, Weak}, sync::{Arc, RwLock as StdRwLock},
}; };
use async_trait::async_trait; use async_trait::async_trait;
@@ -41,7 +41,7 @@ struct Services {
timeline: Dep<rooms::timeline::Service>, timeline: Dep<rooms::timeline::Service>,
state: Dep<rooms::state::Service>, state: Dep<rooms::state::Service>,
state_cache: Dep<rooms::state_cache::Service>, state_cache: Dep<rooms::state_cache::Service>,
services: StdRwLock<Option<Weak<crate::Services>>>, services: StdRwLock<Option<Arc<crate::Services>>>,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -174,14 +174,7 @@ impl Service {
} }
async fn process_command(&self, command: CommandInput) -> CommandResult { async fn process_command(&self, command: CommandInput) -> CommandResult {
let Some(services) = self let Some(services) = self.services.services.read().expect("locked").clone() else {
.services
.services
.read()
.expect("locked")
.as_ref()
.and_then(Weak::upgrade)
else {
return Err!("Services self-reference not initialized."); return Err!("Services self-reference not initialized.");
}; };
@@ -372,9 +365,7 @@ impl Service {
/// Sets the self-reference to crate::Services which will provide context to /// Sets the self-reference to crate::Services which will provide context to
/// the admin commands. /// the admin commands.
pub(super) fn set_services(&self, services: &Option<Arc<crate::Services>>) { pub(super) fn set_services(&self, services: Option<Arc<crate::Services>>) {
let receiver = &mut *self.services.services.write().expect("locked for writing"); *self.services.services.write().expect("locked for writing") = services;
let weak = services.as_ref().map(Arc::downgrade);
*receiver = weak;
} }
} }
+1 -2
View File
@@ -60,8 +60,7 @@ impl Manager {
.read() .read()
.expect("locked for reading") .expect("locked for reading")
.values() .values()
.map(|val| val.0.upgrade()) .map(|v| v.0.clone())
.map(|arc| arc.expect("services available for manager startup"))
.collect(); .collect();
debug!("Starting service workers..."); debug!("Starting service workers...");
+4 -21
View File
@@ -4,8 +4,7 @@ use conduit::{debug_warn, utils, Error, Result};
use database::Map; use database::Map;
use ruma::{events::presence::PresenceEvent, presence::PresenceState, OwnedUserId, UInt, UserId}; use ruma::{events::presence::PresenceEvent, presence::PresenceState, OwnedUserId, UInt, UserId};
use super::Presence; use crate::{globals, presence::Presence, users, Dep};
use crate::{globals, users, Dep};
pub struct Data { pub struct Data {
presenceid_presence: Arc<Map>, presenceid_presence: Arc<Map>,
@@ -61,22 +60,6 @@ impl Data {
Some(ref presence) => presence.1.content.presence != *presence_state, Some(ref presence) => presence.1.content.presence != *presence_state,
}; };
let status_msg_changed = match last_presence {
None => true,
Some(ref last_presence) => {
let old_msg = last_presence
.1
.content
.status_msg
.clone()
.unwrap_or_default();
let new_msg = status_msg.clone().unwrap_or_default();
new_msg != old_msg
},
};
let now = utils::millis_since_unix_epoch(); let now = utils::millis_since_unix_epoch();
let last_last_active_ts = match last_presence { let last_last_active_ts = match last_presence {
None => 0, None => 0,
@@ -88,10 +71,10 @@ impl Data {
Some(last_active_ago) => now.saturating_sub(last_active_ago.into()), Some(last_active_ago) => now.saturating_sub(last_active_ago.into()),
}; };
// TODO: tighten for state flicker? // tighten for state flicker?
if !status_msg_changed && !state_changed && last_active_ts < last_last_active_ts { if !state_changed && last_active_ts <= last_last_active_ts {
debug_warn!( debug_warn!(
"presence spam {:?} last_active_ts:{:?} < {:?}", "presence spam {:?} last_active_ts:{:?} <= {:?}",
user_id, user_id,
last_active_ts, last_active_ts,
last_last_active_ts last_last_active_ts
+70 -16
View File
@@ -1,25 +1,81 @@
mod data; mod data;
mod presence;
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use async_trait::async_trait; use async_trait::async_trait;
use conduit::{checked, debug, error, Error, Result, Server}; use conduit::{checked, debug, error, utils, Error, Result, Server};
use futures_util::{stream::FuturesUnordered, StreamExt}; use futures_util::{stream::FuturesUnordered, StreamExt};
use ruma::{events::presence::PresenceEvent, presence::PresenceState, OwnedUserId, UInt, UserId}; use ruma::{
events::presence::{PresenceEvent, PresenceEventContent},
presence::PresenceState,
OwnedUserId, UInt, UserId,
};
use serde::{Deserialize, Serialize};
use tokio::{sync::Mutex, time::sleep}; use tokio::{sync::Mutex, time::sleep};
use self::{data::Data, presence::Presence}; use self::data::Data;
use crate::{globals, users, Dep}; use crate::{globals, users, Dep};
/// Represents data required to be kept in order to implement the presence
/// specification.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Presence {
state: PresenceState,
currently_active: bool,
last_active_ts: u64,
status_msg: Option<String>,
}
impl Presence {
#[must_use]
pub fn new(state: PresenceState, currently_active: bool, last_active_ts: u64, status_msg: Option<String>) -> Self {
Self {
state,
currently_active,
last_active_ts,
status_msg,
}
}
pub fn from_json_bytes(bytes: &[u8]) -> Result<Self> {
serde_json::from_slice(bytes).map_err(|_| Error::bad_database("Invalid presence data in database"))
}
pub fn to_json_bytes(&self) -> Result<Vec<u8>> {
serde_json::to_vec(self).map_err(|_| Error::bad_database("Could not serialize Presence to JSON"))
}
/// Creates a PresenceEvent from available data.
pub fn to_presence_event(&self, user_id: &UserId, users: &users::Service) -> Result<PresenceEvent> {
let now = utils::millis_since_unix_epoch();
let last_active_ago = if self.currently_active {
None
} else {
Some(UInt::new_saturating(now.saturating_sub(self.last_active_ts)))
};
Ok(PresenceEvent {
sender: user_id.to_owned(),
content: PresenceEventContent {
presence: self.state.clone(),
status_msg: self.status_msg.clone(),
currently_active: Some(self.currently_active),
last_active_ago,
displayname: users.displayname(user_id)?,
avatar_url: users.avatar_url(user_id)?,
},
})
}
}
pub struct Service { pub struct Service {
timer_sender: loole::Sender<TimerType>, services: Services,
timer_receiver: Mutex<loole::Receiver<TimerType>>, pub db: Data,
pub timer_sender: loole::Sender<(OwnedUserId, Duration)>,
timer_receiver: Mutex<loole::Receiver<(OwnedUserId, Duration)>>,
timeout_remote_users: bool, timeout_remote_users: bool,
idle_timeout: u64, idle_timeout: u64,
offline_timeout: u64, offline_timeout: u64,
pub db: Data,
services: Services,
} }
struct Services { struct Services {
@@ -28,8 +84,6 @@ struct Services {
users: Dep<users::Service>, users: Dep<users::Service>,
} }
type TimerType = (OwnedUserId, Duration);
#[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>> {
@@ -38,17 +92,17 @@ impl crate::Service for Service {
let offline_timeout_s = config.presence_offline_timeout_s; let offline_timeout_s = config.presence_offline_timeout_s;
let (timer_sender, timer_receiver) = loole::unbounded(); let (timer_sender, timer_receiver) = loole::unbounded();
Ok(Arc::new(Self { Ok(Arc::new(Self {
timer_sender,
timer_receiver: Mutex::new(timer_receiver),
timeout_remote_users: config.presence_timeout_remote_users,
idle_timeout: checked!(idle_timeout_s * 1_000)?,
offline_timeout: checked!(offline_timeout_s * 1_000)?,
db: Data::new(&args),
services: Services { services: Services {
server: args.server.clone(), server: args.server.clone(),
globals: args.depend::<globals::Service>("globals"), globals: args.depend::<globals::Service>("globals"),
users: args.depend::<users::Service>("users"), users: args.depend::<users::Service>("users"),
}, },
db: Data::new(&args),
timer_sender,
timer_receiver: Mutex::new(timer_receiver),
timeout_remote_users: config.presence_timeout_remote_users,
idle_timeout: checked!(idle_timeout_s * 1_000)?,
offline_timeout: checked!(offline_timeout_s * 1_000)?,
})) }))
} }
-65
View File
@@ -1,65 +0,0 @@
use std::sync::Arc;
use conduit::{utils, Error, Result};
use ruma::{
events::presence::{PresenceEvent, PresenceEventContent},
presence::PresenceState,
UInt, UserId,
};
use serde::{Deserialize, Serialize};
use crate::users;
/// Represents data required to be kept in order to implement the presence
/// specification.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub(super) struct Presence {
state: PresenceState,
currently_active: bool,
last_active_ts: u64,
status_msg: Option<String>,
}
impl Presence {
#[must_use]
pub(super) fn new(
state: PresenceState, currently_active: bool, last_active_ts: u64, status_msg: Option<String>,
) -> Self {
Self {
state,
currently_active,
last_active_ts,
status_msg,
}
}
pub(super) fn from_json_bytes(bytes: &[u8]) -> Result<Self> {
serde_json::from_slice(bytes).map_err(|_| Error::bad_database("Invalid presence data in database"))
}
pub(super) fn to_json_bytes(&self) -> Result<Vec<u8>> {
serde_json::to_vec(self).map_err(|_| Error::bad_database("Could not serialize Presence to JSON"))
}
/// Creates a PresenceEvent from available data.
pub(super) fn to_presence_event(&self, user_id: &UserId, users: &Arc<users::Service>) -> Result<PresenceEvent> {
let now = utils::millis_since_unix_epoch();
let last_active_ago = if self.currently_active {
None
} else {
Some(UInt::new_saturating(now.saturating_sub(self.last_active_ts)))
};
Ok(PresenceEvent {
sender: user_id.to_owned(),
content: PresenceEventContent {
presence: self.state.clone(),
status_msg: self.status_msg.clone(),
currently_active: Some(self.currently_active),
last_active_ago,
displayname: users.displayname(user_id)?,
avatar_url: users.avatar_url(user_id)?,
},
})
}
}
+1 -1
View File
@@ -189,7 +189,7 @@ impl super::Service {
.services .services
.client .client
.well_known .well_known
.get(format!("https://{dest}/.well-known/matrix/server")) .get(&format!("https://{dest}/.well-known/matrix/server"))
.send() .send()
.await; .await;
+4 -6
View File
@@ -12,19 +12,17 @@ use ruma::{DeviceId, OwnedDeviceId, OwnedRoomId, OwnedUserId, RoomId, UserId};
use self::data::Data; use self::data::Data;
pub struct Service { pub struct Service {
pub lazy_load_waiting: Mutex<LazyLoadWaiting>,
db: Data, db: Data,
}
type LazyLoadWaiting = HashMap<LazyLoadWaitingKey, LazyLoadWaitingVal>; #[allow(clippy::type_complexity)]
type LazyLoadWaitingKey = (OwnedUserId, OwnedDeviceId, OwnedRoomId, PduCount); pub lazy_load_waiting: Mutex<HashMap<(OwnedUserId, OwnedDeviceId, OwnedRoomId, PduCount), HashSet<OwnedUserId>>>,
type LazyLoadWaitingVal = HashSet<OwnedUserId>; }
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>> {
Ok(Arc::new(Self { Ok(Arc::new(Self {
lazy_load_waiting: Mutex::new(HashMap::new()),
db: Data::new(args.db), db: Data::new(args.db),
lazy_load_waiting: Mutex::new(HashMap::new()),
})) }))
} }
+1 -12
View File
@@ -1,8 +1,7 @@
use std::{fmt::Debug, mem}; use std::{fmt::Debug, mem};
use conduit::{ use conduit::{
debug, debug_error, debug_info, debug_warn, error::inspect_debug_log, trace, utils::string::EMPTY, Err, Error, debug, debug_error, debug_warn, error::inspect_debug_log, trace, utils::string::EMPTY, Err, Error, Result,
Result,
}; };
use http::{header::AUTHORIZATION, HeaderValue}; use http::{header::AUTHORIZATION, HeaderValue};
use ipaddress::IPAddress; use ipaddress::IPAddress;
@@ -32,16 +31,6 @@ impl super::Service {
return Err!(Config("allow_federation", "Federation is disabled.")); return Err!(Config("allow_federation", "Federation is disabled."));
} }
if self
.server
.config
.forbidden_remote_server_names
.contains(&dest.to_owned())
{
debug_info!("Refusing to send outbound federation request to {dest}");
return Err!(Request(Forbidden("Federation with this homeserver is not allowed.")));
}
let actual = self.services.resolver.get_actual_dest(dest).await?; let actual = self.services.resolver.get_actual_dest(dest).await?;
let request = self.prepare::<T>(dest, &actual, req).await?; let request = self.prepare::<T>(dest, &actual, req).await?;
self.execute::<T>(dest, &actual, request, client).await self.execute::<T>(dest, &actual, request, client).await
+32 -47
View File
@@ -3,7 +3,7 @@ use std::{
collections::BTreeMap, collections::BTreeMap,
fmt::Write, fmt::Write,
ops::Deref, ops::Deref,
sync::{Arc, OnceLock, RwLock, Weak}, sync::{Arc, OnceLock, RwLock},
}; };
use async_trait::async_trait; use async_trait::async_trait;
@@ -53,92 +53,77 @@ pub(crate) struct Args<'a> {
/// Circular-dependencies between services require this indirection. /// Circular-dependencies between services require this indirection.
pub(crate) struct Dep<T> { pub(crate) struct Dep<T> {
dep: OnceLock<Arc<T>>, dep: OnceLock<Arc<T>>,
service: Weak<Map>, service: Arc<Map>,
name: &'static str, name: &'static str,
} }
pub(crate) type Map = RwLock<MapType>; pub(crate) type Map = RwLock<BTreeMap<String, MapVal>>;
pub(crate) type MapType = BTreeMap<MapKey, MapVal>; pub(crate) type MapVal = (Arc<dyn Service>, Arc<dyn Any + Send + Sync>);
pub(crate) type MapVal = (Weak<dyn Service>, Weak<dyn Any + Send + Sync>);
pub(crate) type MapKey = String;
impl<T: Send + Sync + 'static> Deref for Dep<T> { impl<T: Send + Sync + 'static> Deref for Dep<T> {
type Target = Arc<T>; type Target = Arc<T>;
/// Dereference a dependency. The dependency must be ready or panics. /// Dereference a dependency. The dependency must be ready or panics.
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
self.dep.get_or_init(|| { self.dep
let service = self .get_or_init(|| require::<T>(&self.service, self.name))
.service
.upgrade()
.expect("services map exists for dependency initialization.");
require::<T>(&service, self.name)
})
} }
} }
impl<'a> Args<'a> { impl Args<'_> {
/// Create a lazy-reference to a service when constructing another Service. /// Create a lazy-reference to a service when constructing another Service.
pub(crate) fn depend<T: Send + Sync + 'a + 'static>(&'a self, name: &'static str) -> Dep<T> { pub(crate) fn depend<T: Send + Sync + 'static>(&self, name: &'static str) -> Dep<T> {
Dep::<T> { Dep::<T> {
dep: OnceLock::new(), dep: OnceLock::new(),
service: Arc::downgrade(self.service), service: self.service.clone(),
name, name,
} }
} }
/// Create a reference immediately to a service when constructing another /// Create a reference immediately to a service when constructing another
/// Service. The other service must be constructed. /// Service. The other service must be constructed.
pub(crate) fn require<T: Send + Sync + 'a + 'static>(&'a self, name: &'static str) -> Arc<T> { pub(crate) fn require<T: Send + Sync + 'static>(&self, name: &str) -> Arc<T> { require::<T>(self.service, name) }
require::<T>(self.service, name)
}
} }
/// Reference a Service by name. Panics if the Service does not exist or was /// Reference a Service by name. Panics if the Service does not exist or was
/// incorrectly cast. /// incorrectly cast.
pub(crate) fn require<'a, 'b, T: Send + Sync + 'a + 'b + 'static>(map: &'b Map, name: &'a str) -> Arc<T> { pub(crate) fn require<T: Send + Sync + 'static>(map: &Map, name: &str) -> Arc<T> {
try_get::<T>(map, name) try_get::<T>(map, name)
.inspect_err(inspect_log) .inspect_err(inspect_log)
.expect("Failure to reference service required by another service.") .expect("Failure to reference service required by another service.")
} }
/// Reference a Service by name. Returns Err if the Service does not exist or
/// was incorrectly cast.
pub(crate) fn try_get<T: Send + Sync + 'static>(map: &Map, name: &str) -> Result<Arc<T>> {
map.read()
.expect("locked for reading")
.get(name)
.map_or_else(
|| Err!("Service {name:?} does not exist or has not been built yet."),
|(_, s)| {
s.clone()
.downcast::<T>()
.map_err(|_| err!("Service {name:?} must be correctly downcast."))
},
)
}
/// Reference a Service by name. Returns None if the Service does not exist, but /// Reference a Service by name. Returns None if the Service does not exist, but
/// panics if incorrectly cast. /// panics if incorrectly cast.
/// ///
/// # Panics /// # Panics
/// Incorrect type is not a silent failure (None) as the type never has a reason /// Incorrect type is not a silent failure (None) as the type never has a reason
/// to be incorrect. /// to be incorrect.
pub(crate) fn get<'a, 'b, T: Send + Sync + 'a + 'b + 'static>(map: &'b Map, name: &'a str) -> Option<Arc<T>> { pub(crate) fn get<T: Send + Sync + 'static>(map: &Map, name: &str) -> Option<Arc<T>> {
map.read() map.read()
.expect("locked for reading") .expect("locked for reading")
.get(name) .get(name)
.map(|(_, s)| { .map(|(_, s)| {
s.upgrade().map(|s| { s.clone()
s.downcast::<T>() .downcast::<T>()
.expect("Service must be correctly downcast.") .expect("Service must be correctly downcast.")
}) })
})?
}
/// Reference a Service by name. Returns Err if the Service does not exist or
/// was incorrectly cast.
pub(crate) fn try_get<'a, 'b, T: Send + Sync + 'a + 'b + 'static>(map: &'b Map, name: &'a str) -> Result<Arc<T>> {
map.read()
.expect("locked for reading")
.get(name)
.map_or_else(
|| Err!("Service {name:?} does not exist or has not been built yet."),
|(_, s)| {
s.upgrade().map_or_else(
|| Err!("Service {name:?} no longer exists."),
|s| {
s.downcast::<T>()
.map_err(|_| err!("Service {name:?} must be correctly downcast."))
},
)
},
)
} }
/// Utility for service implementations; see Service::name() in the trait. /// Utility for service implementations; see Service::name() in the trait.
+11 -18
View File
@@ -109,7 +109,7 @@ impl Services {
pub async fn start(self: &Arc<Self>) -> Result<Arc<Self>> { pub async fn start(self: &Arc<Self>) -> Result<Arc<Self>> {
debug_info!("Starting services..."); debug_info!("Starting services...");
self.admin.set_services(&Some(Arc::clone(self))); self.admin.set_services(Some(Arc::clone(self)));
globals::migrations::migrations(self).await?; globals::migrations::migrations(self).await?;
self.manager self.manager
.lock() .lock()
@@ -131,7 +131,7 @@ impl Services {
manager.stop().await; manager.stop().await;
} }
self.admin.set_services(&None); self.admin.set_services(None);
debug_info!("Services shutdown complete."); debug_info!("Services shutdown complete.");
} }
@@ -146,9 +146,7 @@ impl Services {
pub async fn clear_cache(&self) { pub async fn clear_cache(&self) {
for (service, ..) in self.service.read().expect("locked for reading").values() { for (service, ..) in self.service.read().expect("locked for reading").values() {
if let Some(service) = service.upgrade() { service.clear_cache();
service.clear_cache();
}
} }
//TODO //TODO
@@ -163,9 +161,7 @@ impl Services {
pub async fn memory_usage(&self) -> Result<String> { pub async fn memory_usage(&self) -> Result<String> {
let mut out = String::new(); let mut out = String::new();
for (service, ..) in self.service.read().expect("locked for reading").values() { for (service, ..) in self.service.read().expect("locked for reading").values() {
if let Some(service) = service.upgrade() { service.memory_usage(&mut out)?;
service.memory_usage(&mut out)?;
}
} }
//TODO //TODO
@@ -183,30 +179,27 @@ impl Services {
fn interrupt(&self) { fn interrupt(&self) {
debug!("Interrupting services..."); debug!("Interrupting services...");
for (name, (service, ..)) in self.service.read().expect("locked for reading").iter() { for (name, (service, ..)) in self.service.read().expect("locked for reading").iter() {
if let Some(service) = service.upgrade() { trace!("Interrupting {name}");
trace!("Interrupting {name}"); service.interrupt();
service.interrupt();
}
} }
} }
pub fn try_get<'a, 'b, T: Send + Sync + 'a + 'b + 'static>(&'b self, name: &'a str) -> Result<Arc<T>> { pub fn try_get<T: Send + Sync + 'static>(&self, name: &str) -> Result<Arc<T>> {
service::try_get::<T>(&self.service, name) service::try_get::<T>(&self.service, name)
} }
pub fn get<'a, 'b, T: Send + Sync + 'a + 'b + 'static>(&'b self, name: &'a str) -> Option<Arc<T>> { pub fn get<T: Send + Sync + 'static>(&self, name: &str) -> Option<Arc<T>> { service::get::<T>(&self.service, name) }
service::get::<T>(&self.service, name)
}
} }
#[allow(clippy::needless_pass_by_value)]
fn add_service(map: &Arc<Map>, s: Arc<dyn Service>, a: Arc<dyn Any + Send + Sync>) { fn add_service(map: &Arc<Map>, s: Arc<dyn Service>, a: Arc<dyn Any + Send + Sync>) {
let name = s.name(); let name = s.name();
let len = map.read().expect("locked for reading").len(); let len = map.read().expect("locked for reading").len();
trace!("built service #{len}: {name:?}"); trace!("built service #{len}: {name:?}");
map.write() map.write()
.expect("locked for writing") .expect("locked for writing")
.insert(name.to_owned(), (Arc::downgrade(&s), Arc::downgrade(&a))); .insert(name.to_owned(), (s, a));
} }
+1 -2
View File
@@ -246,7 +246,6 @@ impl Data {
/// Adds a new device to a user. /// Adds a new device to a user.
pub(super) fn create_device( pub(super) fn create_device(
&self, user_id: &UserId, device_id: &DeviceId, token: &str, initial_device_display_name: Option<String>, &self, user_id: &UserId, device_id: &DeviceId, token: &str, initial_device_display_name: Option<String>,
client_ip: Option<String>,
) -> Result<()> { ) -> Result<()> {
// This method should never be called for nonexistent users. We shouldn't assert // This method should never be called for nonexistent users. We shouldn't assert
// though... // though...
@@ -267,7 +266,7 @@ impl Data {
&serde_json::to_vec(&Device { &serde_json::to_vec(&Device {
device_id: device_id.into(), device_id: device_id.into(),
display_name: initial_device_display_name, display_name: initial_device_display_name,
last_seen_ip: client_ip, last_seen_ip: None, // TODO
last_seen_ts: Some(MilliSecondsSinceUnixEpoch::now()), last_seen_ts: Some(MilliSecondsSinceUnixEpoch::now()),
}) })
.expect("Device::to_string never fails."), .expect("Device::to_string never fails."),
+14 -17
View File
@@ -26,10 +26,19 @@ use ruma::{
use self::data::Data; use self::data::Data;
use crate::{admin, rooms, Dep}; use crate::{admin, rooms, Dep};
pub struct SlidingSyncCache {
lists: BTreeMap<String, SyncRequestList>,
subscriptions: BTreeMap<OwnedRoomId, sync_events::v4::RoomSubscription>,
known_rooms: BTreeMap<String, BTreeMap<OwnedRoomId, u64>>, // For every room, the roomsince number
extensions: ExtensionsConfig,
}
type DbConnections = Mutex<BTreeMap<(OwnedUserId, OwnedDeviceId, String), Arc<Mutex<SlidingSyncCache>>>>;
pub struct Service { pub struct Service {
connections: DbConnections,
pub db: Data,
services: Services, services: Services,
pub db: Data,
pub connections: DbConnections,
} }
struct Services { struct Services {
@@ -40,29 +49,18 @@ struct Services {
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>> {
Ok(Arc::new(Self { Ok(Arc::new(Self {
connections: StdMutex::new(BTreeMap::new()),
db: Data::new(&args),
services: Services { services: Services {
admin: args.depend::<admin::Service>("admin"), admin: args.depend::<admin::Service>("admin"),
state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"), state_cache: args.depend::<rooms::state_cache::Service>("rooms::state_cache"),
}, },
db: Data::new(&args),
connections: StdMutex::new(BTreeMap::new()),
})) }))
} }
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) } fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
} }
type DbConnections = Mutex<BTreeMap<DbConnectionsKey, DbConnectionsVal>>;
type DbConnectionsKey = (OwnedUserId, OwnedDeviceId, String);
type DbConnectionsVal = Arc<Mutex<SlidingSyncCache>>;
struct SlidingSyncCache {
lists: BTreeMap<String, SyncRequestList>,
subscriptions: BTreeMap<OwnedRoomId, sync_events::v4::RoomSubscription>,
known_rooms: BTreeMap<String, BTreeMap<OwnedRoomId, u64>>, // For every room, the roomsince number
extensions: ExtensionsConfig,
}
impl Service { impl Service {
/// Check if a user has an account on this homeserver. /// Check if a user has an account on this homeserver.
#[inline] #[inline]
@@ -328,10 +326,9 @@ impl Service {
/// Adds a new device to a user. /// Adds a new device to a user.
pub fn create_device( pub fn create_device(
&self, user_id: &UserId, device_id: &DeviceId, token: &str, initial_device_display_name: Option<String>, &self, user_id: &UserId, device_id: &DeviceId, token: &str, initial_device_display_name: Option<String>,
client_ip: Option<String>,
) -> Result<()> { ) -> Result<()> {
self.db self.db
.create_device(user_id, device_id, token, initial_device_display_name, client_ip) .create_device(user_id, device_id, token, initial_device_display_name)
} }
/// Removes a device from a user. /// Removes a device from a user.