diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md index 7a7d48a6936..dc613d54f97 100644 --- a/packages/multicast_dns/CHANGELOG.md +++ b/packages/multicast_dns/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.3 + +* Adds an optional error callback for `MDnsClient::start` to prevent uncaught exceptions. + ## 0.3.2+8 * Fixes stack overflows ocurring during the parsing of domain names in MDNS messages. diff --git a/packages/multicast_dns/lib/multicast_dns.dart b/packages/multicast_dns/lib/multicast_dns.dart index d6e2e6b06c0..9efd54ae5e3 100644 --- a/packages/multicast_dns/lib/multicast_dns.dart +++ b/packages/multicast_dns/lib/multicast_dns.dart @@ -84,6 +84,10 @@ class MDnsClient { /// for the mDNS query. If not provided, defaults to either `224.0.0.251` or /// or `FF02::FB`. /// + /// If provided, [onError] will be called in case of a stream error. If + /// omitted any errors on the stream are considered unhandled, and will be + /// passed to the current [Zone]'s error handler. + /// /// Subsequent calls to this method are ignored while the mDNS client is in /// started state. Future start({ @@ -91,6 +95,7 @@ class MDnsClient { NetworkInterfacesFactory? interfacesFactory, int mDnsPort = mDnsPort, InternetAddress? mDnsAddress, + Function? onError, }) async { listenAddress ??= InternetAddress.anyIPv4; interfacesFactory ??= allInterfacesFactory; @@ -152,7 +157,10 @@ class MDnsClient { // Join multicast on this interface. incoming.joinMulticast(_mDnsAddress!, interface); } - incoming.listen((RawSocketEvent event) => _handleIncoming(event, incoming)); + incoming.listen( + (RawSocketEvent event) => _handleIncoming(event, incoming), + onError: onError, + ); _started = true; _starting = false; } diff --git a/packages/multicast_dns/pubspec.yaml b/packages/multicast_dns/pubspec.yaml index 3303a8fb944..974a4b58889 100644 --- a/packages/multicast_dns/pubspec.yaml +++ b/packages/multicast_dns/pubspec.yaml @@ -2,7 +2,7 @@ name: multicast_dns description: Dart package for performing mDNS queries (e.g. Bonjour, Avahi). repository: https://github.com/flutter/packages/tree/main/packages/multicast_dns issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+multicast_dns%22 -version: 0.3.2+8 +version: 0.3.3 environment: sdk: ^3.4.0 diff --git a/packages/multicast_dns/test/client_test.dart b/packages/multicast_dns/test/client_test.dart index f3047e5deee..706e2f1aa8e 100644 --- a/packages/multicast_dns/test/client_test.dart +++ b/packages/multicast_dns/test/client_test.dart @@ -158,6 +158,35 @@ void main() { }); } }); + + test('Calls onError callback in case of socket error', () async { + final FakeRawDatagramSocketThatSendsError datagramSocket = + FakeRawDatagramSocketThatSendsError(); + final MDnsClient client = MDnsClient( + rawDatagramSocketFactory: ( + dynamic host, + int port, { + bool reuseAddress = true, + bool reusePort = true, + int ttl = 1, + }) async { + return datagramSocket; + }, + ); + + final Completer onErrorCalledCompleter = Completer(); + await client.start( + mDnsPort: 1234, + interfacesFactory: (InternetAddressType type) async => + [], + onError: (Object e) { + expect(e, 'Error'); + onErrorCalledCompleter.complete(); + }, + ); + + await onErrorCalledCompleter.future.timeout(const Duration(seconds: 5)); + }); } class FakeRawDatagramSocket extends Fake implements RawDatagramSocket { @@ -196,6 +225,27 @@ class FakeRawDatagramSocket extends Fake implements RawDatagramSocket { } } +class FakeRawDatagramSocketThatSendsError extends Fake + implements RawDatagramSocket { + @override + InternetAddress address = InternetAddress.anyIPv4; + + @override + StreamSubscription listen( + void Function(RawSocketEvent event)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + }) { + return Stream.error('Error').listen( + onData, + onError: onError, + cancelOnError: cancelOnError, + onDone: onDone, + ); + } +} + class FakeNetworkInterface implements NetworkInterface { FakeNetworkInterface(this._name, this._addresses, this._index);