Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable caching in hickory-dns with configurables. #230

Merged
merged 9 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# .git-blame-ignore-revs
# adds a proper rustfmt.toml and formats the entire codebase
1d1ac065141181438e744e7d8abd0e45f75a2f91
# use chain_width 60
162948313c212193965dece50b816ef0903172ba
49 changes: 37 additions & 12 deletions conduwuit-example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -361,21 +361,21 @@ url_preview_check_root_domain = false
# Defaults to false as this uses more CPU when compressing.
#rocksdb_bottommost_compression = false

# RocksDB WAL recovery mode
# Database recovery mode (for RocksDB WAL corruption)
#
# If the database becomes corrupted, an attempt at some form of recovery or at least opening it can be made
# using this config option.
# Use this option when the server reports corruption and refuses to start. Set mode 2 (PointInTime)
# to cleanly recover from this corruption. The server will continue from the last good state,
# several seconds or minutes prior to the crash. Clients may have to run "clear-cache & reload" to
# account for the rollback. Upon success, you may reset the mode back to default and restart again.
# Please note in some cases the corruption error may not be cleared for at least 30 minutes of
# operation in PointInTime mode.
#
# In this event, provided that you have searched for any backups already, it's recommended to start by using PointInTime recovery mode. If this opens your database successfully,
# you will want to immediately run the `clear-cache` database admin command and restart Conduwuit again setting this back to 1 (TolerateCorruptedTailRecords)
# If no further issues arrise, your database should be okay now.
#
# As a very last ditch effort, if PointInTime does not fix or resolve anything, you can try SkipAnyCorruptedRecord but this
# has a good chance to do more damage than before
#
# TolerateCorruptedTailRecords is the default as generally tail records may be caused by unclean shutdowns, and any data here is likely
# federation data that can be re-retrieved by other servers again.
# As a very last ditch effort, if PointInTime does not fix or resolve anything, you can try mode
# 3 (SkipAnyCorruptedRecord) but this will leave the server in a potentially inconsistent state.
#
# The default mode 1 (TolerateCorruptedTailRecords) will automatically drop the last entry in the
# database if corrupted during shutdown, but nothing more. It is extraordinarily unlikely this will
# desynchronize clients. To disable any form of silent rollback set mode 0 (AbsoluteConsistency).
#
# The options are:
# 0 = AbsoluteConsistency
Expand All @@ -390,6 +390,31 @@ url_preview_check_root_domain = false



### Domain Name Resolution and Caching

# Maximum entries stored in DNS memory-cache. The size of an entry may vary so please take care if
# raising this value excessively. Only decrease this when using an external DNS cache. Please note
# that systemd does *not* count as an external cache, even when configured to do so.
#dns_cache_entries = 12288

# Minimum time-to-live in seconds for entries in the DNS cache. The default may appear high to most
# administrators; this is by design. Only decrease this if you are using an external DNS cache.
#dns_min_ttl = 60 * 90

# Minimum time-to-live in seconds for NXDOMAIN entries in the DNS cache. This value is critical for
# the server to federate efficiently. NXDOMAIN's are assumed to not be returning to the federation
# and aggressively cached rather than constantly rechecked.
#dns_min_ttl_nxdomain = 60 * 60 * 24 * 3

# The number of seconds to wait for a reply to a DNS query. Please note that recursive queries can
# take up to several seconds for some domains, so this value should not be too low.
#dns_timeout = 5

# Number of retries after a timeout.
#dns_attempts = 5



### Request Timeouts, Connection Timeouts, and Connection Pooling

## Request Timeouts are HTTP response timeouts
Expand Down
3 changes: 2 additions & 1 deletion rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ group_imports = "StdExternalCrate"
newline_style = "Unix"
use_field_init_shorthand = true
use_small_heuristics = "Off"
use_try_shorthand = true
use_try_shorthand = true
chain_width = 60
26 changes: 21 additions & 5 deletions src/api/appservice_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ where
"?"
};

parts.path_and_query = Some((old_path_and_query + symbol + "access_token=" + hs_token).parse().unwrap());
parts.path_and_query = Some(
(old_path_and_query + symbol + "access_token=" + hs_token)
.parse()
.unwrap(),
);
*http_request.uri_mut() = parts.try_into().expect("our manipulation is always valid");

let mut reqwest_request =
Expand Down Expand Up @@ -64,7 +68,13 @@ where
}
}

let mut response = match services().globals.client.appservice.execute(reqwest_request).await {
let mut response = match services()
.globals
.client
.appservice
.execute(reqwest_request)
.await
{
Ok(r) => r,
Err(e) => {
warn!(
Expand All @@ -77,10 +87,14 @@ where

// reqwest::Response -> http::Response conversion
let status = response.status();
let mut http_response_builder = http::Response::builder().status(status).version(response.version());
let mut http_response_builder = http::Response::builder()
.status(status)
.version(response.version());
mem::swap(
response.headers_mut(),
http_response_builder.headers_mut().expect("http::response::Builder is usable"),
http_response_builder
.headers_mut()
.expect("http::response::Builder is usable"),
);

let body = response.bytes().await.unwrap_or_else(|e| {
Expand All @@ -99,7 +113,9 @@ where
}

let response = T::IncomingResponse::try_from_http_response(
http_response_builder.body(body).expect("reqwest body is valid http body"),
http_response_builder
.body(body)
.expect("reqwest body is valid http body"),
);

Some(response.map_err(|_| {
Expand Down
100 changes: 74 additions & 26 deletions src/api/client_server/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ pub async fn get_register_available_route(
return Err(Error::BadRequest(ErrorKind::UserInUse, "Desired user ID is already taken."));
}

if services().globals.forbidden_usernames().is_match(user_id.localpart()) {
if services()
.globals
.forbidden_usernames()
.is_match(user_id.localpart())
{
return Err(Error::BadRequest(ErrorKind::Unknown, "Username is forbidden."));
}

Expand Down Expand Up @@ -129,7 +133,11 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
return Err(Error::BadRequest(ErrorKind::UserInUse, "Desired user ID is already taken."));
}

if services().globals.forbidden_usernames().is_match(proposed_user_id.localpart()) {
if services()
.globals
.forbidden_usernames()
.is_match(proposed_user_id.localpart())
{
return Err(Error::BadRequest(ErrorKind::Unknown, "Username is forbidden."));
}

Expand Down Expand Up @@ -220,7 +228,10 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
displayname.push_str(&(" ".to_owned() + services().globals.new_user_displayname_suffix()));
}

services().users.set_displayname(&user_id, Some(displayname.clone())).await?;
services()
.users
.set_displayname(&user_id, Some(displayname.clone()))
.await?;

// Initial account data
services().account_data.update(
Expand Down Expand Up @@ -258,31 +269,45 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe
let token = utils::random_string(TOKEN_LENGTH);

// Create device for this account
services().users.create_device(&user_id, &device_id, &token, body.initial_device_display_name.clone())?;
services()
.users
.create_device(&user_id, &device_id, &token, body.initial_device_display_name.clone())?;

info!("New user \"{}\" registered on this server.", user_id);

// log in conduit admin channel if a non-guest user registered
if !body.from_appservice && !is_guest {
services().admin.send_message(RoomMessageEventContent::notice_plain(format!(
"New user \"{user_id}\" registered on this server."
)));
services()
.admin
.send_message(RoomMessageEventContent::notice_plain(format!(
"New user \"{user_id}\" registered on this server."
)));
}

// log in conduit admin channel if a guest registered
if !body.from_appservice && is_guest {
services().admin.send_message(RoomMessageEventContent::notice_plain(format!(
"Guest user \"{user_id}\" with device display name `{:?}` registered on this server.",
body.initial_device_display_name
)));
services()
.admin
.send_message(RoomMessageEventContent::notice_plain(format!(
"Guest user \"{user_id}\" with device display name `{:?}` registered on this server.",
body.initial_device_display_name
)));
}

// If this is the first real user, grant them admin privileges except for guest
// users Note: the server user, @conduit:servername, is generated first
if !is_guest {
if let Some(admin_room) = service::admin::Service::get_admin_room()? {
if services().rooms.state_cache.room_joined_count(&admin_room)? == Some(1) {
services().admin.make_user_admin(&user_id, displayname).await?;
if services()
.rooms
.state_cache
.room_joined_count(&admin_room)?
== Some(1)
{
services()
.admin
.make_user_admin(&user_id, displayname)
.await?;

warn!("Granting {} admin privileges as the first user", user_id);
}
Expand All @@ -291,7 +316,11 @@ pub async fn register_route(body: Ruma<register::v3::Request>) -> Result<registe

if !services().globals.config.auto_join_rooms.is_empty() {
for room in &services().globals.config.auto_join_rooms {
if !services().rooms.state_cache.server_in_room(services().globals.server_name(), room)? {
if !services()
.rooms
.state_cache
.server_in_room(services().globals.server_name(), room)?
{
warn!("Skipping room {room} to automatically join as we have never joined before.");
continue;
}
Expand Down Expand Up @@ -359,32 +388,45 @@ pub async fn change_password_route(body: Ruma<change_password::v3::Request>) ->
};

if let Some(auth) = &body.auth {
let (worked, uiaainfo) = services().uiaa.try_auth(sender_user, sender_device, auth, &uiaainfo)?;
let (worked, uiaainfo) = services()
.uiaa
.try_auth(sender_user, sender_device, auth, &uiaainfo)?;
if !worked {
return Err(Error::Uiaa(uiaainfo));
}
// Success!
} else if let Some(json) = body.json_body {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
services().uiaa.create(sender_user, sender_device, &uiaainfo, &json)?;
services()
.uiaa
.create(sender_user, sender_device, &uiaainfo, &json)?;
return Err(Error::Uiaa(uiaainfo));
} else {
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
}

services().users.set_password(sender_user, Some(&body.new_password))?;
services()
.users
.set_password(sender_user, Some(&body.new_password))?;

if body.logout_devices {
// Logout all devices except the current one
for id in services().users.all_device_ids(sender_user).filter_map(Result::ok).filter(|id| id != sender_device) {
for id in services()
.users
.all_device_ids(sender_user)
.filter_map(Result::ok)
.filter(|id| id != sender_device)
{
services().users.remove_device(sender_user, &id)?;
}
}

info!("User {} changed their password.", sender_user);
services().admin.send_message(RoomMessageEventContent::notice_plain(format!(
"User {sender_user} changed their password."
)));
services()
.admin
.send_message(RoomMessageEventContent::notice_plain(format!(
"User {sender_user} changed their password."
)));

Ok(change_password::v3::Response {})
}
Expand Down Expand Up @@ -431,14 +473,18 @@ pub async fn deactivate_route(body: Ruma<deactivate::v3::Request>) -> Result<dea
};

if let Some(auth) = &body.auth {
let (worked, uiaainfo) = services().uiaa.try_auth(sender_user, sender_device, auth, &uiaainfo)?;
let (worked, uiaainfo) = services()
.uiaa
.try_auth(sender_user, sender_device, auth, &uiaainfo)?;
if !worked {
return Err(Error::Uiaa(uiaainfo));
}
// Success!
} else if let Some(json) = body.json_body {
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
services().uiaa.create(sender_user, sender_device, &uiaainfo, &json)?;
services()
.uiaa
.create(sender_user, sender_device, &uiaainfo, &json)?;
return Err(Error::Uiaa(uiaainfo));
} else {
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
Expand All @@ -451,9 +497,11 @@ pub async fn deactivate_route(body: Ruma<deactivate::v3::Request>) -> Result<dea
services().users.deactivate_account(sender_user)?;

info!("User {} deactivated their account.", sender_user);
services().admin.send_message(RoomMessageEventContent::notice_plain(format!(
"User {sender_user} deactivated their account."
)));
services()
.admin
.send_message(RoomMessageEventContent::notice_plain(format!(
"User {sender_user} deactivated their account."
)));

Ok(deactivate::v3::Response {
id_server_unbind_result: ThirdPartyIdRemovalStatus::NoSupport,
Expand Down
Loading
Loading