Skyost / Bonsoir

A Zeroconf library that allows you to discover network services and to broadcast your own. Based on Apple Bonjour and Android NSD.
http://bonsoir.skyost.eu/
Other
112 stars 48 forks source link

Scan for all the mDNS devices in the network #86

Open guyluz11 opened 8 months ago

guyluz11 commented 8 months ago

Is your feature request related to a problem? Please describe. I would like to scan all mDNS devices in the network in an efficient manner. I saw that there is an option to search for a specific serviceType but I prefer not to search all the serviceTypes that ever existed.

Describe the solution you'd like As written in DNS-SD specification chapter 9 there is a special type _services._dns-sd._udp that retrieves all current types in the network.

I would love to see a function that retrieves all of the serviceType on the network using _services._dns-sd._udp so that I can iterate only on existing services in the network.

Describe alternatives you've considered I have searched also in multicast_dns but they do not support it yet, see issue number 97210 on flutter repo https://github.com/flutter/flutter/issues

Also nsd package had implemented it in issue number 8 https://github.com/sebastianhaberey/nsd/issues/ . This package is more popular, supports Linux, I think the other package does not support iOS (issue 57) so it would be easier for me if it exists here.

Skyost commented 8 months ago

I did some researches with what you've provided. Why don't you do something like that ?

BonsoirDiscovery typeDiscovery = BonsoirDiscovery(type: '_services._dns-sd._udp');
await typeDiscovery.ready;

Map<String, BonsoirDiscovery> discoveries = {};

discovery.eventStream!.listen((event) async {
  if (event.type == BonsoirDiscoveryEventType.discoveryServiceFound) {
    String type = event.service!.type;
    BonsoirDiscovery discovery = BonsoirDiscovery(type: type);
    await discovery.ready;
    discoveries[type] = discovery;
  } else if (event.type == BonsoirDiscoveryEventType.discoveryServiceLost) {
    await discoveries[type]?.stop();
    discoveries.remove(type);
  }
});

await discovery.start();
MaxiStefan commented 6 months ago

Hi @Skyost I am tying to do something similar but with http._tcp.

if I use either http._tcp. or _services._dns-sd._udp I get the following error:

ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(discoveryError, Bonsoir has encountered an error during discovery : -65555: NoAuth (error %s)., -65555, null)
flutter: It seems that you are trying to discover an invalid type using Bonsoir.
flutter: Did you mean "_my-service._tcp" instead of "http._tcp." ?
Skyost commented 6 months ago

@MaxiStefan Do you mean _http._tcp ?

Caesarovich commented 3 months ago

Hi,

Because of the normalizeType function, it is indeed impossible to use that workaround for now. Like @MaxiStefan said, I get the following error when trying your code @Skyost:

flutter: It seems that you are trying to discover an invalid type using Bonsoir.
flutter: Did you mean "_my-service._tcp" instead of "_services._dns-sd._udp" ?

So we need to account for the special meta-query in this function.

Caesarovich commented 3 months ago

Hi,

I'm back after some tests. It looks like the solution doesn't only require adding a specific rule to the normalizeType. It appears that the platform specific libs also need to handle the way service types are returned. I'm currently trying to debug it for linux.

Skyost commented 3 months ago

I get the following error when trying your code @Skyost:

That's not an error, just a warning.

Caesarovich commented 3 months ago

Hi again, sorry for late reply.

I've been doing some experimenting and finally got it to work (for linux at least). The only thing is that this special case might need to be documented as it is a bit different from normal services. event.service.name returns the specific service (such as _http) and event.service.type return the tcp/udp part. So in order to get the full service you must compose it like so

'${event.service!.name}.${event.service!.type}' //  _http._tcp

It's still pretty usable, especially for such a niche use case but it could be nice to have specific wrapper for it.

If you're okay with this @Skyost I'll open a PR as soon as possible.