Compare commits

...

11 Commits

Author SHA1 Message Date
timedout 82bd0c8e15 fix: Actually flush destinations before selecting new events 2026-02-27 11:18:43 +00:00
timedout 5e3174493d feat: Add method to flush senders when a server becomes active 2026-02-26 16:16:45 +00:00
Niklas Wojtkowiak 052c4dfa21 fix(sync): don't override sliding sync v5 list range start to zero 2026-02-24 13:59:33 +00:00
lynxize a43dee1728 fix: Don't show successful media deletion as an error
Fixes !admin media delete --mxc <url> responding with an error message
when the media was deleted successfully.
2026-02-23 22:02:34 -07:00
Niklas Wojtkowiak 763d9b3de8 fixup! fix(api): restore backwards compatibility for RTC foci config 2026-02-23 18:10:25 -05:00
Niklas Wojtkowiak 1e6d95583c chore(deps): update ruwuma revision 2026-02-23 23:01:15 +00:00
Niklas Wojtkowiak 8a254a33cc fix(api): restore backwards compatibility for RTC foci config 2026-02-23 23:01:15 +00:00
Niklas Wojtkowiak c97dd54766 chore(changelog): add news fragment for #1442 2026-02-23 23:01:15 +00:00
Niklas Wojtkowiak 8ddb7c70c0 feat(api): implement MSC4143 RTC transports discovery endpoint
Add dedicated \`GET /_matrix/client/v1/rtc/transports\` and \`GET /_matrix/client/unstable/org.matrix.msc4143/rtc/transports\` endpoints for MatrixRTC focus discovery (MSC4143), replacing the deprecated well-known approach.

Move RTC foci configuration from \`[global.well_known]\` into a new \`[global.matrix_rtc]\` config section with a \`foci\` field. Remove \`rtc_foci\` from the \`.well-known/matrix/client\` response. Update LiveKit setup documentation accordingly.

Closes #1431
2026-02-23 23:01:15 +00:00
Niklas Wojtkowiak cb9786466b chore(changelog): add news fragment for #1441 2026-02-23 17:59:13 +00:00
Niklas Wojtkowiak 18d2662b01 fix(config): remove allow_public_room_directory_without_auth 2026-02-23 17:59:13 +00:00
16 changed files with 205 additions and 102 deletions
Generated
+14 -14
View File
@@ -1222,7 +1222,7 @@ dependencies = [
[[package]] [[package]]
name = "continuwuity-admin-api" name = "continuwuity-admin-api"
version = "0.1.0" version = "0.1.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"ruma-common", "ruma-common",
"serde", "serde",
@@ -1601,7 +1601,7 @@ dependencies = [
[[package]] [[package]]
name = "draupnir-antispam" name = "draupnir-antispam"
version = "0.1.0" version = "0.1.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"ruma-common", "ruma-common",
"serde", "serde",
@@ -3003,7 +3003,7 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]] [[package]]
name = "meowlnir-antispam" name = "meowlnir-antispam"
version = "0.1.0" version = "0.1.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"ruma-common", "ruma-common",
"serde", "serde",
@@ -4095,7 +4095,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma" name = "ruma"
version = "0.10.1" version = "0.10.1"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"assign", "assign",
"continuwuity-admin-api", "continuwuity-admin-api",
@@ -4118,7 +4118,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-appservice-api" name = "ruma-appservice-api"
version = "0.10.0" version = "0.10.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@@ -4130,7 +4130,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-client-api" name = "ruma-client-api"
version = "0.18.0" version = "0.18.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"assign", "assign",
@@ -4153,7 +4153,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-common" name = "ruma-common"
version = "0.13.0" version = "0.13.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"base64 0.22.1", "base64 0.22.1",
@@ -4185,7 +4185,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-events" name = "ruma-events"
version = "0.28.1" version = "0.28.1"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"indexmap", "indexmap",
@@ -4210,7 +4210,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-federation-api" name = "ruma-federation-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"bytes", "bytes",
"headers", "headers",
@@ -4232,7 +4232,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identifiers-validation" name = "ruma-identifiers-validation"
version = "0.9.5" version = "0.9.5"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"js_int", "js_int",
"thiserror 2.0.18", "thiserror 2.0.18",
@@ -4241,7 +4241,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identity-service-api" name = "ruma-identity-service-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@@ -4251,7 +4251,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-macros" name = "ruma-macros"
version = "0.13.0" version = "0.13.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"proc-macro-crate", "proc-macro-crate",
@@ -4266,7 +4266,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-push-gateway-api" name = "ruma-push-gateway-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@@ -4278,7 +4278,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-signatures" name = "ruma-signatures"
version = "0.15.0" version = "0.15.0"
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=e087ff15888156942ca2ffe6097d1b4c3fd27628#e087ff15888156942ca2ffe6097d1b4c3fd27628" source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf#a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"ed25519-dalek", "ed25519-dalek",
+1 -1
View File
@@ -343,7 +343,7 @@ version = "0.1.2"
[workspace.dependencies.ruma] [workspace.dependencies.ruma]
git = "https://forgejo.ellis.link/continuwuation/ruwuma" git = "https://forgejo.ellis.link/continuwuation/ruwuma"
#branch = "conduwuit-changes" #branch = "conduwuit-changes"
rev = "e087ff15888156942ca2ffe6097d1b4c3fd27628" rev = "a4b5e89f4951c87e903ef224c2d1c2c4ef1ebeaf"
features = [ features = [
"compat", "compat",
"rand", "rand",
+1
View File
@@ -0,0 +1 @@
Removed the `allow_public_room_directory_without_auth` config option. Contributed by @0xnim.
+1
View File
@@ -0,0 +1 @@
Implement MSC4143 MatrixRTC transport discovery endpoint. Move RTC foci configuration from `[global.well_known]` to a new `[global.matrix_rtc]` section with a `foci` field. Contributed by @0xnim
+1
View File
@@ -0,0 +1 @@
Fixed sliding sync v5 list ranges always starting from 0, causing extra rooms to be unnecessarily processed and returned. Contributed by @0xnim
-1
View File
@@ -9,7 +9,6 @@ address = "0.0.0.0"
allow_device_name_federation = true allow_device_name_federation = true
allow_guest_registration = true allow_guest_registration = true
allow_public_room_directory_over_federation = true allow_public_room_directory_over_federation = true
allow_public_room_directory_without_auth = true
allow_registration = true allow_registration = true
database_path = "/database" database_path = "/database"
log = "trace,h2=debug,hyper=debug" log = "trace,h2=debug,hyper=debug"
+23 -13
View File
@@ -546,12 +546,6 @@
# #
#allow_public_room_directory_over_federation = false #allow_public_room_directory_over_federation = false
# Set this to true to allow your server's public room directory to be
# queried without client authentication (access token) through the Client
# APIs. Set this to false to protect against /publicRooms spiders.
#
#allow_public_room_directory_without_auth = false
# Allow guests/unauthenticated users to access TURN credentials. # Allow guests/unauthenticated users to access TURN credentials.
# #
# This is the equivalent of Synapse's `turn_allow_guests` config option. # This is the equivalent of Synapse's `turn_allow_guests` config option.
@@ -1850,14 +1844,13 @@
# #
#support_mxid = #support_mxid =
# A list of MatrixRTC foci URLs which will be served as part of the # **DEPRECATED**: Use `[global.matrix_rtc].foci` instead.
# MSC4143 client endpoint at /.well-known/matrix/client. If you're
# setting up livekit, you'd want something like:
# rtc_focus_server_urls = [
# { type = "livekit", livekit_service_url = "https://livekit.example.com" },
# ]
# #
# To disable, set this to be an empty vector (`[]`). # A list of MatrixRTC foci URLs which will be served as part of the
# MSC4143 client endpoint at /.well-known/matrix/client.
#
# This option is deprecated and will be removed in a future release.
# Please migrate to the new `[global.matrix_rtc]` config section.
# #
#rtc_focus_server_urls = [] #rtc_focus_server_urls = []
@@ -1879,6 +1872,23 @@
# #
#blurhash_max_raw_size = 33554432 #blurhash_max_raw_size = 33554432
[global.matrix_rtc]
# A list of MatrixRTC foci (transports) which will be served via the
# MSC4143 RTC transports endpoint at
# `/_matrix/client/v1/rtc/transports`. If you're setting up livekit,
# you'd want something like:
# ```toml
# [global.matrix_rtc]
# foci = [
# { type = "livekit", livekit_service_url = "https://livekit.example.com" },
# ]
# ```
#
# To disable, set this to an empty list (`[]`).
#
#foci = []
[global.ldap] [global.ldap]
# Whether to enable LDAP login. # Whether to enable LDAP login.
+4 -32
View File
@@ -78,47 +78,19 @@ You will need to allow ports `7881/tcp` and `50100:50200/udp` through your firew
### 3. Telling clients where to find LiveKit ### 3. Telling clients where to find LiveKit
To tell clients where to find LiveKit, you need to add the address of your `lk-jwt-service` to your client .well-known file. To do so, in the config section `global.well-known`, add (or modify) the option `rtc_focus_server_urls`. To tell clients where to find LiveKit, you need to add the address of your `lk-jwt-service` to the `[global.matrix_rtc]` config section using the `foci` option.
The variable should be a list of servers serving as MatrixRTC endpoints to serve in the well-known file to the client. The variable should be a list of servers serving as MatrixRTC endpoints. Clients discover these via the `/_matrix/client/v1/rtc/transports` endpoint (MSC4143).
```toml ```toml
rtc_focus_server_urls = [ [global.matrix_rtc]
foci = [
{ type = "livekit", livekit_service_url = "https://livekit.example.com" }, { type = "livekit", livekit_service_url = "https://livekit.example.com" },
] ]
``` ```
Remember to replace the URL with the address you are deploying your instance of lk-jwt-service to. Remember to replace the URL with the address you are deploying your instance of lk-jwt-service to.
#### Serving .well-known manually
If you don't let Continuwuity serve your `.well-known` files, you need to add the following lines to your `.well-known/matrix/client` file, remembering to replace the URL with your own `lk-jwt-service` deployment:
```json
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://livekit.example.com"
}
]
```
The final file should look something like this:
```json
{
"m.homeserver": {
"base_url":"https://matrix.example.com"
},
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://livekit.example.com"
}
]
}
```
### 4. Configure your Reverse Proxy ### 4. Configure your Reverse Proxy
Reverse proxies can be configured in many different ways - so we can't provide a step by step for this. Reverse proxies can be configured in many different ways - so we can't provide a step by step for this.
+3 -1
View File
@@ -29,7 +29,9 @@ pub(super) async fn delete(
.delete(&mxc.as_str().try_into()?) .delete(&mxc.as_str().try_into()?)
.await?; .await?;
return Err!("Deleted the MXC from our database and on our filesystem.",); return self
.write_str("Deleted the MXC from our database and on our filesystem.")
.await;
} }
if let Some(event_id) = event_id { if let Some(event_id) = event_id {
+3 -1
View File
@@ -336,7 +336,9 @@ where
let ranges = list.ranges.clone(); let ranges = list.ranges.clone();
for mut range in ranges { for mut range in ranges {
range.0 = uint!(0); range.0 = range
.0
.min(UInt::try_from(active_rooms.len()).unwrap_or(UInt::MAX));
range.1 = range.1.checked_add(uint!(1)).unwrap_or(range.1); range.1 = range.1.checked_add(uint!(1)).unwrap_or(range.1);
range.1 = range range.1 = range
.1 .1
+23 -1
View File
@@ -27,10 +27,32 @@ pub(crate) async fn well_known_client(
identity_server: None, identity_server: None,
sliding_sync_proxy: Some(SlidingSyncProxyInfo { url: client_url }), sliding_sync_proxy: Some(SlidingSyncProxyInfo { url: client_url }),
tile_server: None, tile_server: None,
rtc_foci: services.config.well_known.rtc_focus_server_urls.clone(), rtc_foci: services
.config
.matrix_rtc
.effective_foci(&services.config.well_known.rtc_focus_server_urls)
.to_vec(),
}) })
} }
/// # `GET /_matrix/client/v1/rtc/transports`
/// # `GET /_matrix/client/unstable/org.matrix.msc4143/rtc/transports`
///
/// Returns the list of MatrixRTC foci (transports) configured for this
/// homeserver, implementing MSC4143.
pub(crate) async fn get_rtc_transports(
State(services): State<crate::State>,
_body: Ruma<ruma::api::client::discovery::get_rtc_transports::Request>,
) -> Result<ruma::api::client::discovery::get_rtc_transports::Response> {
Ok(ruma::api::client::discovery::get_rtc_transports::Response::new(
services
.config
.matrix_rtc
.effective_foci(&services.config.well_known.rtc_focus_server_urls)
.to_vec(),
))
}
/// # `GET /.well-known/matrix/support` /// # `GET /.well-known/matrix/support`
/// ///
/// Server support contact and support page of a homeserver's domain. /// Server support contact and support page of a homeserver's domain.
+1
View File
@@ -184,6 +184,7 @@ pub fn build(router: Router<State>, server: &Server) -> Router<State> {
.ruma_route(&client::put_suspended_status) .ruma_route(&client::put_suspended_status)
.ruma_route(&client::well_known_support) .ruma_route(&client::well_known_support)
.ruma_route(&client::well_known_client) .ruma_route(&client::well_known_client)
.ruma_route(&client::get_rtc_transports)
.route("/_conduwuit/server_version", get(client::conduwuit_server_version)) .route("/_conduwuit/server_version", get(client::conduwuit_server_version))
.route("/_continuwuity/server_version", get(client::conduwuit_server_version)) .route("/_continuwuity/server_version", get(client::conduwuit_server_version))
.ruma_route(&client::room_initial_sync_route) .ruma_route(&client::room_initial_sync_route)
+20 -18
View File
@@ -4,7 +4,7 @@ use axum_extra::{
headers::{Authorization, authorization::Bearer}, headers::{Authorization, authorization::Bearer},
typed_header::TypedHeaderRejectionReason, typed_header::TypedHeaderRejectionReason,
}; };
use conduwuit::{Err, Error, Result, debug_error, err, warn}; use conduwuit::{Err, Error, Result, debug_error, debug_info, err, warn};
use futures::{ use futures::{
TryFutureExt, TryFutureExt,
future::{ future::{
@@ -67,23 +67,17 @@ pub(super) async fn auth(
if metadata.authentication == AuthScheme::None { if metadata.authentication == AuthScheme::None {
match metadata { match metadata {
| &get_public_rooms::v3::Request::METADATA => { | &get_public_rooms::v3::Request::METADATA => {
if !services match token {
.server | Token::Appservice(_) | Token::User(_) => {
.config // we should have validated the token above
.allow_public_room_directory_without_auth // already
{ },
match token { | Token::None | Token::Invalid => {
| Token::Appservice(_) | Token::User(_) => { return Err(Error::BadRequest(
// we should have validated the token above ErrorKind::MissingToken,
// already "Missing or invalid access token.",
}, ));
| Token::None | Token::Invalid => { },
return Err(Error::BadRequest(
ErrorKind::MissingToken,
"Missing or invalid access token.",
));
},
}
} }
}, },
| &get_profile::v3::Request::METADATA | &get_profile::v3::Request::METADATA
@@ -335,6 +329,14 @@ async fn auth_server(
return Err!(Request(Forbidden("Failed to verify X-Matrix signatures."))); return Err!(Request(Forbidden("Failed to verify X-Matrix signatures.")));
} }
if services.sending.server_is_offline(destination).await {
debug_info!(?destination, "server returned from being offline");
services
.sending
.mark_server_online(destination, false)
.await;
}
Ok(Auth { Ok(Auth {
origin: origin.to_owned().into(), origin: origin.to_owned().into(),
sender_user: None, sender_user: None,
+51 -17
View File
@@ -678,12 +678,6 @@ pub struct Config {
#[serde(default)] #[serde(default)]
pub allow_public_room_directory_over_federation: bool, pub allow_public_room_directory_over_federation: bool,
/// Set this to true to allow your server's public room directory to be
/// queried without client authentication (access token) through the Client
/// APIs. Set this to false to protect against /publicRooms spiders.
#[serde(default)]
pub allow_public_room_directory_without_auth: bool,
/// Allow guests/unauthenticated users to access TURN credentials. /// Allow guests/unauthenticated users to access TURN credentials.
/// ///
/// This is the equivalent of Synapse's `turn_allow_guests` config option. /// This is the equivalent of Synapse's `turn_allow_guests` config option.
@@ -2086,6 +2080,12 @@ pub struct Config {
/// display: nested /// display: nested
#[serde(default)] #[serde(default)]
pub blurhashing: BlurhashConfig, pub blurhashing: BlurhashConfig,
/// Configuration for MatrixRTC (MSC4143) transport discovery.
/// display: nested
#[serde(default)]
pub matrix_rtc: MatrixRtcConfig,
#[serde(flatten)] #[serde(flatten)]
#[allow(clippy::zero_sized_map_values)] #[allow(clippy::zero_sized_map_values)]
// this is a catchall, the map shouldn't be zero at runtime // this is a catchall, the map shouldn't be zero at runtime
@@ -2151,17 +2151,16 @@ pub struct WellKnownConfig {
/// listed. /// listed.
pub support_mxid: Option<OwnedUserId>, pub support_mxid: Option<OwnedUserId>,
/// A list of MatrixRTC foci URLs which will be served as part of the /// **DEPRECATED**: Use `[global.matrix_rtc].foci` instead.
/// MSC4143 client endpoint at /.well-known/matrix/client. If you're
/// setting up livekit, you'd want something like:
/// rtc_focus_server_urls = [
/// { type = "livekit", livekit_service_url = "https://livekit.example.com" },
/// ]
/// ///
/// To disable, set this to be an empty vector (`[]`). /// A list of MatrixRTC foci URLs which will be served as part of the
/// MSC4143 client endpoint at /.well-known/matrix/client.
///
/// This option is deprecated and will be removed in a future release.
/// Please migrate to the new `[global.matrix_rtc]` config section.
/// ///
/// default: [] /// default: []
#[serde(default = "default_rtc_focus_urls")] #[serde(default)]
pub rtc_focus_server_urls: Vec<RtcFocusInfo>, pub rtc_focus_server_urls: Vec<RtcFocusInfo>,
} }
@@ -2190,6 +2189,43 @@ pub struct BlurhashConfig {
pub blurhash_max_raw_size: u64, pub blurhash_max_raw_size: u64,
} }
#[derive(Clone, Debug, Deserialize, Default)]
#[config_example_generator(filename = "conduwuit-example.toml", section = "global.matrix_rtc")]
pub struct MatrixRtcConfig {
/// A list of MatrixRTC foci (transports) which will be served via the
/// MSC4143 RTC transports endpoint at
/// `/_matrix/client/v1/rtc/transports`. If you're setting up livekit,
/// you'd want something like:
/// ```toml
/// [global.matrix_rtc]
/// foci = [
/// { type = "livekit", livekit_service_url = "https://livekit.example.com" },
/// ]
/// ```
///
/// To disable, set this to an empty list (`[]`).
///
/// default: []
#[serde(default)]
pub foci: Vec<RtcFocusInfo>,
}
impl MatrixRtcConfig {
/// Returns the effective foci, falling back to the deprecated
/// `rtc_focus_server_urls` if the new config is empty.
#[must_use]
pub fn effective_foci<'a>(
&'a self,
deprecated_foci: &'a [RtcFocusInfo],
) -> &'a [RtcFocusInfo] {
if !self.foci.is_empty() {
&self.foci
} else {
deprecated_foci
}
}
}
#[derive(Clone, Debug, Default, Deserialize)] #[derive(Clone, Debug, Default, Deserialize)]
#[config_example_generator(filename = "conduwuit-example.toml", section = "global.ldap")] #[config_example_generator(filename = "conduwuit-example.toml", section = "global.ldap")]
pub struct LdapConfig { pub struct LdapConfig {
@@ -2383,6 +2419,7 @@ const DEPRECATED_KEYS: &[&str] = &[
"well_known_support_email", "well_known_support_email",
"well_known_support_mxid", "well_known_support_mxid",
"registration_token_file", "registration_token_file",
"well_known.rtc_focus_server_urls",
]; ];
impl Config { impl Config {
@@ -2666,9 +2703,6 @@ fn default_rocksdb_stats_level() -> u8 { 1 }
#[inline] #[inline]
pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V11 } pub fn default_default_room_version() -> RoomVersionId { RoomVersionId::V11 }
#[must_use]
pub fn default_rtc_focus_urls() -> Vec<RtcFocusInfo> { vec![] }
fn default_ip_range_denylist() -> Vec<String> { fn default_ip_range_denylist() -> Vec<String> {
vec![ vec![
"127.0.0.0/8".to_owned(), "127.0.0.0/8".to_owned(),
+42 -2
View File
@@ -5,6 +5,7 @@ mod dest;
mod sender; mod sender;
use std::{ use std::{
collections::HashSet,
fmt::Debug, fmt::Debug,
hash::{DefaultHasher, Hash, Hasher}, hash::{DefaultHasher, Hash, Hasher},
iter::once, iter::once,
@@ -19,8 +20,8 @@ use conduwuit::{
warn, warn,
}; };
use futures::{FutureExt, Stream, StreamExt}; use futures::{FutureExt, Stream, StreamExt};
use ruma::{RoomId, ServerName, UserId, api::OutgoingRequest}; use ruma::{OwnedServerName, RoomId, ServerName, UserId, api::OutgoingRequest};
use tokio::{task, task::JoinSet}; use tokio::{sync::RwLock, task, task::JoinSet};
use self::data::Data; use self::data::Data;
pub use self::{ pub use self::{
@@ -37,6 +38,7 @@ pub struct Service {
server: Arc<Server>, server: Arc<Server>,
services: Services, services: Services,
channels: Vec<(loole::Sender<Msg>, loole::Receiver<Msg>)>, channels: Vec<(loole::Sender<Msg>, loole::Receiver<Msg>)>,
pub offline_servers: RwLock<HashSet<OwnedServerName>>,
} }
struct Services { struct Services {
@@ -52,6 +54,7 @@ struct Services {
account_data: Dep<account_data::Service>, account_data: Dep<account_data::Service>,
appservice: Dep<crate::appservice::Service>, appservice: Dep<crate::appservice::Service>,
pusher: Dep<pusher::Service>, pusher: Dep<pusher::Service>,
resolver: Dep<crate::resolver::Service>,
federation: Dep<federation::Service>, federation: Dep<federation::Service>,
} }
@@ -96,9 +99,11 @@ impl crate::Service for Service {
account_data: args.depend::<account_data::Service>("account_data"), account_data: args.depend::<account_data::Service>("account_data"),
appservice: args.depend::<crate::appservice::Service>("appservice"), appservice: args.depend::<crate::appservice::Service>("appservice"),
pusher: args.depend::<pusher::Service>("pusher"), pusher: args.depend::<pusher::Service>("pusher"),
resolver: args.depend::<crate::resolver::Service>("resolver"),
federation: args.depend::<federation::Service>("federation"), federation: args.depend::<federation::Service>("federation"),
}, },
channels: (0..num_senders).map(|_| loole::unbounded()).collect(), channels: (0..num_senders).map(|_| loole::unbounded()).collect(),
offline_servers: RwLock::new(HashSet::new()),
})) }))
} }
@@ -146,6 +151,8 @@ impl crate::Service for Service {
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) } fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
fn unconstrained(&self) -> bool { true } fn unconstrained(&self) -> bool { true }
async fn clear_cache(&self) { self.offline_servers.write().await.clear(); }
} }
impl Service { impl Service {
@@ -379,6 +386,39 @@ impl Service {
let chans = self.channels.len().max(1); let chans = self.channels.len().max(1);
hash.overflowing_rem(chans).0 hash.overflowing_rem(chans).0
} }
/// Marks a server as offline
pub async fn mark_server_offline(&self, server: OwnedServerName) {
self.offline_servers.write().await.insert(server);
}
/// Marks a server as online again and flushes the senders if it was
/// previously marked as offline
pub async fn mark_server_online(&self, server: &ServerName, skip_flush: bool) {
if self.offline_servers.write().await.remove(server) && !skip_flush {
// Flush the senders if this server was previously offline
self.services.resolver.cache.del_destination(server);
self.services.resolver.cache.del_override(server);
self.dispatch(Msg {
dest: Destination::Federation(server.to_owned()),
event: SendingEvent::Flush,
queue_id: Vec::<u8>::new(),
})
.inspect_err(|e| {
error!(
?server,
?e,
"failed to dispatch flush message for server coming back online"
);
})
.ok();
}
}
/// Checks if a server is currently marked as offline
pub async fn server_is_offline(&self, server: &ServerName) -> bool {
self.offline_servers.read().await.contains(server)
}
} }
fn num_senders(args: &crate::Args<'_>) -> usize { fn num_senders(args: &crate::Args<'_>) -> usize {
+17 -1
View File
@@ -9,6 +9,7 @@ use std::{
}; };
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD}; use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
use conduwuit::debug_warn;
use conduwuit_core::{ use conduwuit_core::{
Error, Event, Result, debug, err, error, Error, Event, Result, debug, err, error,
result::LogErr, result::LogErr,
@@ -135,7 +136,13 @@ impl Service {
) { ) {
match response { match response {
| Ok(dest) => self.handle_response_ok(&dest, futures, statuses).await, | Ok(dest) => self.handle_response_ok(&dest, futures, statuses).await,
| Err((dest, e)) => Self::handle_response_err(dest, statuses, &e), | Err((dest, e)) => {
Self::handle_response_err(dest.clone(), statuses, &e);
if let Destination::Federation(server_name) = dest {
debug_warn!(?server_name, "marking server offline due to error: {e:?}");
self.mark_server_offline(server_name).await;
}
},
} }
} }
@@ -180,6 +187,12 @@ impl Service {
} else { } else {
statuses.remove(dest); statuses.remove(dest);
} }
if let Destination::Federation(server_name) = dest {
self.mark_server_online(server_name, true).await;
// We skip the flush here because we were already able to contact
// the server, and have queued any pending events, and the
// resolver cache will be fine.
}
} }
#[allow(clippy::needless_pass_by_ref_mut)] #[allow(clippy::needless_pass_by_ref_mut)]
@@ -190,6 +203,9 @@ impl Service {
futures: &mut SendingFutures<'a>, futures: &mut SendingFutures<'a>,
statuses: &mut CurTransactionStatus, statuses: &mut CurTransactionStatus,
) { ) {
if msg.event == SendingEvent::Flush {
statuses.remove(&msg.dest);
}
let iv = vec![(msg.queue_id, msg.event)]; let iv = vec![(msg.queue_id, msg.event)];
if let Ok(Some(events)) = self.select_events(&msg.dest, iv, statuses).await { if let Ok(Some(events)) = self.select_events(&msg.dest, iv, statuses).await {
if !events.is_empty() { if !events.is_empty() {