mdns-sd
mdns-sd copied to clipboard
Getting no addresses from discovered service
I am using mdns_sd to discover a service running on a Raspberry Pi of mine (also using mdsn_sd there) and from Pi Pico's (using edge-mdns).
Occaisionally it fails due to discovering a service but not being able to get the addresses of it to get the IP to connect to the service.
This is the code that finds the services and panics when no address is found
let mdns = ServiceDaemon::new().expect("Failed to create daemon");
if let Ok(receiver) = mdns.browse(TCP_MDNS_SERVICE_TYPE) {
while Instant::now() < deadline {
if let Ok(ServiceEvent::ServiceResolved(info)) = receiver.recv_async().await {
println!("Addresses: {:?}", info.get_addresses_v4());
let ip = info
.get_addresses_v4()
.drain()
.next()
.expect("Failed to get IP");
output:
Addresses: {192.168.1.67}
Discovered device: 00000000e91e810c : ip = 192.168.1.67
Addresses: {}
Any ideas on what coudl be the cause for this intermittent problem?
Can I improve my code to improve reliability of discovery somehow?
BTW: "deadline" is currently 1s, not sure what a good value would be.
I have extended to make sure, and then the issue I get is that the same device seems to report different IPs, and the same IP seems to be reported from different devices:
Discovered device: 00000000e91e810c : ip = 192.168.1.67
Addresses: {192.168.1.116, 192.168.1.101}
Discovered device: 00000000e91e810c : ip = 192.168.1.116
Addresses: {192.168.1.101, 192.168.1.116}
Discovered device: f796c3e764ad1c09 : ip = 192.168.1.116
making me wonder if I am doing something wrong about use of addresses() to get IPs....
Any ideas on what coudl be the cause for this intermittent problem?
Since the source code that prints Discovered device: is not included, I cannot be sure. But it is worth to check if IPv6 address is reported when info.get_addresses_v4() returns empty. The lib currently sends out ServiceResolved as long as any IP address is available (V4 or V6). But it also continues to report more if found (with more time like you tried)
the issue I get is that the same device seems to report different IPs, and the same IP seems to be reported from different devices:
It is okay / supported that one device reports more than one IP (that's why get_addresses_v4 returns a set). But it's strange that the same IP seems to be reported from different devices. Is it possible for you to share the code that prints Discovered device: without disclosing any sensitive data ?
Thanks for the response!
All the code is open source, that test support method can be seen in full here: https://github.com/andrewdavidmackenzie/pigg/blob/master/hw_test/tests/mdns_support.rs#L25
I'm making some changes in a branch to debug, but this is the existing code that exhibits this behaviour.
I expected the multiple IPs per device, but not sure what's happening with the multiple devices per IP, unless it's some pretty fundamental DHCP issue with the Pi Pico implementation via embassy, causing two devices to use same IP?
But I don't get any errors reported related to that.
I added some logging and it appears that the IP of address reported, does not match the IP I get using local_ip crate - but I need to check this more...
Later today I will be able to debug that a bit more when back home.
Also to note that sometimes when I run this test, I have seen Addresses as being empty. No restart of the devices, no network change, just a different run of the test seems to produce a different result. Not sure what could cause the device to be discovered, but not get any address.
Thanks for the link. Indeed it seems odd. Could you also print out the get_hostname() and get_fullname() when a service info is resolved? (as internally we index addresses and TXT record using those names)
only fails sometimes, not always... repeated until it fails, and this is the output:
---- mdns_discover_and_connect_tcp stdout ----
Addresses: {192.168.1.101}
Hostname: host1.local.
Fullname: e66138528350be2b._pigg._tcp.local.
Discovered device: e66138528350be2b : ip = 192.168.1.101
Addresses: {192.168.1.101, 192.168.1.116}
Hostname: host1.local.
Fullname: f796c3e764ad1c09._pigg._tcp.local.
Discovered device: f796c3e764ad1c09 : ip = 192.168.1.101
Addresses: {192.168.1.116, 192.168.1.101}
Hostname: host1.local.
Fullname: e66138528350be2b._pigg._tcp.local.
Discovered device: e66138528350be2b : ip = 192.168.1.101
I think multiple of my devices (with different IPs) will be using the same hard-coded hostname.
Do you think that could be the cause? I could use the serial number or a random number.
some other times I still get:
---- mdns_discover_and_connect_tcp stdout ----
Addresses: {}
Hostname: host1.local.
Fullname: 00000000e91e810c._pigg._tcp.local.
thread 'mdns_discover_and_connect_tcp' panicked at hw_test/tests/mdns_support.rs:36:22:
Failed to get IP
After fixing the hostname, I cannot reproduce either failure....
I trust that fixes it.
Thanks for your help and patience!
Do you think that could be the cause?
Yes. If hostname is same, the resolved addresses will be the same (or accumulated) .
some other times I still get:
I still wondering if that's the case where only IPv6 address was detected (IPv4 might be detected soon after). If not, and real empty, that will be a bug as we should never return a real empty address set.
After fixing the hostname, I cannot reproduce either failure....
Nice! (I just still wonder about the empty address set.)
I spoke too soon. Here is a case where Addresses is empty again:
---- mdns_discover_and_connect_tcp stdout ----
Addresses: {}
Hostname: 00000000e91e810c.local.
Fullname: 00000000e91e810c._pigg._tcp.local.
Didn't mean to close, finger trouble :-(
On my embedded (Pi Pico) devices I create a unique hostname to use for mDNS.
In Pi Zero instance, I do the same and use that in ServiceInfo::new
But the device (it has Pi OS running...) has it's own (.local) hostname and the two won't coincide.
Could that cause problems?
The example code used a made-up, hard-coded "host1.local." hostname (as opposed to getting real hostname from the OS) so I wasn't sure...
Here is a case where Addresses is empty again:
Just wanted to confirm, could you try to print all addresses (not only V4)? i.e. doing:
println!("Addresses: {:?}", info.get_addresses());
(as the current code aborts in expect(), the log won't show if V4 address shows up later).
But the device (it has Pi OS running...) has it's own (.local) hostname and the two won't coincide. Could that cause problems?
Should not coincide as this lib itself does not read the hostname set by the OS.
Didn't mean to close, finger trouble :-(
No problem ;-) I will re-open this issue.
---- connect_and_disconnect_iroh stdout ----
Addresses: {192.168.1.101}
Hostname: e66138528350be2b.local.
Fullname: e66138528350be2b._pigg._tcp.local.
Addresses: {192.168.1.116}
Hostname: host1.local.
Fullname: f796c3e764ad1c09._pigg._tcp.local.
Addresses: {fe80::f4fe:d0c0:2415:6a05}
Hostname: 00000000e91e810c.local.
Fullname: 00000000e91e810c._pigg._tcp.local.
To my surprise, a v6 IP shows up there, and in that iteration my code that assumes a v4 IP will fail.
I am not explicitly doing anything with IPv6 anywhere in my app, hardware or network - but maybe still expected?
So, I guess I should handle (skip) that case, and not crash.
I've mentioned about possible IPv6 address in earlier comments ;-)
I am not explicitly doing anything with IPv6 anywhere in my app, hardware or network - but maybe still expected?
Yes as long as there are IPv6 interface configured. If that's a noise to you, you can disable IPv6 using:
daemon.disable_interface(IfKind::IPv6)
like in the example code: https://github.com/keepsimple1/mdns-sd/blob/5e4df27170bc8e593a0ec819bc491e0520b5b7c8/examples/register.rs#L59-L61