Compare commits

...

9 Commits

Author SHA1 Message Date
Ginger a76c5c95aa chore: Release 2026-07-10 13:01:48 -04:00
Ginger 7f83ec3883 chore: Update changelog 2026-07-10 12:59:50 -04:00
Ginger 9b14ab4c0b fix: Parse OIDC discovery URL more leniently 2026-07-10 16:52:04 +00:00
timedout b915692ae1 fix: Remove broken federated invite revoke handling
It turns out it never worked in the first place :D
2026-07-10 16:32:38 +01:00
theS1LV3R bed80964fd chore: Update changelog 2026-07-10 13:44:59 +00:00
theS1LV3R bc7e3185ef chore(deps): Update to resolvematrix 1.1.0 2026-07-10 13:44:59 +00:00
theS1LV3R 7082914d7d chore: Update resolvematrix dependency rev hash 2026-07-10 13:44:59 +00:00
theS1LV3R 8fb14f666f chore: Add changelog 2026-07-10 13:44:59 +00:00
theS1LV3R 8b6a176901 fix: Use correct DNS caching for SNI to function properly
This removes the old (broken) DNS caching method for reqwest, and replaces
it with resolvematrix' `MatrixDnsResolver`, as it correctly implements
caching and overrides for correct SNI behavior.
2026-07-10 13:44:59 +00:00
51 changed files with 242 additions and 295 deletions
+128
View File
@@ -1,3 +1,131 @@
# Continuwuity 26.6.0 (2026-07-10)
## Features
- Added support for linking an external identity provider with OIDC. Contributed by @ginger. (#765)
- Updated [MSC4284: Policy Servers](https://github.com/matrix-org/matrix-spec-proposals/pull/4284) implementation to support the newly stabilised proposal. Contributed by @nex. (#1487)
- Added config option for default room ACLs. Contributed by @eve. (#1691)
- Added support for fallback encryption keys. (#1710)
- Add `!admin users reject-all-invites` to clean invite spam (#1741)
- Implemented event rejection, which should resolve and prevent future netsplits of the kinds observed
within some Continuwuity rooms.
Also resolved several bugs related to both soft-failing events, and event backfilling, which should
improve state resolution stability.
The `!admin debug get-pdu` command was updated to disambiguate event acceptance status, and
`!admin debug show-auth-chain` was added to visually display event auth chains, which may assist
developers in debugging strangely complex events.
Contributed by @nex. (#1747)
- Added full support for [MSC4168: Update `m.space.*` state on room upgrade](https://github.com/matrix-org/matrix-spec-proposals/pull/4168). Contributed by @nex. (#1807)
- Improved the performance and reliability of fetching missing events, improving network partition recovery. Contributed
by @nex. (#1818)
- Added static builds using Nix, allowing for Continuwuity on musl. During this, we also introduced a `max-perf-haswell` package, separating it from `max-perf`, so you may want to swap to this if you are on NixOS. Contributed by @Henry-Hiles (QuadRadical). (#1853)
- Added support for MSC4380 invite blocking, which has become part of the Matrix specification in v1.18. Contributed by @nex. (#1875)
- Added `!admin debug get-state-at` command (#1877)
- Added a configuration option to allow choosing a client IP source that is not the TCP connecting IP. Contributed by @nex. (#1931)
- Added support for MSC4466, which allows clients to customize how changes to a user's global profile are propagated. Contributed by @ginger.
- Added support for Matrix 1.16's `state_after` feature, allowing clients which understand it to sync room state changes more reliably. Contributed by @ginger.
- Added support for authenticating clients using the new OAuth 2.0 login API. Contributed by @ginger.
- Appservice device management as outlined in MSC4190 (part of Matrix 1.17) is now fully supported. Contributed by @ginger.
- Users may now be forbidden from deactivating their own accounts with the new `allow_deactivation` config option. Contributed by @ginger.
## Bugfixes
- Adjusted legacy sync logic to allow the `roomsynctoken_shortstatehash` database column to be dropped, massively reducing database sizes, especially for old deployments. Contributed by @ginger. (#917)
- Fixed a bug that caused the server to drop events during processing if several events for the same room were sent in a singular transaction. Contributed by @nex. (#1711)
- fix `!admin query account-data account-data-get` not returning the content (#1742)
- Fixed an issue where Continuwuity would only advertise support for the unstable endpoint for Mutual Rooms (MSC2666), despite only supporting the stable endpoint. Contributed by @Henry-Hiles (QuadRadical) (#1752)
- Fixed admin commands being ignored when they had leading whitespace before admin commands. Contributed by @kitvonsnookerz. (#1804)
- Fixed several bugs in the `POST /_matrix/client/v3/rooms/{roomId}/upgrade` endpoint. Contributed by @nex. (#1807)
- Devices which set their presence as "offline" will no longer be considered for presence updates. Contributed by @timedout.
- Improved invite and join reliability in clients using legacy sync. Contributed by @ginger
- The invite recipient's membership event is now included in invite stripped state, which should fix flaky invite display in some clients. Contributed by @ginger
## Improved Documentation
- Add performance tuning documentation. Contributed by @stratself. (#1498)
- Added example configuration using caddy-docker-proxy in the livekit setup section of the docs. Contributed by @Cease (#1762)
- Updated deployment docs to account for new RPM package availability across more distros. Contributed by @julian45. (#1912)
## Deprecations and Removals
- Removed support for LDAP. (#1701)
- Removed support for guest user registration, a little-used and deprecated approach to room previews.
- Removed the `/_conduwuit/` versions of the `local_user_count` and `version` routes. These routes are still accessible under the `/_continuwuity` prefix.
- Support for server-side blurhashing (part of MSC2448) has been removed.
- The deprecated `well_known.rtc_focus_server_urls` config option has been removed. MatrixRTC foci should be configured using the `matrix_rtc.foci` config option.
## Misc
- #1829, #1933
- Switched from Continuwuity's fork of Ruma back to upstream Ruma. Contributed by @ginger.
- The version of Debian that the Docker-based build process uses has been upgraded from Bookworm to Trixie, meaning that standalone binaries now have a minimum glibc of 2.41, and can no longer be used on distro versions from before 2025-01-30
# Continuwuity 26.6.0 (2026-07-10)
## Features
- Added support for linking an external identity provider with OIDC. Contributed by @ginger. (#765)
- Updated [MSC4284: Policy Servers](https://github.com/matrix-org/matrix-spec-proposals/pull/4284) implementation to support the newly stabilised proposal. Contributed by @nex. (#1487)
- Added config option for default room ACLs. Contributed by @eve. (#1691)
- Added support for fallback encryption keys. (#1710)
- Add `!admin users reject-all-invites` to clean invite spam (#1741)
- Implemented event rejection, which should resolve and prevent future netsplits of the kinds observed
within some Continuwuity rooms.
Also resolved several bugs related to both soft-failing events, and event backfilling, which should
improve state resolution stability.
The `!admin debug get-pdu` command was updated to disambiguate event acceptance status, and
`!admin debug show-auth-chain` was added to visually display event auth chains, which may assist
developers in debugging strangely complex events.
Contributed by @nex. (#1747)
- Added full support for [MSC4168: Update `m.space.*` state on room upgrade](https://github.com/matrix-org/matrix-spec-proposals/pull/4168). Contributed by @nex. (#1807)
- Improved the performance and reliability of fetching missing events, improving network partition recovery. Contributed
by @nex. (#1818)
- Added static builds using Nix, allowing for Continuwuity on musl. During this, we also introduced a `max-perf-haswell` package, separating it from `max-perf`, so you may want to swap to this if you are on NixOS. Contributed by @Henry-Hiles (QuadRadical). (#1853)
- Added support for MSC4380 invite blocking, which has become part of the Matrix specification in v1.18. Contributed by @nex. (#1875)
- Added `!admin debug get-state-at` command (#1877)
- Added a configuration option to allow choosing a client IP source that is not the TCP connecting IP. Contributed by @nex. (#1931)
- Added support for MSC4466, which allows clients to customize how changes to a user's global profile are propagated. Contributed by @ginger.
- Added support for Matrix 1.16's `state_after` feature, allowing clients which understand it to sync room state changes more reliably. Contributed by @ginger.
- Added support for authenticating clients using the new OAuth 2.0 login API. Contributed by @ginger.
- Appservice device management as outlined in MSC4190 (part of Matrix 1.17) is now fully supported. Contributed by @ginger.
- Users may now be forbidden from deactivating their own accounts with the new `allow_deactivation` config option. Contributed by @ginger.
## Bugfixes
- Adjusted legacy sync logic to allow the `roomsynctoken_shortstatehash` database column to be dropped, massively reducing database sizes, especially for old deployments. Contributed by @ginger. (#917)
- Fixed a bug that caused the server to drop events during processing if several events for the same room were sent in a singular transaction. Contributed by @nex. (#1711)
- fix `!admin query account-data account-data-get` not returning the content (#1742)
- Fixed an issue where Continuwuity would only advertise support for the unstable endpoint for Mutual Rooms (MSC2666), despite only supporting the stable endpoint. Contributed by @Henry-Hiles (QuadRadical) (#1752)
- Fixed admin commands being ignored when they had leading whitespace before admin commands. Contributed by @kitvonsnookerz. (#1804)
- Fixed several bugs in the `POST /_matrix/client/v3/rooms/{roomId}/upgrade` endpoint. Contributed by @nex. (#1807)
- Devices which set their presence as "offline" will no longer be considered for presence updates. Contributed by @timedout.
- Improved invite and join reliability in clients using legacy sync. Contributed by @ginger
- The invite recipient's membership event is now included in invite stripped state, which should fix flaky invite display in some clients. Contributed by @ginger
## Improved Documentation
- Add performance tuning documentation. Contributed by @stratself. (#1498)
- Added example configuration using caddy-docker-proxy in the livekit setup section of the docs. Contributed by @Cease (#1762)
- Updated deployment docs to account for new RPM package availability across more distros. Contributed by @julian45. (#1912)
## Deprecations and Removals
- Removed support for LDAP. (#1701)
- Removed support for guest user registration, a little-used and deprecated approach to room previews.
- Removed the `/_conduwuit/` versions of the `local_user_count` and `version` routes. These routes are still accessible under the `/_continuwuity` prefix.
- Support for server-side blurhashing (part of MSC2448) has been removed.
- The deprecated `well_known.rtc_focus_server_urls` config option has been removed. MatrixRTC foci should be configured using the `matrix_rtc.foci` config option.
## Misc
- #1829, #1933
- Switched from Continuwuity's fork of Ruma back to upstream Ruma. Contributed by @ginger.
- The version of Debian that the Docker-based build process uses has been upgraded from Bookworm to Trixie, meaning that standalone binaries now have a minimum glibc of 2.41, and can no longer be used on distro versions from before 2025-01-30
# Continuwuity 0.5.8 (2026-04-24)
## Features
Generated
+14 -14
View File
@@ -826,7 +826,7 @@ dependencies = [
[[package]]
name = "conduwuit"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"aws-lc-rs",
"clap",
@@ -864,7 +864,7 @@ dependencies = [
[[package]]
name = "conduwuit_admin"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"assign",
"clap",
@@ -890,7 +890,7 @@ dependencies = [
[[package]]
name = "conduwuit_api"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"assign",
"async-trait",
@@ -928,7 +928,7 @@ dependencies = [
[[package]]
name = "conduwuit_build_metadata"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"built",
"cargo_metadata",
@@ -936,7 +936,7 @@ dependencies = [
[[package]]
name = "conduwuit_core"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"argon2",
"arrayvec",
@@ -1004,7 +1004,7 @@ dependencies = [
[[package]]
name = "conduwuit_database"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"async-channel",
"conduwuit_core",
@@ -1025,7 +1025,7 @@ dependencies = [
[[package]]
name = "conduwuit_macros"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"cargo_toml",
"itertools 0.15.0",
@@ -1036,7 +1036,7 @@ dependencies = [
[[package]]
name = "conduwuit_router"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"assign",
"axum",
@@ -1074,7 +1074,7 @@ dependencies = [
[[package]]
name = "conduwuit_service"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"askama",
"assign",
@@ -1126,7 +1126,7 @@ dependencies = [
[[package]]
name = "conduwuit_web"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"askama",
"assign",
@@ -4539,9 +4539,9 @@ checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7"
[[package]]
name = "resolvematrix"
version = "1.0.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3121df844d2f59c801c703af7200b8dab5d1c04c5032cd57fa9347440346fe87"
checksum = "a574e37f06e219dcfdb14a4f0abf56e806c4551e030aae53802d2c42b29aea33"
dependencies = [
"futures",
"hickory-resolver",
@@ -4799,7 +4799,7 @@ dependencies = [
[[package]]
name = "ruminuwuity"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"assign",
"ruma",
@@ -6972,7 +6972,7 @@ dependencies = [
[[package]]
name = "xtask"
version = "26.6.0-rc.1"
version = "26.6.0"
dependencies = [
"askama",
"cargo_metadata",
+2 -2
View File
@@ -12,7 +12,7 @@ license = "Apache-2.0"
# See also `rust-toolchain.toml`
readme = "README.md"
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
version = "26.6.0-rc.1"
version = "26.6.0"
[workspace.metadata.crane]
name = "conduwuit"
@@ -570,7 +570,7 @@ features = ["std"]
version = "0.3.0"
[workspace.dependencies.resolvematrix]
version = "1.0.0"
version = "1.1.0"
[workspace.dependencies.serde_urlencoded]
version = "0.7.1"
-1
View File
@@ -1 +0,0 @@
Appservice device management as outlined in MSC4190 (part of Matrix 1.17) is now fully supported. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Improved invite and join reliability in clients using legacy sync. Contributed by @ginger
-1
View File
@@ -1 +0,0 @@
Removed the `/_conduwuit/` versions of the `local_user_count` and `version` routes. These routes are still accessible under the `/_continuwuity` prefix.
-1
View File
@@ -1 +0,0 @@
The invite recipient's membership event is now included in invite stripped state, which should fix flaky invite display in some clients. Contributed by @ginger
-1
View File
@@ -1 +0,0 @@
Switched from Continuwuity's fork of Ruma back to upstream Ruma. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Users may now be forbidden from deactivating their own accounts with the new `allow_deactivation` config option. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Added support for Matrix 1.16's `state_after` feature, allowing clients which understand it to sync room state changes more reliably. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Added support for authenticating clients using the new OAuth 2.0 login API. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Added support for MSC4466, which allows clients to customize how changes to a user's global profile are propagated. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Devices which set their presence as "offline" will no longer be considered for presence updates. Contributed by @timedout.
-1
View File
@@ -1 +0,0 @@
Removed support for guest user registration, a little-used and deprecated approach to room previews.
-1
View File
@@ -1 +0,0 @@
The deprecated `well_known.rtc_focus_server_urls` config option has been removed. MatrixRTC foci should be configured using the `matrix_rtc.foci` config option.
-1
View File
@@ -1 +0,0 @@
The version of Debian that the Docker-based build process uses has been upgraded from Bookworm to Trixie, meaning that standalone binaries now have a minimum glibc of 2.41, and can no longer be used on distro versions from before 2025-01-30
-1
View File
@@ -1 +0,0 @@
Support for server-side blurhashing (part of MSC2448) has been removed.
-1
View File
@@ -1 +0,0 @@
Updated [MSC4284: Policy Servers](https://github.com/matrix-org/matrix-spec-proposals/pull/4284) implementation to support the newly stabilised proposal. Contributed by @nex.
-1
View File
@@ -1 +0,0 @@
Add performance tuning documentation. Contributed by @stratself.
-1
View File
@@ -1 +0,0 @@
Added config option for default room ACLs. Contributed by @eve.
-1
View File
@@ -1 +0,0 @@
Removed support for LDAP.
-1
View File
@@ -1 +0,0 @@
Added support for fallback encryption keys.
-1
View File
@@ -1 +0,0 @@
Fixed a bug that caused the server to drop events during processing if several events for the same room were sent in a singular transaction. Contributed by @nex.
-1
View File
@@ -1 +0,0 @@
Add `!admin users reject-all-invites` to clean invite spam
-1
View File
@@ -1 +0,0 @@
fix `!admin query account-data account-data-get` not returning the content
-9
View File
@@ -1,9 +0,0 @@
Implemented event rejection, which should resolve and prevent future netsplits of the kinds observed
within some Continuwuity rooms.
Also resolved several bugs related to both soft-failing events, and event backfilling, which should
improve state resolution stability.
The `!admin debug get-pdu` command was updated to disambiguate event acceptance status, and
`!admin debug show-auth-chain` was added to visually display event auth chains, which may assist
developers in debugging strangely complex events.
Contributed by @nex.
-1
View File
@@ -1 +0,0 @@
Fixed an issue where Continuwuity would only advertise support for the unstable endpoint for Mutual Rooms (MSC2666), despite only supporting the stable endpoint. Contributed by @Henry-Hiles (QuadRadical)
-1
View File
@@ -1 +0,0 @@
Added example configuration using caddy-docker-proxy in the livekit setup section of the docs. Contributed by @Cease
-1
View File
@@ -1 +0,0 @@
Fixed admin commands being ignored when they had leading whitespace before admin commands. Contributed by @kitvonsnookerz.
-1
View File
@@ -1 +0,0 @@
Fixed several bugs in the `POST /_matrix/client/v3/rooms/{roomId}/upgrade` endpoint. Contributed by @nex.
-1
View File
@@ -1 +0,0 @@
Added full support for [MSC4168: Update `m.space.*` state on room upgrade](https://github.com/matrix-org/matrix-spec-proposals/pull/4168). Contributed by @nex.
-2
View File
@@ -1,2 +0,0 @@
Improved the performance and reliability of fetching missing events, improving network partition recovery. Contributed
by @nex.
-1
View File
@@ -1 +0,0 @@
Remove support for MSC4373, as the MSC is now closed. Contributed by @vel.
-1
View File
@@ -1 +0,0 @@
Added static builds using Nix, allowing for Continuwuity on musl. During this, we also introduced a `max-perf-haswell` package, separating it from `max-perf`, so you may want to swap to this if you are on NixOS. Contributed by @Henry-Hiles (QuadRadical).
-1
View File
@@ -1 +0,0 @@
Added support for MSC4380 invite blocking, which has become part of the Matrix specification in v1.18. Contributed by @nex.
-1
View File
@@ -1 +0,0 @@
Added `!admin debug get-state-at` command
-1
View File
@@ -1 +0,0 @@
Updated deployment docs to account for new RPM package availability across more distros. Contributed by @julian45.
-1
View File
@@ -1 +0,0 @@
Added a configuration option to allow choosing a client IP source that is not the TCP connecting IP. Contributed by @nex.
-1
View File
@@ -1 +0,0 @@
Enable `direct_tls` and more logging by default
+1
View File
@@ -0,0 +1 @@
Replace DNS resolution and caching system with [resolvematrix](https://forgejo.ellis.link/continuwuation/resolvematrix)' built-in one for more correct server resolution. Contributed by @s1lv3r.
-1
View File
@@ -1 +0,0 @@
Added support for linking an external identity provider with OIDC. Contributed by @ginger.
-1
View File
@@ -1 +0,0 @@
Adjusted legacy sync logic to allow the `roomsynctoken_shortstatehash` database column to be dropped, massively reducing database sizes, especially for old deployments. Contributed by @ginger.
+1 -1
View File
@@ -1017,7 +1017,7 @@ pub(super) async fn resolve_true_destination(
.http_client(self.services.client.default.clone())
.build()?
} else {
&self.services.client.resolver
&self.services.client.matrix_resolver
};
let actual = resolver.resolve_server(server_name.as_str()).await?;
+4 -4
View File
@@ -47,7 +47,7 @@ async fn cache(
writeln!(self, "| Server Name | Destination | SNI | Override | Step | Expires |").await?;
writeln!(self, "| ----------- | ----------- | --- | -------- | ---- | ------- |").await?;
let entries = self.services.client.resolver.get_all_cache_entries();
let entries = self.services.client.matrix_resolver.get_all_cache_entries();
for (host, entry) in entries {
if let Some(ors) = overrides
@@ -81,13 +81,13 @@ async fn cache(
async fn flush_cache(&self, name: Option<OwnedServerName>, all: bool) -> Result {
if all {
self.services.client.resolver.clear_cache();
self.services.client.dns.clear_cache();
self.services.client.matrix_resolver.clear_cache();
self.services.client.dns_resolver.clear_cache();
writeln!(self, "Resolver and DNS caches cleared!").await
} else if let Some(name) = name {
self.services
.client
.resolver
.matrix_resolver
.remove_cache_entry(name.as_str());
self.write_str(&format!("Cleared {name} from resolver caches!"))
.await
+1 -1
View File
@@ -2497,7 +2497,7 @@ pub struct OidcConfig {
/// automatically fetch the identity provider's metadata from this URL.
/// Generally you should set this to the base domain your identity provider
/// runs on.
pub discovery_url: Url,
pub discovery_url: String,
/// The OAuth client ID for Continuwuity to use when communicating with the
/// identity provider.
-108
View File
@@ -1,108 +0,0 @@
use std::{net::SocketAddr, sync::Arc, time::Duration};
use conduwuit::{Result, Server, err};
use futures::FutureExt;
use hickory_resolver::{
TokioResolver, config::ConnectionConfig, lookup_ip::LookupIp,
net::runtime::TokioRuntimeProvider,
};
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
pub struct Resolver {
pub(crate) resolver: Arc<TokioResolver>,
server: Arc<Server>,
}
type ResolvingResult = Result<Addrs, Box<dyn std::error::Error + Send + Sync>>;
impl Resolver {
#[allow(clippy::as_conversions, clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub(super) fn build(server: &Arc<Server>) -> Result<Arc<Self>> {
let config = &server.config;
let (sys_conf, mut opts) = hickory_resolver::system_conf::read_system_conf()
.map_err(|e| err!(error!("Failed to configure DNS resolver from system: {e}")))?;
let mut conf = hickory_resolver::config::ResolverConfig::default();
if let Some(domain) = sys_conf.domain() {
conf.set_domain(domain.clone());
}
for sys_conf in sys_conf.search() {
conf.add_search(sys_conf.clone());
}
for sys_conf in sys_conf.name_servers() {
let mut ns = sys_conf.clone();
if config.query_over_tcp_only {
ns.connections = vec![ConnectionConfig::tcp()];
}
ns.trust_negative_responses = !config.query_all_nameservers;
conf.add_name_server(ns);
}
opts.cache_size = u64::from(config.dns_cache_entries);
opts.preserve_intermediates = true;
opts.negative_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain));
opts.negative_max_ttl = Some(Duration::from_hours(720));
opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl));
opts.positive_max_ttl = Some(Duration::from_hours(168));
opts.timeout = Duration::from_secs(config.dns_timeout);
opts.attempts = config.dns_attempts as usize;
opts.try_tcp_on_error = config.dns_tcp_fallback;
opts.num_concurrent_reqs = 1;
opts.edns0 = true;
opts.case_randomization = true;
opts.ip_strategy = match config.ip_lookup_strategy {
| 1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only,
| 2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only,
| 3 => hickory_resolver::config::LookupIpStrategy::Ipv4AndIpv6,
| 4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4,
| _ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6,
};
let runtime_provider = TokioRuntimeProvider::new();
let mut builder = TokioResolver::builder_with_config(conf, runtime_provider);
*builder.options_mut() = opts;
let resolver = Arc::new(builder.build().expect("failed to build resolver :("));
Ok(Arc::new(Self { resolver, server: server.clone() }))
}
/// Clear the in-memory hickory-dns caches
#[inline]
pub fn clear_cache(&self) { self.resolver.clear_cache(); }
}
impl Resolve for Resolver {
fn resolve(&self, name: Name) -> Resolving {
resolve_to_reqwest(self.server.clone(), self.resolver.clone(), name).boxed()
}
}
async fn resolve_to_reqwest(
server: Arc<Server>,
resolver: Arc<TokioResolver>,
name: Name,
) -> ResolvingResult {
use std::{io, io::ErrorKind::Interrupted};
let handle_shutdown = || Box::new(io::Error::new(Interrupted, "Server shutting down"));
let handle_results = |results: LookupIp| {
Box::new(
results
.iter()
.collect::<Vec<_>>()
.into_iter()
.map(|ip| SocketAddr::new(ip, 0)),
)
};
tokio::select! {
results = resolver.lookup_ip(name.as_str()) => Ok(handle_results(results?)),
() = server.until_shutdown() => Err(handle_shutdown()),
}
}
+84 -23
View File
@@ -1,19 +1,20 @@
mod dns;
use std::{sync::Arc, time::Duration};
use async_trait::async_trait;
use conduwuit::{Config, Result, err, trace};
use conduwuit::{Config, Result, Server, err, trace};
use either::Either;
use hickory_resolver::{
TokioResolver, config::ConnectionConfig, net::runtime::TokioRuntimeProvider,
};
use ipaddress::IPAddress;
use reqwest::redirect;
use resolvematrix::server::{MatrixResolver, MatrixResolverBuilder};
use crate::{client::dns::Resolver, service};
use crate::service;
pub struct Service {
pub resolver: MatrixResolver,
pub dns: Arc<Resolver>,
pub matrix_resolver: Arc<MatrixResolver>,
pub dns_resolver: Arc<TokioResolver>,
pub default: reqwest::Client,
pub url_preview: reqwest::Client,
@@ -31,8 +32,10 @@ pub struct Service {
impl crate::Service for Service {
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
let config = &args.server.config;
let dns = Resolver::build(args.server)?;
let resolver = MatrixResolverBuilder::new()
let dns_resolver = get_dns_resolver(args.server)?;
let matrix_resolver = Arc::new(MatrixResolverBuilder::new()
.dangerous_tls_accept_invalid_certs(args.server.config.allow_invalid_tls_certificates_yes_i_know_what_the_fuck_i_am_doing_with_this_and_i_know_this_is_insecure)
.http_client(
base(&args.server.config)?
@@ -43,8 +46,9 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.redirect(redirect::Policy::limited(4))
.build()?
)
.dns_resolver(dns.resolver.clone())
.build()?;
.dns_resolver(dns_resolver.clone())
.build()?);
let matrix_dns_resolver = matrix_resolver.create_dns_resolver();
let url_preview_bind_addr = config
.url_preview_bound_interface
@@ -62,29 +66,31 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.unwrap_or_else(|| conduwuit::user_agent_media().to_owned());
Ok(Arc::new(Self {
resolver,
dns: dns.clone(),
matrix_resolver,
dns_resolver,
default: base(config)?.dns_resolver(dns.clone()).build()?,
default: base(config)?
.dns_resolver(matrix_dns_resolver.clone())
.build()?,
url_preview: base(config)
.and_then(|builder| {
builder_interface(builder, url_preview_bind_iface.as_deref())
})?
.local_address(url_preview_bind_addr)
.dns_resolver(dns.clone())
.dns_resolver(matrix_dns_resolver.clone())
.timeout(Duration::from_secs(config.url_preview_timeout))
.redirect(redirect::Policy::limited(3))
.user_agent(url_preview_user_agent)
.build()?,
extern_media: base(config)?
.dns_resolver(dns.clone())
.dns_resolver(matrix_dns_resolver.clone())
.redirect(redirect::Policy::limited(3))
.build()?,
federation: base(config)?
.dns_resolver(dns.clone())
.dns_resolver(matrix_dns_resolver.clone())
.connect_timeout(Duration::from_secs(config.federation_conn_timeout))
.read_timeout(Duration::from_secs(config.federation_timeout))
.timeout(Duration::from_secs(
@@ -98,7 +104,7 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.build()?,
federation_slow: base(config)?
.dns_resolver(dns.clone())
.dns_resolver(matrix_dns_resolver.clone())
.connect_timeout(Duration::from_secs(config.federation_conn_timeout))
.read_timeout(Duration::from_secs(config.federation_timeout.saturating_mul(6)))
.timeout(Duration::from_secs(
@@ -112,7 +118,7 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.build()?,
sender: base(config)?
.dns_resolver(dns.clone())
.dns_resolver(matrix_dns_resolver.clone())
.connect_timeout(Duration::from_secs(config.federation_conn_timeout))
.read_timeout(Duration::from_secs(config.sender_timeout))
.timeout(Duration::from_secs(config.sender_timeout))
@@ -122,7 +128,7 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.build()?,
appservice: base(config)?
.dns_resolver(dns.clone())
.dns_resolver(matrix_dns_resolver.clone())
.connect_timeout(Duration::from_secs(5))
.read_timeout(Duration::from_secs(config.appservice_timeout))
.timeout(Duration::from_secs(config.appservice_timeout))
@@ -132,7 +138,7 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.build()?,
pusher: base(config)?
.dns_resolver(dns)
.dns_resolver(matrix_dns_resolver)
.connect_timeout(Duration::from_secs(config.pusher_conn_timeout))
.timeout(Duration::from_secs(config.pusher_timeout))
.pool_max_idle_per_host(1)
@@ -151,11 +157,11 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
}
async fn clear_cache(&self) {
self.resolver.clear_cache();
self.dns.resolver.clear_cache();
self.matrix_resolver.clear_cache();
self.dns_resolver.clear_cache();
}
fn name(&self) -> &str { service::make_name(std::module_path!()) }
fn name(&self) -> &str { service::make_name(module_path!()) }
}
impl Service {
@@ -254,3 +260,58 @@ fn builder_interface(
Ok(builder)
}
}
fn get_dns_resolver(server: &Arc<Server>) -> Result<Arc<TokioResolver>> {
let config = &server.config;
let (sys_conf, mut opts) = hickory_resolver::system_conf::read_system_conf()
.map_err(|e| err!(error!("Failed to configure DNS resolver from system: {e}")))?;
let mut conf = hickory_resolver::config::ResolverConfig::default();
if let Some(domain) = sys_conf.domain() {
conf.set_domain(domain.clone());
}
for sys_conf in sys_conf.search() {
conf.add_search(sys_conf.clone());
}
for sys_conf in sys_conf.name_servers() {
let mut ns = sys_conf.clone();
if config.query_over_tcp_only {
ns.connections = vec![ConnectionConfig::tcp()];
}
ns.trust_negative_responses = !config.query_all_nameservers;
conf.add_name_server(ns);
}
opts.cache_size = u64::from(config.dns_cache_entries);
opts.preserve_intermediates = true;
opts.negative_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain));
opts.negative_max_ttl = Some(Duration::from_hours(720));
opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl));
opts.positive_max_ttl = Some(Duration::from_hours(168));
opts.timeout = Duration::from_secs(config.dns_timeout);
opts.attempts = config.dns_attempts.into();
opts.try_tcp_on_error = config.dns_tcp_fallback;
opts.num_concurrent_reqs = 1;
opts.edns0 = true;
opts.case_randomization = true;
opts.ip_strategy = match config.ip_lookup_strategy {
| 1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only,
| 2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only,
| 3 => hickory_resolver::config::LookupIpStrategy::Ipv4AndIpv6,
| 4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4,
| _ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6,
};
let runtime_provider = TokioRuntimeProvider::new();
let mut builder = TokioResolver::builder_with_config(conf, runtime_provider);
*builder.options_mut() = opts;
let resolver = Arc::new(builder.build().expect("failed to build resolver :("));
Ok(resolver)
}
+1 -1
View File
@@ -134,7 +134,7 @@ pub async fn execute_on<'i, T, PathBuilderInput>(
let actual = self
.services
.client
.resolver
.matrix_resolver
.resolve_server(dest.as_str())
.await?;
+2 -1
View File
@@ -172,7 +172,8 @@ async fn worker(self: Arc<Self>) -> Result {
.expect("redirect url should be valid");
let provider_metadata = CoreProviderMetadata::discover_async(
IssuerUrl::from_url(config.discovery_url.clone()),
IssuerUrl::new(config.discovery_url.clone())
.map_err(|err| err!("Failed to parse OIDC discovery URL: {err}"))?,
client,
)
.await
@@ -4,83 +4,18 @@
};
use conduwuit::{
Err, Event, PduEvent, Result, debug, debug_error, debug_info, debug_warn, defer, err, error,
info, matrix::PartialPdu, result::DebugInspect, trace, utils::time::jitter, warn,
Err, Event, Result, debug, debug_error, debug_warn, defer, err, error, info,
matrix::PartialPdu, result::DebugInspect, trace, utils::time::jitter, warn,
};
use futures::{
FutureExt, StreamExt,
future::{OptionFuture, try_join4},
};
use ruma::{
CanonicalJsonValue, EventId, OwnedUserId, RoomId, ServerName, UserId,
events::{
TimelineEventType,
room::member::{MembershipState, RoomMemberEventContent},
},
};
use ruma::{CanonicalJsonValue, EventId, OwnedUserId, RoomId, ServerName, UserId};
use tokio::sync::mpsc;
use crate::rooms::timeline::{RawPduId, pdu_fits};
async fn should_rescind_invite(
services: &crate::rooms::event_handler::Services,
content: &mut BTreeMap<String, CanonicalJsonValue>,
sender: &UserId,
room_id: &RoomId,
) -> Result<Option<PduEvent>> {
// We insert a bogus event ID since we can't actually calculate the right one
content.insert("event_id".to_owned(), CanonicalJsonValue::String("$rescind".to_owned()));
let pdu_event = serde_json::from_value::<PduEvent>(
serde_json::to_value(&content).expect("CanonicalJsonObj is a valid JsonValue"),
)
.map_err(|e| err!("invalid PDU: {e}"))?;
if pdu_event.room_id().is_none_or(|r| r != room_id)
&& pdu_event.sender() != sender
&& pdu_event.event_type() != &TimelineEventType::RoomMember
&& pdu_event.state_key().is_none_or(|v| v == sender.as_str())
{
return Ok(None);
}
let target_user_id = UserId::parse(pdu_event.state_key().unwrap())?;
if pdu_event
.get_content::<RoomMemberEventContent>()?
.membership
!= MembershipState::Leave
{
return Ok(None); // Not a leave event
}
// Does the target user have a pending invite?
let Ok(pending_invite_state) = services
.state_cache
.invite_state(&target_user_id, room_id)
.await
else {
return Ok(None); // No pending invite, so nothing to rescind
};
for event in pending_invite_state {
if event
.get_field::<String>("type")?
.is_some_and(|t| t == "m.room.member")
|| event
.get_field::<OwnedUserId>("state_key")?
.is_some_and(|s| s == *target_user_id)
|| event
.get_field::<OwnedUserId>("sender")?
.is_some_and(|s| s == *sender)
|| event
.get_field::<RoomMemberEventContent>("content")?
.is_some_and(|c| c.membership == MembershipState::Invite)
{
return Ok(Some(pdu_event));
}
}
Ok(None)
}
impl super::Service {
/// When receiving an event one needs to:
/// 0. Check the server is in the room
@@ -183,28 +118,6 @@ pub async fn handle_incoming_pdu<'a>(
.server_in_room(self.services.globals.server_name(), room_id)
.await
{
// Is this a federated invite rescind?
// copied from https://github.com/element-hq/synapse/blob/7e4588a/synapse/handlers/federation_event.py#L255-L300
if value.get("type").and_then(|t| t.as_str()) == Some("m.room.member") {
if let Some(pdu) =
should_rescind_invite(&self.services, &mut value.clone(), &sender, room_id)
.await?
{
debug_info!(
"Invite to {room_id} appears to have been rescinded by {sender}, \
marking as left"
);
self.services
.state_cache
.mark_as_left(&sender, room_id, Some(pdu))
.await;
self.services.sync.wake(&sender).await;
return Ok(None);
}
}
info!(
%origin,
%room_id,
+1 -3
View File
@@ -24,7 +24,7 @@
};
use tokio::sync::{Notify, mpsc};
use crate::{Dep, globals, rooms, sending, server_keys, sync};
use crate::{Dep, globals, rooms, sending, server_keys};
pub struct Service {
pub mutex_federation: RoomMutexMap,
pub federation_handletime: SyncRwLock<HandleTimeMap>,
@@ -47,7 +47,6 @@ struct Services {
state_cache: Dep<rooms::state_cache::Service>,
state_accessor: Dep<rooms::state_accessor::Service>,
state_compressor: Dep<rooms::state_compressor::Service>,
sync: Dep<sync::Service>,
timeline: Dep<rooms::timeline::Service>,
server: Arc<Server>,
}
@@ -78,7 +77,6 @@ fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
.depend::<rooms::state_accessor::Service>("rooms::state_accessor"),
state_compressor: args
.depend::<rooms::state_compressor::Service>("rooms::state_compressor"),
sync: args.depend::<sync::Service>("sync"),
timeline: args.depend::<rooms::timeline::Service>("rooms::timeline"),
server: args.server.clone(),
},