Skip to content

Commit 570a90a

Browse files
dasha-uwujevolk
authored andcommitted
Update axum-server to 0.8; switch to axum unix listener.
1 parent 9416297 commit 570a90a

File tree

13 files changed

+230
-389
lines changed

13 files changed

+230
-389
lines changed

Cargo.lock

Lines changed: 5 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,12 @@ features = [
8282
]
8383

8484
[workspace.dependencies.axum-server]
85-
version = "0.7"
85+
version = "0.8"
8686
default-features = false
8787

8888
[workspace.dependencies.axum-server-dual-protocol]
89-
version = "0.7"
89+
git = "https://github.com/matrix-construct/axum-server-dual-protocol"
90+
rev = "76c782fa6f129f83ffdca59e903093e798d4a82f"
9091
default-features = false
9192

9293
[workspace.dependencies.base64]
@@ -201,15 +202,6 @@ features = [
201202
"http2",
202203
]
203204

204-
[workspace.dependencies.hyper-util]
205-
version = "0.1.20"
206-
default-features = false
207-
features = [
208-
"server-auto",
209-
"server-graceful",
210-
"tokio",
211-
]
212-
213205
[workspace.dependencies.image]
214206
version = "0.25"
215207
default-features = false

src/core/config/check.rs

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::env::consts::OS;
22

33
use either::Either;
4-
use figment::Figment;
54
use itertools::Itertools;
65

76
use super::{DEPRECATED_KEYS, IdentityProvider};
8-
use crate::{Config, Err, Result, Server, debug, debug_info, debug_warn, error, warn};
7+
use crate::{Config, Err, Result, Server, debug, debug_info, error, warn};
98

109
/// Performs check() with additional checks specific to reloading old config
1110
/// with new config.
@@ -24,9 +23,8 @@ pub fn reload(old: &Config, new: &Config) -> Result {
2423
}
2524

2625
pub fn check(config: &Config) -> Result {
27-
if cfg!(debug_assertions) {
28-
warn!("Note: tuwunel was built without optimisations (i.e. debug build)");
29-
}
26+
#[cfg(debug_assertions)]
27+
warn!("Note: tuwunel was built without optimisations (i.e. debug build)");
3028

3129
warn_deprecated(config);
3230
warn_unknown_key(config)?;
@@ -38,27 +36,39 @@ pub fn check(config: &Config) -> Result {
3836
));
3937
}
4038

41-
if cfg!(all(feature = "hardened_malloc", feature = "jemalloc", not(target_env = "msvc"))) {
42-
debug_warn!(
43-
"hardened_malloc and jemalloc compile-time features are both enabled, this causes \
44-
jemalloc to be used."
45-
);
46-
}
39+
#[cfg(all(
40+
feature = "hardened_malloc",
41+
feature = "jemalloc",
42+
not(target_env = "msvc")
43+
))]
44+
debug_warn!(
45+
"hardened_malloc and jemalloc compile-time features are both enabled, this causes \
46+
jemalloc to be used."
47+
);
4748

48-
if cfg!(not(unix)) && config.unix_socket_path.is_some() {
49+
#[cfg(not(unix))]
50+
if config.unix_socket_path.is_some() {
4951
return Err!(Config(
5052
"unix_socket_path",
5153
"UNIX socket support is only available on *nix platforms. Please remove \
5254
'unix_socket_path' from your config."
5355
));
5456
}
5557

56-
if config.unix_socket_path.is_none() && config.get_bind_hosts().is_empty() {
57-
return Err!(Config("address", "No TCP addresses were specified to listen on"));
58+
if config.unix_socket_path.is_none() {
59+
if config.get_bind_hosts().is_empty() {
60+
return Err!(Config("address", "No TCP addresses were specified to listen on"));
61+
}
62+
63+
if config.get_bind_ports().is_empty() {
64+
return Err!(Config("port", "No ports were specified to listen on"));
65+
}
5866
}
5967

60-
if config.unix_socket_path.is_none() && config.get_bind_ports().is_empty() {
61-
return Err!(Config("port", "No ports were specified to listen on"));
68+
let certs_set = config.tls.certs.is_some();
69+
let key_set = config.tls.key.is_some();
70+
if certs_set ^ key_set {
71+
return Err!(Config("tls", "tls.certs and tls.key must either both be set or unset"));
6272
}
6373

6474
if !config.listening {
@@ -115,7 +125,8 @@ pub fn check(config: &Config) -> Result {
115125
}
116126

117127
// yeah, unless the user built a debug build hopefully for local testing only
118-
if cfg!(not(debug_assertions)) && config.server_name == "your.server.name" {
128+
#[cfg(not(debug_assertions))]
129+
if config.server_name == "your.server.name" {
119130
return Err!(Config(
120131
"server_name",
121132
"You must specify a valid server name for production usage of tuwunel."
@@ -412,18 +423,3 @@ fn warn_unknown_key(config: &Config) -> Result {
412423
Ok(())
413424
}
414425
}
415-
416-
/// Checks the presence of the `address` and `unix_socket_path` keys in the
417-
/// raw_config, exiting the process if both keys were detected.
418-
pub(super) fn is_dual_listening(raw_config: &Figment) -> Result {
419-
let contains_address = raw_config.contains("address");
420-
let contains_unix_socket = raw_config.contains("unix_socket_path");
421-
if contains_address && contains_unix_socket {
422-
return Err!(
423-
"TOML keys \"address\" and \"unix_socket_path\" were both defined. Please specify \
424-
only one option."
425-
);
426-
}
427-
428-
Ok(())
429-
}

src/core/config/mod.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ pub struct Config {
106106
/// "::1"]
107107
///
108108
/// default: ["127.0.0.1", "::1"]
109-
#[serde(default = "default_address")]
110-
address: ListeningAddr,
109+
#[serde(default)]
110+
address: Option<ListeningAddr>,
111111

112112
/// The port(s) tuwunel will listen on.
113113
///
@@ -129,9 +129,6 @@ pub struct Config {
129129

130130
/// The UNIX socket tuwunel will listen on.
131131
///
132-
/// tuwunel cannot listen on both an IP address and a UNIX socket. If
133-
/// listening on a UNIX socket, you MUST remove/comment the `address` key.
134-
///
135132
/// Remember to make sure that your reverse proxy has access to this socket
136133
/// file, either by adding your reverse proxy to the 'tuwunel' group or
137134
/// granting world R/W permissions with `unix_socket_perms` (666 minimum).
@@ -3009,18 +3006,24 @@ impl Config {
30093006
.extract::<Self>()
30103007
.map_err(|e| err!("There was a problem with your configuration file: {e}"))?;
30113008

3012-
// don't start if we're listening on both UNIX sockets and TCP at same time
3013-
check::is_dual_listening(raw_config)?;
3014-
30153009
Ok(config)
30163010
}
30173011

3012+
pub fn get_unix_socket_perms(&self) -> Result<u32> {
3013+
let octal_perms = self.unix_socket_perms.to_string();
3014+
let socket_perms = u32::from_str_radix(&octal_perms, 8).map_err(|_| {
3015+
err!(Config("unix_socket_perms", "failed to convert octal permissions"))
3016+
})?;
3017+
3018+
Ok(socket_perms)
3019+
}
3020+
30183021
#[must_use]
30193022
pub fn get_bind_addrs(&self) -> Vec<SocketAddr> {
30203023
let mut addrs = Vec::with_capacity(
30213024
self.get_bind_hosts()
30223025
.len()
3023-
.saturating_add(self.get_bind_ports().len()),
3026+
.saturating_mul(self.get_bind_ports().len()),
30243027
);
30253028
for host in &self.get_bind_hosts() {
30263029
for port in &self.get_bind_ports() {
@@ -3032,9 +3035,15 @@ impl Config {
30323035
}
30333036

30343037
fn get_bind_hosts(&self) -> Vec<IpAddr> {
3035-
match &self.address.addrs {
3036-
| Left(addr) => vec![*addr],
3037-
| Right(addrs) => addrs.clone(),
3038+
if let Some(address) = &self.address {
3039+
match &address.addrs {
3040+
| Left(addr) => vec![*addr],
3041+
| Right(addrs) => addrs.clone(),
3042+
}
3043+
} else if self.unix_socket_path.is_some() {
3044+
vec![]
3045+
} else {
3046+
vec![Ipv4Addr::LOCALHOST.into(), Ipv6Addr::LOCALHOST.into()]
30383047
}
30393048
}
30403049

@@ -3055,12 +3064,6 @@ fn default_server_name() -> OwnedServerName { ruma::owned_server_name!("localhos
30553064

30563065
fn default_database_path() -> PathBuf { "/var/lib/tuwunel".to_owned().into() }
30573066

3058-
fn default_address() -> ListeningAddr {
3059-
ListeningAddr {
3060-
addrs: Right(vec![Ipv4Addr::LOCALHOST.into(), Ipv6Addr::LOCALHOST.into()]),
3061-
}
3062-
}
3063-
30643067
fn default_port() -> ListeningPort { ListeningPort { ports: Left(8008) } }
30653068

30663069
fn default_unix_socket_perms() -> u32 { 660 }

src/router/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ futures.workspace = true
115115
http.workspace = true
116116
http-body-util.workspace = true
117117
hyper.workspace = true
118-
hyper-util.workspace = true
119118
log.workspace = true
120119
ruma.workspace = true
121120
rustls.workspace = true

src/router/handle.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use std::time::Duration;
2+
3+
use axum_server::Handle;
4+
5+
#[derive(Clone)]
6+
pub(crate) struct ServerHandle {
7+
pub(crate) handle_ip: Handle<std::net::SocketAddr>,
8+
#[cfg(unix)]
9+
pub(crate) handle_unix: Handle<std::os::unix::net::SocketAddr>,
10+
}
11+
12+
impl ServerHandle {
13+
pub(crate) fn new() -> Self {
14+
Self {
15+
handle_ip: Handle::<std::net::SocketAddr>::new(),
16+
#[cfg(unix)]
17+
handle_unix: Handle::<std::os::unix::net::SocketAddr>::new(),
18+
}
19+
}
20+
21+
pub(crate) fn graceful_shutdown(&self, duration: Option<Duration>) {
22+
self.handle_ip.graceful_shutdown(duration);
23+
24+
#[cfg(unix)]
25+
self.handle_unix.graceful_shutdown(duration);
26+
}
27+
}

src/router/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![type_length_limit = "32768"] //TODO: reduce me
22
#![expect(clippy::duration_suboptimal_units)] // remove after MSRV 1.91
33

4+
mod handle;
45
mod layers;
56
mod request;
67
mod router;

0 commit comments

Comments
 (0)