Use the default port for configured listen addresses with no port (#2043)
* Allow use listen address in config without port * update comments * remove not used alias * use Network::default_port * Move tests and use toml instead json * change error message * Make match more readable Co-authored-by: teor <teor@riseup.net>
This commit is contained in:
parent
96b3c94dbc
commit
afac2c2846
|
@ -4382,6 +4382,7 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio 0.3.6",
|
"tokio 0.3.6",
|
||||||
"tokio-util 0.5.1",
|
"tokio-util 0.5.1",
|
||||||
|
"toml",
|
||||||
"tower",
|
"tower",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
|
|
|
@ -38,5 +38,6 @@ zebra-chain = { path = "../zebra-chain" }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
proptest = "0.10"
|
proptest = "0.10"
|
||||||
proptest-derive = "0.3"
|
proptest-derive = "0.3"
|
||||||
|
toml = "0.5"
|
||||||
|
|
||||||
zebra-test = { path = "../zebra-test/" }
|
zebra-test = { path = "../zebra-test/" }
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
use std::{collections::HashSet, net::SocketAddr, string::String, time::Duration};
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
net::{IpAddr, SocketAddr},
|
||||||
|
string::String,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{de, Deserialize, Deserializer};
|
||||||
|
|
||||||
use zebra_chain::parameters::Network;
|
use zebra_chain::parameters::Network;
|
||||||
|
|
||||||
|
@ -9,11 +16,15 @@ use crate::BoxError;
|
||||||
const MAX_SINGLE_PEER_RETRIES: usize = 2;
|
const MAX_SINGLE_PEER_RETRIES: usize = 2;
|
||||||
|
|
||||||
/// Configuration for networking code.
|
/// Configuration for networking code.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
#[serde(deny_unknown_fields, default)]
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// The address on which this node should listen for connections.
|
/// The address on which this node should listen for connections.
|
||||||
///
|
///
|
||||||
|
/// Can be `address:port` or just `address`. If there is no configured
|
||||||
|
/// port, Zebra will use the default port for the configured `network`.
|
||||||
|
/// `address` can be an IP address or a DNS name. DNS names are
|
||||||
|
/// only resolved once, when Zebra starts up.
|
||||||
|
///
|
||||||
/// Zebra will also advertise this address to other nodes. Advertising a
|
/// Zebra will also advertise this address to other nodes. Advertising a
|
||||||
/// different external IP address is currently not supported, see #1890
|
/// different external IP address is currently not supported, see #1890
|
||||||
/// for details.
|
/// for details.
|
||||||
|
@ -44,7 +55,6 @@ pub struct Config {
|
||||||
/// - regularly, every time `crawl_new_peer_interval` elapses, and
|
/// - regularly, every time `crawl_new_peer_interval` elapses, and
|
||||||
/// - if the peer set is busy, and there aren't any peer addresses for the
|
/// - if the peer set is busy, and there aren't any peer addresses for the
|
||||||
/// next connection attempt.
|
/// next connection attempt.
|
||||||
#[serde(alias = "new_peer_interval")]
|
|
||||||
pub crawl_new_peer_interval: Duration,
|
pub crawl_new_peer_interval: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,3 +186,61 @@ impl Default for Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Config {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields, default)]
|
||||||
|
struct DConfig {
|
||||||
|
listen_addr: String,
|
||||||
|
network: Network,
|
||||||
|
initial_mainnet_peers: HashSet<String>,
|
||||||
|
initial_testnet_peers: HashSet<String>,
|
||||||
|
peerset_initial_target_size: usize,
|
||||||
|
#[serde(alias = "new_peer_interval")]
|
||||||
|
crawl_new_peer_interval: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
let config = Config::default();
|
||||||
|
Self {
|
||||||
|
listen_addr: config.listen_addr.to_string(),
|
||||||
|
network: config.network,
|
||||||
|
initial_mainnet_peers: config.initial_mainnet_peers,
|
||||||
|
initial_testnet_peers: config.initial_testnet_peers,
|
||||||
|
peerset_initial_target_size: config.peerset_initial_target_size,
|
||||||
|
crawl_new_peer_interval: config.crawl_new_peer_interval,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = DConfig::deserialize(deserializer)?;
|
||||||
|
// TODO: perform listener DNS lookups asynchronously with a timeout (#1631)
|
||||||
|
let listen_addr = match config.listen_addr.parse::<SocketAddr>() {
|
||||||
|
Ok(socket) => Ok(socket),
|
||||||
|
Err(_) => match config.listen_addr.parse::<IpAddr>() {
|
||||||
|
Ok(ip) => Ok(SocketAddr::new(ip, config.network.default_port())),
|
||||||
|
Err(err) => Err(de::Error::custom(format!(
|
||||||
|
"{}; Hint: addresses can be a IPv4, IPv6 (with brackets), or a DNS name, the port is optional",
|
||||||
|
err
|
||||||
|
))),
|
||||||
|
},
|
||||||
|
}?;
|
||||||
|
|
||||||
|
Ok(Config {
|
||||||
|
listen_addr,
|
||||||
|
network: config.network,
|
||||||
|
initial_mainnet_peers: config.initial_mainnet_peers,
|
||||||
|
initial_testnet_peers: config.initial_testnet_peers,
|
||||||
|
peerset_initial_target_size: config.peerset_initial_target_size,
|
||||||
|
crawl_new_peer_interval: config.crawl_new_peer_interval,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
use super::Config;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_config_listen_addr() {
|
||||||
|
let fixtures = vec![
|
||||||
|
("listen_addr = '0.0.0.0'", "0.0.0.0:8233"),
|
||||||
|
("listen_addr = '0.0.0.0:9999'", "0.0.0.0:9999"),
|
||||||
|
(
|
||||||
|
"listen_addr = '0.0.0.0'\nnetwork = 'Testnet'",
|
||||||
|
"0.0.0.0:18233",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"listen_addr = '0.0.0.0:8233'\nnetwork = 'Testnet'",
|
||||||
|
"0.0.0.0:8233",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (config, value) in fixtures {
|
||||||
|
let config: Config = toml::from_str(config).unwrap();
|
||||||
|
assert_eq!(config.listen_addr.to_string(), value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -121,13 +121,12 @@ where
|
||||||
// 1. Incoming peer connections, via a listener.
|
// 1. Incoming peer connections, via a listener.
|
||||||
|
|
||||||
// Warn if we're configured using the wrong network port.
|
// Warn if we're configured using the wrong network port.
|
||||||
// TODO: use the right port if the port is unspecified
|
use Network::*;
|
||||||
// split the address and port configs?
|
let wrong_net = match config.network {
|
||||||
let (wrong_net, wrong_net_port) = match config.network {
|
Mainnet => Testnet,
|
||||||
Network::Mainnet => (Network::Testnet, 18233),
|
Testnet => Mainnet,
|
||||||
Network::Testnet => (Network::Mainnet, 8233),
|
|
||||||
};
|
};
|
||||||
if config.listen_addr.port() == wrong_net_port {
|
if config.listen_addr.port() == wrong_net.default_port() {
|
||||||
warn!(
|
warn!(
|
||||||
"We are configured with port {} for {:?}, but that port is the default port for {:?}",
|
"We are configured with port {} for {:?}, but that port is the default port for {:?}",
|
||||||
config.listen_addr.port(),
|
config.listen_addr.port(),
|
||||||
|
|
Loading…
Reference in New Issue