Skip to content

Commit

Permalink
feat: Add mDNS and Rendezvous configs (#377)
Browse files Browse the repository at this point in the history
# Description

This PR implements the following features:

- [x] Add `enable_mdns` config
- [x] Add `enable_rendezvous` config

These configs determine whether we toggle mDNS and Rendezvous on or off.
In addition, we check the toggle states in event handlers where we might
use mDNS or Rendezvous.

## Link to issue

Closes #376 

## Type of change

- [x] New feature (non-breaking change that adds functionality)
- [x] Refactor (non-breaking change that updates existing functionality)

## Test plan (required)

All existing tests should pass. In particular, we are interested in the
multi-node tests that rely on known peers and mDNS.
  • Loading branch information
bgins committed Oct 12, 2023
1 parent 1574aea commit ea11c27
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 48 deletions.
71 changes: 42 additions & 29 deletions homestar-runtime/src/event_handler/swarm_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,25 +142,32 @@ async fn handle_swarm_event<THandlerErr: fmt::Debug + Send, DB: Database>(
// rendezvous
// we are good to register self & discover with any node we contact. more peers = more better!
if info.protocols.contains(&RENDEZVOUS_PROTOCOL_NAME) {
// register self with remote
if let Err(err) = behavior.rendezvous_client.register(
Namespace::from_static(RENDEZVOUS_NAMESPACE),
peer_id,
None,
) {
warn!(
peer_id = peer_id.to_string(),
err = format!("{err}"),
"failed to register with rendezvous peer"
)
if let Some(rendezvous_client) = event_handler
.swarm
.behaviour_mut()
.rendezvous_client
.as_mut()
{
// register self with remote
if let Err(err) = rendezvous_client.register(
Namespace::from_static(RENDEZVOUS_NAMESPACE),
peer_id,
None,
) {
warn!(
peer_id = peer_id.to_string(),
err = format!("{err}"),
"failed to register with rendezvous peer"
)
}
// discover other nodes
rendezvous_client.discover(
Some(Namespace::from_static(RENDEZVOUS_NAMESPACE)),
None,
None,
peer_id,
);
}
// discover other nodes
behavior.rendezvous_client.discover(
Some(Namespace::from_static(RENDEZVOUS_NAMESPACE)),
None,
None,
peer_id,
);
}
}
identify::Event::Pushed { peer_id } => debug!(
Expand Down Expand Up @@ -224,17 +231,20 @@ async fn handle_swarm_event<THandlerErr: fmt::Debug + Send, DB: Database>(
}
rendezvous::client::Event::Expired { peer } => {
// re-discover records from peer
let cookie = event_handler.rendezvous_cookies.get(&peer).cloned();
event_handler
if let Some(rendezvous_client) = event_handler
.swarm
.behaviour_mut()
.rendezvous_client
.discover(
.as_mut()
{
let cookie = event_handler.rendezvous_cookies.get(&peer).cloned();
rendezvous_client.discover(
Some(Namespace::from_static(RENDEZVOUS_NAMESPACE)),
cookie,
None,
peer,
);
}
}
}
}
Expand Down Expand Up @@ -535,14 +545,17 @@ async fn handle_swarm_event<THandlerErr: fmt::Debug + Send, DB: Database>(
}
}
SwarmEvent::Behaviour(ComposedEvent::Mdns(mdns::Event::Expired(list))) => {
for (peer_id, multiaddr) in list {
info!("mDNS discover peer has expired: {peer_id}");
if event_handler.swarm.behaviour_mut().mdns.has_node(&peer_id) {
event_handler
.swarm
.behaviour_mut()
.kademlia
.remove_address(&peer_id, &multiaddr);
let behaviour = event_handler.swarm.behaviour_mut();

if let Some(mdns) = behaviour.mdns.as_ref() {
for (peer_id, multiaddr) in list {
info!(
peer_id = peer_id.to_string(),
"mDNS discover peer has expired"
);
if mdns.has_node(&peer_id) {
behaviour.kademlia.remove_address(&peer_id, &multiaddr);
}
}
}
}
Expand Down
44 changes: 28 additions & 16 deletions homestar-runtime/src/network/swarm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use libp2p::{
multiaddr::Protocol,
noise, rendezvous,
request_response::{self, ProtocolSupport},
swarm::{NetworkBehaviour, Swarm, SwarmBuilder},
swarm::{behaviour::toggle::Toggle, NetworkBehaviour, Swarm, SwarmBuilder},
tcp, yamux, StreamProtocol, Transport,
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -78,18 +78,30 @@ pub(crate) async fn new(settings: &settings::Node) -> Result<Swarm<ComposedBehav
)],
request_response::Config::default(),
),
mdns: mdns::Behaviour::new(
mdns::Config {
ttl: settings.network.mdns_ttl,
query_interval: settings.network.mdns_query_interval,
enable_ipv6: settings.network.mdns_enable_ipv6,
},
peer_id,
)?,
rendezvous_client: rendezvous::client::Behaviour::new(keypair.clone()),
rendezvous_server: rendezvous::server::Behaviour::new(
rendezvous::server::Config::default(),
),
mdns: Toggle::from(if settings.network.enable_mdns {
Some(mdns::Behaviour::new(
mdns::Config {
ttl: settings.network.mdns_ttl,
query_interval: settings.network.mdns_query_interval,
enable_ipv6: settings.network.mdns_enable_ipv6,
},
peer_id,
)?)
} else {
None
}),
rendezvous_client: Toggle::from(if settings.network.enable_rendezvous {
Some(rendezvous::client::Behaviour::new(keypair.clone()))
} else {
None
}),
rendezvous_server: Toggle::from(if settings.network.enable_rendezvous {
Some(rendezvous::server::Behaviour::new(
rendezvous::server::Config::default(),
))
} else {
None
}),
identify: identify::Behaviour::new(
identify::Config::new(HOMESTAR_PROTOCOL_VER.to_string(), keypair.public())
.with_agent_version(format!("homestar-runtime/{}", env!("CARGO_PKG_VERSION"))),
Expand Down Expand Up @@ -235,11 +247,11 @@ pub(crate) struct ComposedBehaviour {
/// [request_response::Behaviour] CBOR-flavored behaviour.
pub(crate) request_response: request_response::cbor::Behaviour<RequestResponseKey, Vec<u8>>,
/// [mdns::tokio::Behaviour] behaviour.
pub(crate) mdns: mdns::tokio::Behaviour,
pub(crate) mdns: Toggle<mdns::tokio::Behaviour>,
/// [rendezvous::client::Behaviour] behaviour.
pub(crate) rendezvous_client: rendezvous::client::Behaviour,
pub(crate) rendezvous_client: Toggle<rendezvous::client::Behaviour>,
/// [rendezvous::server::Behaviour] behaviour.
pub(crate) rendezvous_server: rendezvous::server::Behaviour,
pub(crate) rendezvous_server: Toggle<rendezvous::server::Behaviour>,
/// [identify::Behaviour] behaviour.
pub(crate) identify: identify::Behaviour,
}
Expand Down
12 changes: 9 additions & 3 deletions homestar-runtime/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,16 @@ pub struct Network {
/// [Swarm]: libp2p::swarm::Swarm
#[serde(with = "http_serde::uri")]
pub(crate) listen_address: Uri,
/// Mdns IPv6 enable flag.
/// Enable Rendezvous protocol.
pub(crate) enable_rendezvous: bool,
/// Enable mDNS.
pub(crate) enable_mdns: bool,
/// mDNS IPv6 enable flag
pub(crate) mdns_enable_ipv6: bool,
/// Mdns query interval.
/// mDNS query interval.
#[serde_as(as = "DurationSeconds<u64>")]
pub(crate) mdns_query_interval: Duration,
/// Mdns TTL.
/// mDNS TTL.
#[serde_as(as = "DurationSeconds<u64>")]
pub(crate) mdns_ttl: Duration,
/// Timeout for p2p requests for a provided record.
Expand Down Expand Up @@ -181,6 +185,8 @@ impl Default for Network {
events_buffer_len: 1024,
listen_address: Uri::from_static("/ip4/0.0.0.0/tcp/0"),
// TODO: we would like to enable this by default, however this breaks mdns on at least some linux distros. Requires further investigation.
enable_rendezvous: true,
enable_mdns: true,
mdns_enable_ipv6: false,
mdns_query_interval: Duration::from_secs(5 * 60),
mdns_ttl: Duration::from_secs(60 * 9),
Expand Down
1 change: 1 addition & 0 deletions homestar-runtime/tests/fixtures/test_mdns_connect1.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ console_subscriber_port = 5560
rpc_port = 9800
websocket_port = 8000
listen_address = "/ip4/0.0.0.0/tcp/0"
enable_rendezvous = false

[node.network.keypair_config]
existing = { key_type = "ed25519", path = "./fixtures/__testkey_ed25519.pem" }
1 change: 1 addition & 0 deletions homestar-runtime/tests/fixtures/test_mdns_connect2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ console_subscriber_port = 5561
rpc_port = 9801
websocket_port = 8001
listen_address = "/ip4/0.0.0.0/tcp/0"
enable_rendezvous = false

[node.network.keypair_config]
existing = { key_type = "secp256k1", path = "./fixtures/__testkey_secp256k1.der" }
2 changes: 2 additions & 0 deletions homestar-runtime/tests/fixtures/test_network1.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ listen_address = "/ip4/127.0.0.1/tcp/7000"
node_addresses = [
"/ip4/127.0.0.1/tcp/7001/p2p/16Uiu2HAm3g9AomQNeEctL2hPwLapap7AtPSNt8ZrBny4rLx1W5Dc",
]
enable_mdns = false
enable_rendezvous = false

[node.network.keypair_config]
existing = { key_type = "ed25519", path = "./fixtures/__testkey_ed25519.pem" }
2 changes: 2 additions & 0 deletions homestar-runtime/tests/fixtures/test_network2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ listen_address = "/ip4/127.0.0.1/tcp/7001"
node_addresses = [
"/ip4/127.0.0.1/tcp/7000/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN",
]
enable_mdns = false
enable_rendezvous = false

[node.network.keypair_config]
existing = { key_type = "secp256k1", path = "./fixtures/__testkey_secp256k1.der" }

0 comments on commit ea11c27

Please sign in to comment.