Repository navigation
mdns discovery - #79
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds an mDNS/DNS-SD based neighbor discovery mechanism to dtn7-rs (as an alternative to legacy UDP multicast IPND) and introduces configuration/CLI options to select the discovery transport, enabling same-host multi-daemon discovery without UDP port binding conflicts.
Changes:
- Added mDNS discovery implementation (
_dtn._udp.local.) and transport selection (udp-multicast/mdns/both). - Refactored legacy UDP multicast discovery into its own module and wired it through a unified
spawn_neighbour_discovery()dispatcher. - Added documentation and configuration examples, plus a new dependency (
mdns-sd).
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| examples/dtn7.toml.example | Documents new discovery.transport option. |
| doc/mdns-discovery.md | New mDNS discovery documentation and usage examples. |
| core/dtn7/src/ipnd/udp_discovery.rs | Extracted UDP multicast discovery implementation into a dedicated module. |
| core/dtn7/src/ipnd/neighbour_discovery.rs | Dispatches discovery startup based on configured transport. |
| core/dtn7/src/ipnd/mod.rs | Exposes new mdns_discovery and udp_discovery modules. |
| core/dtn7/src/ipnd/mdns_discovery.rs | New mDNS/DNS-SD discovery implementation. |
| core/dtn7/src/dtnconfig.rs | Adds DiscoveryTransport enum and config-file parsing for transport selection. |
| core/dtn7/src/bin/dtnd.rs | Adds --discovery-transport CLI flag and parsing into config. |
| core/dtn7/Cargo.toml | Adds mdns-sd dependency. |
| Cargo.lock | Locks transitive dependencies introduced by mdns-sd. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+16
to
+33
| let config = CONFIG.lock(); | ||
| let nodeid = config.nodeid.clone(); | ||
| let eid = config.host_eid.clone(); | ||
| let interval_duration = config.announcement_interval; | ||
| drop(config); | ||
|
|
||
| info!("Starting mDNS discovery for service type: {}", MDNS_SERVICE_TYPE); | ||
|
|
||
| // Create mDNS daemon | ||
| let mdns = ServiceDaemon::new().expect("Failed to create mDNS daemon"); | ||
|
|
||
| // Build and register our service | ||
| let service_info = build_mdns_service_info(&nodeid, &eid); | ||
| mdns.register(service_info) | ||
| .expect("Failed to register mDNS service"); | ||
|
|
||
| info!("Registered mDNS service type: {} (Node: {})", MDNS_SERVICE_TYPE, nodeid); | ||
|
|
Comment on lines
+96
to
+118
| // Add available CLAs with their ports | ||
| let clas = CLAS.lock(); | ||
| let cla_props: Vec<(String, String)> = clas.iter() | ||
| .enumerate() | ||
| .map(|(idx, cla)| { | ||
| (format!("cla{}", idx), format!("{}:{}", cla.name(), cla.port())) | ||
| }) | ||
| .collect(); | ||
| drop(clas); | ||
|
|
||
| for (key, val) in cla_props { | ||
| properties.push((Box::leak(key.into_boxed_str()), val)); | ||
| } | ||
|
|
||
| // Add custom services | ||
| let services = DTNCORE.lock().service_list.clone(); | ||
| let svc_props: Vec<(String, String)> = services.iter() | ||
| .map(|(tag, payload)| (format!("svc{}", tag), payload.clone())) | ||
| .collect(); | ||
|
|
||
| for (key, val) in svc_props { | ||
| properties.push((Box::leak(key.into_boxed_str()), val)); | ||
| } |
Comment on lines
+24
to
+37
| // Create mDNS daemon | ||
| let mdns = ServiceDaemon::new().expect("Failed to create mDNS daemon"); | ||
|
|
||
| // Build and register our service | ||
| let service_info = build_mdns_service_info(&nodeid, &eid); | ||
| mdns.register(service_info) | ||
| .expect("Failed to register mDNS service"); | ||
|
|
||
| info!("Registered mDNS service type: {} (Node: {})", MDNS_SERVICE_TYPE, nodeid); | ||
|
|
||
| // Browse for other DTN nodes | ||
| let receiver = mdns.browse(MDNS_SERVICE_TYPE) | ||
| .expect("Failed to browse for mDNS services"); | ||
|
|
Comment on lines
+109
to
+110
| (*CONFIG.lock()).update_beacon_sequence_number(&destination.to_string()); | ||
| pkt.set_beacon_sequence_number(bsn); |
Comment on lines
+189
to
+196
| if v6 { | ||
| let addr: SocketAddr = format!("[::1]:{}", port).parse()?; | ||
| let addr = addr.into(); | ||
| let socket = Socket::new(Domain::IPV6, Type::DGRAM, None)?; | ||
| socket.set_reuse_address(true)?; | ||
| socket.set_only_v6(true)?; | ||
| socket.bind(&addr)?; | ||
|
|
Comment on lines
+69
to
+76
| | Feature | UDP Multicast | mDNS | | ||
| |---------|--------------|------| | ||
| | Port conflicts | Yes (only one daemon/host) | No (system manages mDNS) | | ||
| | Same-host discovery | No | Yes | | ||
| | Standard tooling | Limited | Full (dns-sd, avahi-browse) | | ||
| | Name resolution | No | Yes (`.local` hostnames) | | ||
| | Legacy compatibility | IPND | New | | ||
|
|
Comment on lines
+366
to
+369
| if let Some(transport) = matches.get_one::<String>("discoverytransport") { | ||
| cfg.discovery_transport = transport.parse() | ||
| .expect("Invalid discovery transport! Use: udp-multicast, mdns, or both"); | ||
| } |
Comment on lines
+191
to
+196
| dtncfg.discovery_transport = if let Ok(transport) = s.get_string("discovery.transport") { | ||
| DiscoveryTransport::from_str(&transport).unwrap_or_default() | ||
| } else { | ||
| dtncfg.discovery_transport | ||
| }; | ||
| debug!("discovery-transport: {:?}", dtncfg.discovery_transport); |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Member
|
Wow, thx for this PR. mDNS was on my todo list for a very long time! appreciate that it works on multiple platforms! |
Member
|
@copilot resolve the merge conflicts in this pull request |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Current neighbor discovery uses binding to a local udp port with multicast. Thus two dtn node on the same host can't discover themselves and also cannot bind on the same port.
This PR Implements neighbour discovery over mDNS, this doesn't require any binding to local port, the service messages encapsulate all eid and services in a similar fashion to the beacon with udp multicast discovery.
I also Added new options for dtnd to select which neighbouring discovery protocol to use.