Skip to content

Add mDNS configuration #290

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

Merged
merged 5 commits into from
Jul 26, 2022
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
8 changes: 7 additions & 1 deletion node/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};

use chainstate::ChainstateConfig;
use p2p::config::P2pConfig;
use p2p::config::{MdnsConfig, P2pConfig};
use rpc::RpcConfig;

use crate::RunOptions;
Expand Down Expand Up @@ -101,6 +101,7 @@ fn p2p_config(config: P2pConfig, options: &RunOptions) -> P2pConfig {
bind_address,
ban_threshold,
outbound_connection_timeout,
mdns_config: _,
} = config;

let bind_address = options.p2p_addr.clone().unwrap_or(bind_address);
Expand All @@ -112,6 +113,11 @@ fn p2p_config(config: P2pConfig, options: &RunOptions) -> P2pConfig {
bind_address,
ban_threshold,
outbound_connection_timeout,
mdns_config: MdnsConfig::from_options(
options.p2p_enable_mdns.unwrap_or(false),
options.p2p_mdns_query_interval,
options.p2p_enable_ipv6_mdns_discovery,
),
}
}

Expand Down
12 changes: 12 additions & 0 deletions node/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ pub struct RunOptions {
#[clap(long)]
pub p2p_ban_threshold: Option<u32>,

/// Use IPv6 instead of IPv4 for mDNS.
#[clap(long)]
pub p2p_enable_ipv6_mdns_discovery: Option<bool>,

/// Enable multicast DNS peer discovery
#[clap(long)]
pub p2p_enable_mdns: Option<bool>,

/// Interval (in milliseconds) at which to poll the network for new peers.
#[clap(long)]
pub p2p_mdns_query_interval: Option<u64>,

/// The p2p timeout value in seconds.
#[clap(long)]
pub p2p_outbound_connection_timeout: Option<u64>,
Expand Down
2 changes: 1 addition & 1 deletion node/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub async fn initialize(
"p2p",
p2p::make_p2p::<p2p::net::libp2p::Libp2pService>(
Arc::clone(&chain_config),
node_config.p2p,
Arc::new(node_config.p2p),
chainstate.clone(),
)
.await
Expand Down
7 changes: 7 additions & 0 deletions node/tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ fn read_config_override_values() {
let p2p_ban_threshold = 3;
let p2p_timeout = 10000;
let rpc_addr = SocketAddr::from_str("127.0.0.1:5432").unwrap();
let enable_mdns = false;

let options = RunOptions {
net: ChainType::Mainnet,
Expand All @@ -96,6 +97,9 @@ fn read_config_override_values() {
p2p_addr: Some(p2p_addr.into()),
p2p_ban_threshold: Some(p2p_ban_threshold),
p2p_outbound_connection_timeout: Some(p2p_timeout),
p2p_enable_mdns: Some(enable_mdns),
p2p_mdns_query_interval: None,
p2p_enable_ipv6_mdns_discovery: None,
rpc_addr: Some(rpc_addr),
};
let config = NodeConfig::read(&config_path, &options).unwrap();
Expand Down Expand Up @@ -168,6 +172,9 @@ fn default_run_options() -> RunOptions {
p2p_addr: None,
p2p_ban_threshold: None,
p2p_outbound_connection_timeout: None,
p2p_enable_mdns: None,
p2p_mdns_query_interval: None,
p2p_enable_ipv6_mdns_discovery: None,
rpc_addr: None,
}
}
74 changes: 74 additions & 0 deletions p2p/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,54 @@

use serde::{Deserialize, Serialize};

pub const MDNS_DEFAULT_QUERY_INTERVAL: u64 = 0;
pub const MDNS_DEFAULT_IPV6_STATE: bool = false;

/// Multicast DNS configuration.
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "state")]
pub enum MdnsConfig {
Enabled {
/// Interval (in milliseconds) at which to poll the network for new peers.
query_interval: u64,
/// Use IPv6 for multicast DNS
enable_ipv6_mdns_discovery: bool,
},
Disabled,
}

impl MdnsConfig {
pub fn new() -> Self {
MdnsConfig::Disabled
}

pub fn from_options(
enable_mdns: bool,
query_interval: Option<u64>,
enable_ipv6_mdns_discovery: Option<bool>,
) -> Self {
if enable_mdns {
MdnsConfig::Enabled {
query_interval: query_interval.unwrap_or(MDNS_DEFAULT_QUERY_INTERVAL),
enable_ipv6_mdns_discovery: enable_ipv6_mdns_discovery
.unwrap_or(MDNS_DEFAULT_IPV6_STATE),
}
} else {
// TODO: make the check for these automatic
assert!(
query_interval.is_none(),
"mDNS is disabled but query interval is specified"
);
assert!(
enable_ipv6_mdns_discovery.is_none(),
"mDNS is disabled but transport over IPv6 is enabled"
);

MdnsConfig::Disabled
}
}
}

/// The p2p subsystem configuration.
#[derive(Serialize, Deserialize, Debug)]
pub struct P2pConfig {
Expand All @@ -24,15 +72,41 @@ pub struct P2pConfig {
pub ban_threshold: u32,
/// The outbound connection timeout value in seconds.
pub outbound_connection_timeout: u64,
/// Multicast DNS configuration.
pub mdns_config: MdnsConfig,
}

impl P2pConfig {
/// Creates a new p2p configuration instance.
pub fn new() -> Self {
Default::default()
}
}

impl Default for P2pConfig {
fn default() -> Self {
Self {
bind_address: "/ip6/::1/tcp/3031".into(),
ban_threshold: 100,
outbound_connection_timeout: 10,
mdns_config: MdnsConfig::Disabled,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
#[should_panic]
fn mdsn_disabled_but_query_interval_specified() {
MdnsConfig::from_options(false, Some(200), None);
}

#[test]
#[should_panic]
fn mdsn_disabled_but_ipv6_enabled() {
MdnsConfig::from_options(false, None, Some(true));
}
}
22 changes: 13 additions & 9 deletions p2p/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
use chainstate::chainstate_interface;
use common::chain::ChainConfig;
use logging::log;
use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration};
use std::{fmt::Debug, str::FromStr, sync::Arc};
use tokio::sync::{mpsc, oneshot};

pub mod config;
Expand Down Expand Up @@ -152,7 +152,7 @@ where
/// This function starts the networking backend and individual manager objects.
pub async fn new(
chain_config: Arc<ChainConfig>,
p2p_config: P2pConfig,
p2p_config: Arc<P2pConfig>,
consensus_handle: subsystem::Handle<Box<dyn chainstate_interface::ChainstateInterface>>,
) -> crate::Result<Self>
where
Expand All @@ -166,9 +166,8 @@ where
p2p_config.bind_address.clone(),
))
})?,
&[],
Arc::clone(&chain_config),
Duration::from_secs(p2p_config.outbound_connection_timeout),
Arc::clone(&p2p_config),
)
.await?;

Expand All @@ -180,10 +179,15 @@ where

let swarm_config = Arc::clone(&chain_config);
tokio::spawn(async move {
if let Err(e) =
swarm::PeerManager::<T>::new(swarm_config, p2p_config, conn, rx_swarm, tx_p2p_sync)
.run()
.await
if let Err(e) = swarm::PeerManager::<T>::new(
swarm_config,
Arc::clone(&p2p_config),
conn,
rx_swarm,
tx_p2p_sync,
)
.run()
.await
{
log::error!("PeerManager failed: {:?}", e);
}
Expand Down Expand Up @@ -235,7 +239,7 @@ pub type P2pHandle<T> = subsystem::Handle<P2pInterface<T>>;

pub async fn make_p2p<T>(
chain_config: Arc<ChainConfig>,
p2p_config: P2pConfig,
p2p_config: Arc<P2pConfig>,
consensus_handle: subsystem::Handle<Box<dyn chainstate_interface::ChainstateInterface>>,
) -> crate::Result<P2pInterface<T>>
where
Expand Down
2 changes: 1 addition & 1 deletion p2p/src/net/libp2p/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ mod tests {
identify,
sync,
connmgr: connectivity::ConnectionManager::new(),
discovery: discovery::DiscoveryManager::new(false).await,
discovery: discovery::DiscoveryManager::new(Default::default()).await,
events: VecDeque::new(),
pending_reqs: HashMap::new(),
waker: None,
Expand Down
5 changes: 3 additions & 2 deletions p2p/src/net/libp2p/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
//! Network behaviour configuration for libp2p

use crate::{
config,
error::{P2pError, ProtocolError},
message,
net::{
Expand Down Expand Up @@ -86,8 +87,8 @@ pub type Libp2pNetworkBehaviourAction = NetworkBehaviourAction<
impl Libp2pBehaviour {
pub async fn new(
config: Arc<ChainConfig>,
p2p_config: Arc<config::P2pConfig>,
id_keys: identity::Keypair,
enable_mdns: bool,
) -> Self {
let gossipsub_config = GossipsubConfigBuilder::default()
.heartbeat_interval(GOSSIPSUB_HEARTBEAT)
Expand Down Expand Up @@ -132,7 +133,7 @@ impl Libp2pBehaviour {
)
.expect("configuration to be valid"),
connmgr: connectivity::ConnectionManager::new(),
discovery: discovery::DiscoveryManager::new(enable_mdns).await,
discovery: discovery::DiscoveryManager::new(Arc::clone(&p2p_config)).await,
events: VecDeque::new(),
pending_reqs: HashMap::new(),
waker: None,
Expand Down
43 changes: 31 additions & 12 deletions p2p/src/net/libp2p/discovery/mdns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

//! Multicast DNS (mDNS) discovery behaviour for the libp2p backend

use crate::config;
use libp2p::{
core::connection::{ConnectedPoint, ConnectionId},
mdns,
Expand All @@ -38,17 +39,27 @@ pub enum Mdns {
}

impl Mdns {
pub async fn new(enabled: bool) -> Self {
if enabled {
match mdns::Mdns::new(Default::default()).await {
Ok(mdns) => Mdns::Enabled(Box::new(mdns)),
Err(err) => {
log::error!("Failed to initialize mDNS: {:?}", err);
Mdns::Disabled
pub async fn new(config: &config::MdnsConfig) -> Self {
match config {
config::MdnsConfig::Enabled {
query_interval,
enable_ipv6_mdns_discovery,
} => {
match mdns::Mdns::new(mdns::MdnsConfig {
ttl: Default::default(),
query_interval: std::time::Duration::from_millis(*query_interval),
enable_ipv6: *enable_ipv6_mdns_discovery,
})
.await
{
Ok(mdns) => Mdns::Enabled(Box::new(mdns)),
Err(err) => {
log::error!("Failed to initialize mDNS: {:?}", err);
Mdns::Disabled
}
}
}
} else {
Mdns::Disabled
config::MdnsConfig::Disabled => Mdns::Disabled,
}
}

Expand Down Expand Up @@ -96,7 +107,7 @@ mod tests {

#[tokio::test]
async fn mdns_disabled() {
let mdns = Mdns::new(false).await;
let mdns = Mdns::new(&config::MdnsConfig::new()).await;
assert!(std::matches!(mdns, Mdns::Disabled));
}

Expand Down Expand Up @@ -148,14 +159,22 @@ mod tests {
}

let tester1 = MdnsTester {
mdns: Mdns::new(true).await,
mdns: Mdns::new(&config::MdnsConfig::Enabled {
query_interval: 200,
enable_ipv6_mdns_discovery: false,
})
.await,
poll_params: TestParams {
peer_id: PeerId::random(),
addr: "/ip6/::1/tcp/9999".parse().unwrap(),
},
};
let tester2 = MdnsTester {
mdns: Mdns::new(true).await,
mdns: Mdns::new(&config::MdnsConfig::Enabled {
query_interval: 200,
enable_ipv6_mdns_discovery: false,
})
.await,
poll_params: TestParams {
peer_id: PeerId::random(),
addr: "/ip6/::1/tcp/8888".parse().unwrap(),
Expand Down
10 changes: 7 additions & 3 deletions p2p/src/net/libp2p/discovery/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

//! Discovery behaviour for libp2p

use crate::config;
use libp2p::{
core::{
connection::{ConnectedPoint, ConnectionId},
Expand All @@ -29,7 +30,10 @@ use libp2p::{
},
Multiaddr,
};
use std::task::{Context, Poll};
use std::{
sync::Arc,
task::{Context, Poll},
};

mod mdns;

Expand All @@ -47,9 +51,9 @@ pub struct DiscoveryManager {
}

impl DiscoveryManager {
pub async fn new(mdns_enabled: bool) -> Self {
pub async fn new(p2p_config: Arc<config::P2pConfig>) -> Self {
Self {
mdns: mdns::Mdns::new(mdns_enabled).await,
mdns: mdns::Mdns::new(&p2p_config.mdns_config).await,
}
}
}
Expand Down
Loading