Skip to content

Commit 967aef2

Browse files
authored
Merge pull request #290 from mintlayer/libp2p-mdns-fix
Add mDNS configuration
2 parents 35b42bd + eb49a9d commit 967aef2

File tree

26 files changed

+279
-208
lines changed

26 files changed

+279
-208
lines changed

node/src/config.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use anyhow::{Context, Result};
2424
use serde::{Deserialize, Serialize};
2525

2626
use chainstate::ChainstateConfig;
27-
use p2p::config::P2pConfig;
27+
use p2p::config::{MdnsConfig, P2pConfig};
2828
use rpc::RpcConfig;
2929

3030
use crate::RunOptions;
@@ -101,6 +101,7 @@ fn p2p_config(config: P2pConfig, options: &RunOptions) -> P2pConfig {
101101
bind_address,
102102
ban_threshold,
103103
outbound_connection_timeout,
104+
mdns_config: _,
104105
} = config;
105106

106107
let bind_address = options.p2p_addr.clone().unwrap_or(bind_address);
@@ -112,6 +113,11 @@ fn p2p_config(config: P2pConfig, options: &RunOptions) -> P2pConfig {
112113
bind_address,
113114
ban_threshold,
114115
outbound_connection_timeout,
116+
mdns_config: MdnsConfig::from_options(
117+
options.p2p_enable_mdns.unwrap_or(false),
118+
options.p2p_mdns_query_interval,
119+
options.p2p_enable_ipv6_mdns_discovery,
120+
),
115121
}
116122
}
117123

node/src/options.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ pub struct RunOptions {
7777
#[clap(long)]
7878
pub p2p_ban_threshold: Option<u32>,
7979

80+
/// Use IPv6 instead of IPv4 for mDNS.
81+
#[clap(long)]
82+
pub p2p_enable_ipv6_mdns_discovery: Option<bool>,
83+
84+
/// Enable multicast DNS peer discovery
85+
#[clap(long)]
86+
pub p2p_enable_mdns: Option<bool>,
87+
88+
/// Interval (in milliseconds) at which to poll the network for new peers.
89+
#[clap(long)]
90+
pub p2p_mdns_query_interval: Option<u64>,
91+
8092
/// The p2p timeout value in seconds.
8193
#[clap(long)]
8294
pub p2p_outbound_connection_timeout: Option<u64>,

node/src/runner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub async fn initialize(
7272
"p2p",
7373
p2p::make_p2p::<p2p::net::libp2p::Libp2pService>(
7474
Arc::clone(&chain_config),
75-
node_config.p2p,
75+
Arc::new(node_config.p2p),
7676
chainstate.clone(),
7777
)
7878
.await

node/tests/cli.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ fn read_config_override_values() {
8888
let p2p_ban_threshold = 3;
8989
let p2p_timeout = 10000;
9090
let rpc_addr = SocketAddr::from_str("127.0.0.1:5432").unwrap();
91+
let enable_mdns = false;
9192

9293
let options = RunOptions {
9394
net: ChainType::Mainnet,
@@ -96,6 +97,9 @@ fn read_config_override_values() {
9697
p2p_addr: Some(p2p_addr.into()),
9798
p2p_ban_threshold: Some(p2p_ban_threshold),
9899
p2p_outbound_connection_timeout: Some(p2p_timeout),
100+
p2p_enable_mdns: Some(enable_mdns),
101+
p2p_mdns_query_interval: None,
102+
p2p_enable_ipv6_mdns_discovery: None,
99103
rpc_addr: Some(rpc_addr),
100104
};
101105
let config = NodeConfig::read(&config_path, &options).unwrap();
@@ -168,6 +172,9 @@ fn default_run_options() -> RunOptions {
168172
p2p_addr: None,
169173
p2p_ban_threshold: None,
170174
p2p_outbound_connection_timeout: None,
175+
p2p_enable_mdns: None,
176+
p2p_mdns_query_interval: None,
177+
p2p_enable_ipv6_mdns_discovery: None,
171178
rpc_addr: None,
172179
}
173180
}

p2p/src/config.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,54 @@
1515

1616
use serde::{Deserialize, Serialize};
1717

18+
pub const MDNS_DEFAULT_QUERY_INTERVAL: u64 = 0;
19+
pub const MDNS_DEFAULT_IPV6_STATE: bool = false;
20+
21+
/// Multicast DNS configuration.
22+
#[derive(Serialize, Deserialize, Debug)]
23+
#[serde(tag = "state")]
24+
pub enum MdnsConfig {
25+
Enabled {
26+
/// Interval (in milliseconds) at which to poll the network for new peers.
27+
query_interval: u64,
28+
/// Use IPv6 for multicast DNS
29+
enable_ipv6_mdns_discovery: bool,
30+
},
31+
Disabled,
32+
}
33+
34+
impl MdnsConfig {
35+
pub fn new() -> Self {
36+
MdnsConfig::Disabled
37+
}
38+
39+
pub fn from_options(
40+
enable_mdns: bool,
41+
query_interval: Option<u64>,
42+
enable_ipv6_mdns_discovery: Option<bool>,
43+
) -> Self {
44+
if enable_mdns {
45+
MdnsConfig::Enabled {
46+
query_interval: query_interval.unwrap_or(MDNS_DEFAULT_QUERY_INTERVAL),
47+
enable_ipv6_mdns_discovery: enable_ipv6_mdns_discovery
48+
.unwrap_or(MDNS_DEFAULT_IPV6_STATE),
49+
}
50+
} else {
51+
// TODO: make the check for these automatic
52+
assert!(
53+
query_interval.is_none(),
54+
"mDNS is disabled but query interval is specified"
55+
);
56+
assert!(
57+
enable_ipv6_mdns_discovery.is_none(),
58+
"mDNS is disabled but transport over IPv6 is enabled"
59+
);
60+
61+
MdnsConfig::Disabled
62+
}
63+
}
64+
}
65+
1866
/// The p2p subsystem configuration.
1967
#[derive(Serialize, Deserialize, Debug)]
2068
pub struct P2pConfig {
@@ -24,15 +72,41 @@ pub struct P2pConfig {
2472
pub ban_threshold: u32,
2573
/// The outbound connection timeout value in seconds.
2674
pub outbound_connection_timeout: u64,
75+
/// Multicast DNS configuration.
76+
pub mdns_config: MdnsConfig,
2777
}
2878

2979
impl P2pConfig {
3080
/// Creates a new p2p configuration instance.
3181
pub fn new() -> Self {
82+
Default::default()
83+
}
84+
}
85+
86+
impl Default for P2pConfig {
87+
fn default() -> Self {
3288
Self {
3389
bind_address: "/ip6/::1/tcp/3031".into(),
3490
ban_threshold: 100,
3591
outbound_connection_timeout: 10,
92+
mdns_config: MdnsConfig::Disabled,
3693
}
3794
}
3895
}
96+
97+
#[cfg(test)]
98+
mod tests {
99+
use super::*;
100+
101+
#[test]
102+
#[should_panic]
103+
fn mdsn_disabled_but_query_interval_specified() {
104+
MdnsConfig::from_options(false, Some(200), None);
105+
}
106+
107+
#[test]
108+
#[should_panic]
109+
fn mdsn_disabled_but_ipv6_enabled() {
110+
MdnsConfig::from_options(false, None, Some(true));
111+
}
112+
}

p2p/src/lib.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::{
2323
use chainstate::chainstate_interface;
2424
use common::chain::ChainConfig;
2525
use logging::log;
26-
use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration};
26+
use std::{fmt::Debug, str::FromStr, sync::Arc};
2727
use tokio::sync::{mpsc, oneshot};
2828

2929
pub mod config;
@@ -152,7 +152,7 @@ where
152152
/// This function starts the networking backend and individual manager objects.
153153
pub async fn new(
154154
chain_config: Arc<ChainConfig>,
155-
p2p_config: P2pConfig,
155+
p2p_config: Arc<P2pConfig>,
156156
consensus_handle: subsystem::Handle<Box<dyn chainstate_interface::ChainstateInterface>>,
157157
) -> crate::Result<Self>
158158
where
@@ -166,9 +166,8 @@ where
166166
p2p_config.bind_address.clone(),
167167
))
168168
})?,
169-
&[],
170169
Arc::clone(&chain_config),
171-
Duration::from_secs(p2p_config.outbound_connection_timeout),
170+
Arc::clone(&p2p_config),
172171
)
173172
.await?;
174173

@@ -180,10 +179,15 @@ where
180179

181180
let swarm_config = Arc::clone(&chain_config);
182181
tokio::spawn(async move {
183-
if let Err(e) =
184-
swarm::PeerManager::<T>::new(swarm_config, p2p_config, conn, rx_swarm, tx_p2p_sync)
185-
.run()
186-
.await
182+
if let Err(e) = swarm::PeerManager::<T>::new(
183+
swarm_config,
184+
Arc::clone(&p2p_config),
185+
conn,
186+
rx_swarm,
187+
tx_p2p_sync,
188+
)
189+
.run()
190+
.await
187191
{
188192
log::error!("PeerManager failed: {:?}", e);
189193
}
@@ -235,7 +239,7 @@ pub type P2pHandle<T> = subsystem::Handle<P2pInterface<T>>;
235239

236240
pub async fn make_p2p<T>(
237241
chain_config: Arc<ChainConfig>,
238-
p2p_config: P2pConfig,
242+
p2p_config: Arc<P2pConfig>,
239243
consensus_handle: subsystem::Handle<Box<dyn chainstate_interface::ChainstateInterface>>,
240244
) -> crate::Result<P2pInterface<T>>
241245
where

p2p/src/net/libp2p/backend.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ mod tests {
312312
identify,
313313
sync,
314314
connmgr: connectivity::ConnectionManager::new(),
315-
discovery: discovery::DiscoveryManager::new(false).await,
315+
discovery: discovery::DiscoveryManager::new(Default::default()).await,
316316
events: VecDeque::new(),
317317
pending_reqs: HashMap::new(),
318318
waker: None,

p2p/src/net/libp2p/behaviour.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//! Network behaviour configuration for libp2p
1919
2020
use crate::{
21+
config,
2122
error::{P2pError, ProtocolError},
2223
message,
2324
net::{
@@ -86,8 +87,8 @@ pub type Libp2pNetworkBehaviourAction = NetworkBehaviourAction<
8687
impl Libp2pBehaviour {
8788
pub async fn new(
8889
config: Arc<ChainConfig>,
90+
p2p_config: Arc<config::P2pConfig>,
8991
id_keys: identity::Keypair,
90-
enable_mdns: bool,
9192
) -> Self {
9293
let gossipsub_config = GossipsubConfigBuilder::default()
9394
.heartbeat_interval(GOSSIPSUB_HEARTBEAT)
@@ -132,7 +133,7 @@ impl Libp2pBehaviour {
132133
)
133134
.expect("configuration to be valid"),
134135
connmgr: connectivity::ConnectionManager::new(),
135-
discovery: discovery::DiscoveryManager::new(enable_mdns).await,
136+
discovery: discovery::DiscoveryManager::new(Arc::clone(&p2p_config)).await,
136137
events: VecDeque::new(),
137138
pending_reqs: HashMap::new(),
138139
waker: None,

p2p/src/net/libp2p/discovery/mdns.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
//! Multicast DNS (mDNS) discovery behaviour for the libp2p backend
1919
20+
use crate::config;
2021
use libp2p::{
2122
core::connection::{ConnectedPoint, ConnectionId},
2223
mdns,
@@ -38,17 +39,27 @@ pub enum Mdns {
3839
}
3940

4041
impl Mdns {
41-
pub async fn new(enabled: bool) -> Self {
42-
if enabled {
43-
match mdns::Mdns::new(Default::default()).await {
44-
Ok(mdns) => Mdns::Enabled(Box::new(mdns)),
45-
Err(err) => {
46-
log::error!("Failed to initialize mDNS: {:?}", err);
47-
Mdns::Disabled
42+
pub async fn new(config: &config::MdnsConfig) -> Self {
43+
match config {
44+
config::MdnsConfig::Enabled {
45+
query_interval,
46+
enable_ipv6_mdns_discovery,
47+
} => {
48+
match mdns::Mdns::new(mdns::MdnsConfig {
49+
ttl: Default::default(),
50+
query_interval: std::time::Duration::from_millis(*query_interval),
51+
enable_ipv6: *enable_ipv6_mdns_discovery,
52+
})
53+
.await
54+
{
55+
Ok(mdns) => Mdns::Enabled(Box::new(mdns)),
56+
Err(err) => {
57+
log::error!("Failed to initialize mDNS: {:?}", err);
58+
Mdns::Disabled
59+
}
4860
}
4961
}
50-
} else {
51-
Mdns::Disabled
62+
config::MdnsConfig::Disabled => Mdns::Disabled,
5263
}
5364
}
5465

@@ -96,7 +107,7 @@ mod tests {
96107

97108
#[tokio::test]
98109
async fn mdns_disabled() {
99-
let mdns = Mdns::new(false).await;
110+
let mdns = Mdns::new(&config::MdnsConfig::new()).await;
100111
assert!(std::matches!(mdns, Mdns::Disabled));
101112
}
102113

@@ -148,14 +159,22 @@ mod tests {
148159
}
149160

150161
let tester1 = MdnsTester {
151-
mdns: Mdns::new(true).await,
162+
mdns: Mdns::new(&config::MdnsConfig::Enabled {
163+
query_interval: 200,
164+
enable_ipv6_mdns_discovery: false,
165+
})
166+
.await,
152167
poll_params: TestParams {
153168
peer_id: PeerId::random(),
154169
addr: "/ip6/::1/tcp/9999".parse().unwrap(),
155170
},
156171
};
157172
let tester2 = MdnsTester {
158-
mdns: Mdns::new(true).await,
173+
mdns: Mdns::new(&config::MdnsConfig::Enabled {
174+
query_interval: 200,
175+
enable_ipv6_mdns_discovery: false,
176+
})
177+
.await,
159178
poll_params: TestParams {
160179
peer_id: PeerId::random(),
161180
addr: "/ip6/::1/tcp/8888".parse().unwrap(),

p2p/src/net/libp2p/discovery/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
//! Discovery behaviour for libp2p
1919
20+
use crate::config;
2021
use libp2p::{
2122
core::{
2223
connection::{ConnectedPoint, ConnectionId},
@@ -29,7 +30,10 @@ use libp2p::{
2930
},
3031
Multiaddr,
3132
};
32-
use std::task::{Context, Poll};
33+
use std::{
34+
sync::Arc,
35+
task::{Context, Poll},
36+
};
3337

3438
mod mdns;
3539

@@ -47,9 +51,9 @@ pub struct DiscoveryManager {
4751
}
4852

4953
impl DiscoveryManager {
50-
pub async fn new(mdns_enabled: bool) -> Self {
54+
pub async fn new(p2p_config: Arc<config::P2pConfig>) -> Self {
5155
Self {
52-
mdns: mdns::Mdns::new(mdns_enabled).await,
56+
mdns: mdns::Mdns::new(&p2p_config.mdns_config).await,
5357
}
5458
}
5559
}

0 commit comments

Comments
 (0)