Skip to content

Commit 75640a0

Browse files
committed
Support setting bind address in config.
1 parent 151f6ce commit 75640a0

File tree

7 files changed

+89
-54
lines changed

7 files changed

+89
-54
lines changed

crates/server/src/config.rs

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use serde::{Deserialize, Serialize};
33
use std::{
44
collections::HashSet,
5+
net::{IpAddr, Ipv4Addr, SocketAddr},
56
path::{Path, PathBuf},
67
};
78
use url::Url;
@@ -22,7 +23,7 @@ pub struct ServerConfig {
2223
pub access: Option<AccessControlConfig>,
2324

2425
/// Configuration for the network.
25-
pub net: Option<NetworkConfig>,
26+
pub net: NetworkConfig,
2627

2728
/// Path the file was loaded from used to determine
2829
/// relative paths.
@@ -79,17 +80,35 @@ impl AccessControlConfig {
7980
}
8081

8182
/// Server network configuration.
82-
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
83+
#[derive(Debug, Clone, Serialize, Deserialize)]
84+
#[serde(default)]
8385
pub struct NetworkConfig {
86+
/// Bind address for the server.
87+
pub bind: SocketAddr,
88+
8489
/// SSL configuration.
8590
pub ssl: SslConfig,
8691

8792
/// Configuration for CORS.
8893
pub cors: Option<CorsConfig>,
8994
}
9095

96+
impl Default for NetworkConfig {
97+
fn default() -> Self {
98+
Self {
99+
bind: SocketAddr::new(
100+
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
101+
5053,
102+
),
103+
ssl: Default::default(),
104+
cors: None,
105+
}
106+
}
107+
}
108+
91109
/// Server SSL configuration.
92110
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
111+
#[serde(rename_all = "lowercase")]
93112
pub enum SslConfig {
94113
/// Default HTTP transport.
95114
#[default]
@@ -159,24 +178,31 @@ impl ServerConfig {
159178

160179
let dir = config.directory();
161180

162-
let mut ssl = config.net.as_mut().map(|n| &mut n.ssl);
163-
if let Some(ssl) = ssl.as_mut() {
164-
if let SslConfig::Tls(tls) = ssl {
165-
if tls.cert.is_relative() {
166-
tls.cert = dir.join(&tls.cert);
167-
}
168-
if tls.key.is_relative() {
169-
tls.key = dir.join(&tls.key);
170-
}
171-
172-
tls.cert = tls.cert.canonicalize()?;
173-
tls.key = tls.key.canonicalize()?;
181+
if let SslConfig::Tls(tls) = &mut config.net.ssl {
182+
if tls.cert.is_relative() {
183+
tls.cert = dir.join(&tls.cert);
174184
}
185+
if tls.key.is_relative() {
186+
tls.key = dir.join(&tls.key);
187+
}
188+
189+
tls.cert = tls.cert.canonicalize()?;
190+
tls.key = tls.key.canonicalize()?;
175191
}
176192

177193
Ok(config)
178194
}
179195

196+
/// Set the server bind address.
197+
pub fn set_bind_address(&mut self, addr: SocketAddr) {
198+
self.net.bind = addr;
199+
}
200+
201+
/// Server bind address.
202+
pub fn bind_address(&self) -> &SocketAddr {
203+
&self.net.bind
204+
}
205+
180206
/// Parent directory of the configuration file.
181207
fn directory(&self) -> PathBuf {
182208
self.file

crates/server/src/main.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ mod cli {
4444
/// Start a server.
4545
Start {
4646
/// Bind to host:port.
47-
#[clap(short, long, default_value = "0.0.0.0:5053")]
48-
bind: String,
47+
#[clap(short, long)]
48+
bind: Option<String>,
4949

5050
/// Config file to load.
5151
config: PathBuf,
@@ -104,21 +104,25 @@ mod cli {
104104
}
105105

106106
/// Start a web server.
107-
pub async fn start(bind: String, config: PathBuf) -> Result<()> {
108-
let config = ServerConfig::load(&config).await?;
107+
pub async fn start(
108+
bind: Option<String>,
109+
config: PathBuf,
110+
) -> Result<()> {
111+
let mut config = ServerConfig::load(&config).await?;
112+
113+
if let Some(bind) = bind {
114+
let addr = SocketAddr::from_str(&bind)?;
115+
config.set_bind_address(addr);
116+
}
117+
109118
let backend = config.backend().await?;
110119

111-
let state = Arc::new(RwLock::new(State {
112-
config,
113-
sockets: Default::default(),
114-
}));
120+
let state = Arc::new(RwLock::new(State::new(config)));
115121

116122
let handle = Handle::new();
117-
118-
let addr = SocketAddr::from_str(&bind)?;
119123
let server = Server::new(backend.directory()).await?;
120124
server
121-
.start(addr, state, Arc::new(RwLock::new(backend)), handle)
125+
.start(state, Arc::new(RwLock::new(backend)), handle)
122126
.await?;
123127
Ok(())
124128
}

crates/server/src/server.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,18 @@ use super::handlers::relay::{upgrade as relay_upgrade, RelayState};
4848
pub struct State {
4949
/// The server configuration.
5050
pub config: ServerConfig,
51-
/// Map of websocket channels by connection identifier.
52-
pub sockets: HashMap<Address, WebSocketAccount>,
51+
/// Map of websocket channels by account identifier.
52+
pub(crate) sockets: HashMap<Address, WebSocketAccount>,
53+
}
54+
55+
impl State {
56+
/// Create new server state.
57+
pub fn new(config: ServerConfig) -> Self {
58+
Self {
59+
config,
60+
sockets: Default::default(),
61+
}
62+
}
5363
}
5464

5565
/// State for the server.
@@ -93,30 +103,29 @@ impl Server {
93103
/// Start the server.
94104
pub async fn start(
95105
&self,
96-
addr: SocketAddr,
97106
state: ServerState,
98107
backend: ServerBackend,
99108
handle: Handle,
100109
) -> Result<()> {
101110
let reader = state.read().await;
102111
let origins = Server::read_origins(&reader)?;
103-
let ssl = reader.config.net.as_ref().map(|n| n.ssl.clone());
112+
let ssl = reader.config.net.ssl.clone();
113+
let addr = reader.config.bind_address().clone();
104114
drop(reader);
105115

106116
match ssl {
107-
Some(SslConfig::Http) => {
117+
SslConfig::Http => {
108118
self.run(addr, state, backend, handle, origins).await
109119
}
110-
Some(SslConfig::Tls(tls)) => {
120+
SslConfig::Tls(tls) => {
111121
self.run_tls(addr, state, backend, handle, origins, tls)
112122
.await
113123
}
114124
#[cfg(feature = "acme")]
115-
Some(SslConfig::Acme(acme)) => {
125+
SslConfig::Acme(acme) => {
116126
self.run_acme(addr, state, backend, handle, origins, acme)
117127
.await
118128
}
119-
None => self.run(addr, state, backend, handle, origins).await,
120129
}
121130
}
122131

@@ -244,12 +253,7 @@ impl Server {
244253
reader: &RwLockReadGuard<'_, State>,
245254
) -> Result<Vec<HeaderValue>> {
246255
let mut origins = Vec::new();
247-
let cors = reader
248-
.config
249-
.net
250-
.as_ref()
251-
.map(|n| n.cors.as_ref())
252-
.flatten();
256+
let cors = reader.config.net.cors.as_ref();
253257
if let Some(cors) = cors {
254258
for url in cors.origins.iter() {
255259
origins.push(HeaderValue::from_str(

crates/test_utils/src/lib.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,14 @@ impl MockServer {
9494
// Override the storage path to use the path
9595
// using the test identifier
9696
config.storage.path = self.path.clone();
97+
config.set_bind_address(self.addr);
9798

9899
let backend = config.backend().await?;
99-
let state = Arc::new(RwLock::new(State {
100-
config,
101-
sockets: Default::default(),
102-
}));
100+
let state = Arc::new(RwLock::new(State::new(config)));
103101

104102
let server = Server::new(backend.directory()).await?;
105103
server
106-
.start(
107-
self.addr.clone(),
108-
state,
109-
Arc::new(RwLock::new(backend)),
110-
self.handle.clone(),
111-
)
104+
.start(state, Arc::new(RwLock::new(backend)), self.handle.clone())
112105
.await?;
113106
Ok(())
114107
}

sandbox/acme.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
[storage]
22
path = "./accounts"
33

4+
[net]
5+
bind = "0.0.0.0:443"
6+
47
# To use the Let's Encrypt ACME TLS provider you must:
58
#
69
# 1. Change the domain name and email address
710
# 2. Ensure the DNS points to a public IP address
8-
# 3. Start the server on port 443
9-
# 4. Ensure the `production` flag is set to `true`
11+
# 3. Ensure the `production` flag is set to `true`
1012
#
1113
# If the production flag is not set then you will get
1214
# an error attempting to connect to the server as a
@@ -21,9 +23,9 @@ path = "./accounts"
2123
#
2224
# You can then check the connection, eg:
2325
#
24-
# curl -vL https://acme.saveoursecrets.com
26+
# curl -vL https://acme.example.com
2527
[net.ssl.acme]
2628
cache = "sandbox/acme-cache"
27-
domains = ["acme.saveoursecrets.com"]
28-
email = ["acme@saveoursecrets.com"]
29+
domains = ["acme.example.com"]
30+
email = ["acme@example.com"]
2931
production = false

sandbox/config-backup.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
[storage]
22
path = "./accounts-backup"
3+
4+
[net]
5+
bind = "0.0.0.0:5054"

sandbox/config.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[storage]
22
path = "./accounts"
33

4+
[net]
5+
bind = "0.0.0.0:5053"
6+
47
#[access]
58
#allow = [
69
#"0x6f4e977644ca8f21d335ab13271616b615ea28cb"

0 commit comments

Comments
 (0)