diff --git a/src/api/client/account.rs b/src/api/client/account.rs index 940d2a9b..6c283b10 100644 --- a/src/api/client/account.rs +++ b/src/api/client/account.rs @@ -161,16 +161,32 @@ pub(crate) async fn register_route( if !services.config.allow_registration && body.appservice_info.is_none() { match (body.username.as_ref(), body.initial_device_display_name.as_ref()) { | (Some(username), Some(device_display_name)) => { - info!(%is_guest, user = %username, device_name = %device_display_name, "Rejecting registration attempt as registration is disabled"); + info!( + %is_guest, + user = %username, + device_name = %device_display_name, + "Rejecting registration attempt as registration is disabled" + ); }, | (Some(username), _) => { - info!(%is_guest, user = %username, "Rejecting registration attempt as registration is disabled"); + info!( + %is_guest, + user = %username, + "Rejecting registration attempt as registration is disabled" + ); }, | (_, Some(device_display_name)) => { - info!(%is_guest, device_name = %device_display_name, "Rejecting registration attempt as registration is disabled"); + info!( + %is_guest, + device_name = %device_display_name, + "Rejecting registration attempt as registration is disabled" + ); }, | (None, _) => { - info!(%is_guest, "Rejecting registration attempt as registration is disabled"); + info!( + %is_guest, + "Rejecting registration attempt as registration is disabled" + ); }, } @@ -879,6 +895,7 @@ pub async fn full_user_deactivate( .deactivate_account(user_id) .await .ok(); + super::update_displayname(services, user_id, None, all_joined_rooms).await; super::update_avatar_url(services, user_id, None, None, all_joined_rooms).await; diff --git a/src/api/client/profile.rs b/src/api/client/profile.rs index 5cdffdde..046cc983 100644 --- a/src/api/client/profile.rs +++ b/src/api/client/profile.rs @@ -199,11 +199,9 @@ pub(crate) async fn get_avatar_url_route( services .users .set_displayname(&body.user_id, response.displayname.clone()); - services .users .set_avatar_url(&body.user_id, response.avatar_url.clone()); - services .users .set_blurhash(&body.user_id, response.blurhash.clone()); @@ -263,15 +261,12 @@ pub(crate) async fn get_profile_route( services .users .set_displayname(&body.user_id, response.displayname.clone()); - services .users .set_avatar_url(&body.user_id, response.avatar_url.clone()); - services .users .set_blurhash(&body.user_id, response.blurhash.clone()); - services .users .set_timezone(&body.user_id, response.tz.clone()); diff --git a/src/api/client/report.rs b/src/api/client/report.rs index 2c709385..4fc6d7d7 100644 --- a/src/api/client/report.rs +++ b/src/api/client/report.rs @@ -191,5 +191,6 @@ async fn delay_response() { "Got successful /report request, waiting {time_to_wait} seconds before sending \ successful response." ); + sleep(Duration::from_secs(time_to_wait)).await; } diff --git a/src/api/client/room/summary.rs b/src/api/client/room/summary.rs index c6f055eb..33b4ef65 100644 --- a/src/api/client/room/summary.rs +++ b/src/api/client/room/summary.rs @@ -118,10 +118,12 @@ async fn local_room_summary_response( .rooms .state_accessor .get_join_rules(room_id); + let world_readable = services .rooms .state_accessor .is_world_readable(room_id); + let guest_can_join = services .rooms .state_accessor @@ -129,8 +131,8 @@ async fn local_room_summary_response( let (join_rule, world_readable, guest_can_join) = join3(join_rule, world_readable, guest_can_join).await; - trace!("{join_rule:?}, {world_readable:?}, {guest_can_join:?}"); + trace!("{join_rule:?}, {world_readable:?}, {guest_can_join:?}"); user_can_see_summary( services, room_id, diff --git a/src/core/config/proxy.rs b/src/core/config/proxy.rs index a8023b46..b773207c 100644 --- a/src/core/config/proxy.rs +++ b/src/core/config/proxy.rs @@ -91,10 +91,7 @@ impl PartialProxyConfig { } } match (included_because, excluded_because) { - | (Some(a), Some(b)) if a.more_specific_than(b) => Some(&self.url), /* included for - * a more specific - * reason */ - // than excluded + | (Some(a), Some(b)) if a.more_specific_than(b) => Some(&self.url), | (Some(_), None) => Some(&self.url), | _ => None, } diff --git a/src/core/info/cargo.rs b/src/core/info/cargo.rs index 6da8fc30..825c56b0 100644 --- a/src/core/info/cargo.rs +++ b/src/core/info/cargo.rs @@ -87,10 +87,12 @@ fn append_features(features: &mut Vec, manifest: &str) -> Result<()> { fn init_dependencies() -> Result { let manifest = Manifest::from_str(WORKSPACE_MANIFEST)?; - Ok(manifest + let deps_set = manifest .workspace .as_ref() .expect("manifest has workspace section") .dependencies - .clone()) + .clone(); + + Ok(deps_set) } diff --git a/src/core/mods/module.rs b/src/core/mods/module.rs index b65bbca2..bcadf5aa 100644 --- a/src/core/mods/module.rs +++ b/src/core/mods/module.rs @@ -44,6 +44,7 @@ impl Module { .handle .as_ref() .expect("backing library loaded by this instance"); + // SAFETY: Calls dlsym(3) on unix platforms. This might not have to be unsafe // if wrapped in libloading with_dlerror(). let sym = unsafe { handle.get::(cname.as_bytes()) }; diff --git a/src/core/mods/path.rs b/src/core/mods/path.rs index d2319a64..502e6fca 100644 --- a/src/core/mods/path.rs +++ b/src/core/mods/path.rs @@ -27,6 +27,7 @@ pub fn to_name(path: &OsStr) -> Result { .expect("path file stem") .to_str() .expect("name string"); + let name = name .strip_prefix("lib") .unwrap_or(name) diff --git a/src/core/utils/html.rs b/src/core/utils/html.rs index f2b6d861..eac4c47f 100644 --- a/src/core/utils/html.rs +++ b/src/core/utils/html.rs @@ -23,8 +23,10 @@ impl fmt::Display for Escape<'_> { | '"' => """, | _ => continue, }; + fmt.write_str(&pile_o_bits[last..i])?; fmt.write_str(s)?; + // NOTE: we only expect single byte characters here - which is fine as long as // we only match single byte characters last = i.saturating_add(1); diff --git a/src/core/utils/json.rs b/src/core/utils/json.rs index 3f2f225e..df4ccd13 100644 --- a/src/core/utils/json.rs +++ b/src/core/utils/json.rs @@ -1,4 +1,4 @@ -use std::{fmt, str::FromStr}; +use std::{fmt, marker::PhantomData, str::FromStr}; use ruma::{CanonicalJsonError, CanonicalJsonObject, canonical_json::try_from_json_map}; @@ -11,25 +11,28 @@ use crate::Result; pub fn to_canonical_object( value: T, ) -> Result { + use CanonicalJsonError::SerDe; use serde::ser::Error; - match serde_json::to_value(value).map_err(CanonicalJsonError::SerDe)? { + match serde_json::to_value(value).map_err(SerDe)? { | serde_json::Value::Object(map) => try_from_json_map(map), - | _ => - Err(CanonicalJsonError::SerDe(serde_json::Error::custom("Value must be an object"))), + | _ => Err(SerDe(serde_json::Error::custom("Value must be an object"))), } } -pub fn deserialize_from_str< - 'de, +pub fn deserialize_from_str<'de, D, T, E>(deserializer: D) -> Result +where D: serde::de::Deserializer<'de>, T: FromStr, E: fmt::Display, ->( - deserializer: D, -) -> Result { - struct Visitor, E>(std::marker::PhantomData); - impl, Err: fmt::Display> serde::de::Visitor<'_> for Visitor { +{ + struct Visitor, E>(PhantomData); + + impl serde::de::Visitor<'_> for Visitor + where + T: FromStr, + Err: fmt::Display, + { type Value = T; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -43,5 +46,6 @@ pub fn deserialize_from_str< v.parse().map_err(serde::de::Error::custom) } } - deserializer.deserialize_str(Visitor(std::marker::PhantomData)) + + deserializer.deserialize_str(Visitor(PhantomData)) } diff --git a/src/core/utils/time.rs b/src/core/utils/time.rs index 9ba67207..c78eed48 100644 --- a/src/core/utils/time.rs +++ b/src/core/utils/time.rs @@ -109,14 +109,11 @@ pub fn whole_unit(d: Duration) -> Unit { | 86_400.. => Days(d.as_secs() / 86_400), | 3_600..=86_399 => Hours(d.as_secs() / 3_600), | 60..=3_599 => Mins(d.as_secs() / 60), - | _ => match d.as_micros() { | 1_000_000.. => Secs(d.as_secs()), | 1_000..=999_999 => Millis(d.subsec_millis().into()), - | _ => match d.as_nanos() { | 1_000.. => Micros(d.subsec_micros().into()), - | _ => Nanos(d.subsec_nanos().into()), }, }, diff --git a/src/database/watchers.rs b/src/database/watchers.rs index 9477db1b..d40d673c 100644 --- a/src/database/watchers.rs +++ b/src/database/watchers.rs @@ -42,7 +42,6 @@ impl Watchers { pub(crate) fn wake(&self, key: &[u8]) { let watchers = self.watchers.read().unwrap(); let mut triggered = Vec::new(); - for length in 0..=key.len() { if watchers.contains_key(&key[..length]) { triggered.push(&key[..length]); diff --git a/src/main/logging.rs b/src/main/logging.rs index 2334ad2b..5122b377 100644 --- a/src/main/logging.rs +++ b/src/main/logging.rs @@ -22,10 +22,12 @@ pub(crate) fn init( let reload_handles = LogLevelReloadHandles::default(); let console_span_events = fmt_span::from_str(&config.log_span_events).unwrap_or_err(); + let console_filter = EnvFilter::builder() .with_regex(config.log_filter_regex) .parse(&config.log) .map_err(|e| err!(Config("log", "{e}.")))?; + let console_layer = fmt::Layer::new() .with_span_events(console_span_events) .event_format(ConsoleFormat::new(config)) @@ -34,6 +36,7 @@ pub(crate) fn init( let (console_reload_filter, console_reload_handle) = reload::Layer::new(console_filter.clone()); + reload_handles.add("console", Box::new(console_reload_handle)); let cap_state = Arc::new(capture::State::new()); @@ -47,8 +50,10 @@ pub(crate) fn init( let subscriber = { let sentry_filter = EnvFilter::try_new(&config.sentry_filter) .map_err(|e| err!(Config("sentry_filter", "{e}.")))?; + let sentry_layer = sentry_tracing::layer(); let (sentry_reload_filter, sentry_reload_handle) = reload::Layer::new(sentry_filter); + reload_handles.add("sentry", Box::new(sentry_reload_handle)); subscriber.with(sentry_layer.with_filter(sentry_reload_filter)) }; @@ -58,12 +63,15 @@ pub(crate) fn init( let (flame_layer, flame_guard) = if config.tracing_flame { let flame_filter = EnvFilter::try_new(&config.tracing_flame_filter) .map_err(|e| err!(Config("tracing_flame_filter", "{e}.")))?; + let (flame_layer, flame_guard) = tracing_flame::FlameLayer::with_file(&config.tracing_flame_output_path) .map_err(|e| err!(Config("tracing_flame_output_path", "{e}.")))?; + let flame_layer = flame_layer .with_empty_samples(false) .with_filter(flame_filter); + (Some(flame_layer), Some(flame_guard)) } else { (None, None) @@ -71,19 +79,24 @@ pub(crate) fn init( let jaeger_filter = EnvFilter::try_new(&config.jaeger_filter) .map_err(|e| err!(Config("jaeger_filter", "{e}.")))?; + let jaeger_layer = config.allow_jaeger.then(|| { opentelemetry::global::set_text_map_propagator( opentelemetry_jaeger::Propagator::new(), ); + let tracer = opentelemetry_jaeger::new_agent_pipeline() .with_auto_split_batch(true) .with_service_name("tuwunel") .install_batch(opentelemetry_sdk::runtime::Tokio) .expect("jaeger agent pipeline"); + let telemetry = tracing_opentelemetry::layer().with_tracer(tracer); + let (jaeger_reload_filter, jaeger_reload_handle) = reload::Layer::new(jaeger_filter.clone()); reload_handles.add("jaeger", Box::new(jaeger_reload_handle)); + Some(telemetry.with_filter(jaeger_reload_filter)) }); diff --git a/src/main/mods.rs b/src/main/mods.rs index 98eeed7f..181d6b37 100644 --- a/src/main/mods.rs +++ b/src/main/mods.rs @@ -51,10 +51,12 @@ pub(crate) async fn run(server: &Arc, starts: bool) -> Result<(bool, boo }, }; } + server .server .stopping .store(false, Ordering::Release); + let run = main_mod.get::("run")?; if let Err(error) = run(server .services @@ -67,10 +69,12 @@ pub(crate) async fn run(server: &Arc, starts: bool) -> Result<(bool, boo error!("Running server: {error}"); return Err(error); } + let reloads = server .server .reloading .swap(false, Ordering::AcqRel); + let stops = !reloads || stale(server).await? <= restart_thresh(); let starts = reloads && stops; if stops { diff --git a/src/main/sentry.rs b/src/main/sentry.rs index b4c5f54a..ac17d962 100644 --- a/src/main/sentry.rs +++ b/src/main/sentry.rs @@ -37,11 +37,13 @@ fn options(config: &Config) -> ClientOptions { .expect("init_sentry should only be called if sentry is enabled and this is not None") .as_str(); + let server_name = config + .sentry_send_server_name + .then(|| config.server_name.to_string().into()); + ClientOptions { dsn: Some(Dsn::from_str(dsn).expect("sentry_endpoint must be a valid URL")), - server_name: config - .sentry_send_server_name - .then(|| config.server_name.to_string().into()), + server_name, traces_sample_rate: config.sentry_traces_sample_rate, debug: cfg!(debug_assertions), release: sentry::release_name!(), diff --git a/src/main/server.rs b/src/main/server.rs index afbd5ff9..fe8c7e1b 100644 --- a/src/main/server.rs +++ b/src/main/server.rs @@ -69,11 +69,10 @@ impl Server { tuwunel_core::version(), ); + let logger = Log { reload: tracing_reload_handle, capture }; + Ok(Arc::new(Self { - server: Arc::new(tuwunel_core::Server::new(config, runtime.cloned(), Log { - reload: tracing_reload_handle, - capture, - })), + server: Arc::new(tuwunel_core::Server::new(config, runtime.cloned(), logger)), services: None.into(), diff --git a/src/router/request.rs b/src/router/request.rs index d927dcc5..272a966f 100644 --- a/src/router/request.rs +++ b/src/router/request.rs @@ -98,10 +98,10 @@ async fn execute( fn handle_result(method: &Method, uri: &Uri, result: Response) -> Result { let status = result.status(); + let code = status.as_u16(); let reason = status .canonical_reason() .unwrap_or("Unknown Reason"); - let code = status.as_u16(); if status.is_server_error() { error!(method = ?method, uri = ?uri, "{code} {reason}");