From 52d7a4c5994f0d705e56c040264230ba47203a37 Mon Sep 17 00:00:00 2001 From: Alexander Irion Date: Wed, 19 Mar 2025 10:03:01 +0100 Subject: [PATCH 1/3] [multicast_dns] MDnsClient::listen supports onError callback (#8888) MDnsClient::Listen now supports an optional onError callback function, 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. By default unhandled async errors are treated as if they were uncaught top-level errors. This fixes an unhandled exception occuring (tested on Android), when the network is disconnected. Issue: https://github.com/flutter/flutter/issues/165482 --- packages/multicast_dns/CHANGELOG.md | 4 ++ packages/multicast_dns/lib/multicast_dns.dart | 12 ++++- packages/multicast_dns/pubspec.yaml | 2 +- packages/multicast_dns/test/client_test.dart | 50 +++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md index 7a7d48a6936..74cdb5ab3cd 100644 --- a/packages/multicast_dns/CHANGELOG.md +++ b/packages/multicast_dns/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.2+9 + +* Optional error callback for `MDnsClient::start` to prevent uncatched 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..6eef93d1112 100644 --- a/packages/multicast_dns/lib/multicast_dns.dart +++ b/packages/multicast_dns/lib/multicast_dns.dart @@ -84,6 +84,12 @@ class MDnsClient { /// for the mDNS query. If not provided, defaults to either `224.0.0.251` or /// or `FF02::FB`. /// + /// The [onError] function allows to provide a callback function, 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. By + /// default unhandled async errors are treated as if they were uncaught top-level + /// errors. + /// /// Subsequent calls to this method are ignored while the mDNS client is in /// started state. Future start({ @@ -91,6 +97,7 @@ class MDnsClient { NetworkInterfacesFactory? interfacesFactory, int mDnsPort = mDnsPort, InternetAddress? mDnsAddress, + Function? onError, }) async { listenAddress ??= InternetAddress.anyIPv4; interfacesFactory ??= allInterfacesFactory; @@ -152,7 +159,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..131c00462ab 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.2+9 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); From 82aa495861f91ca7c594e2849cffd9fbfbd1139f Mon Sep 17 00:00:00 2001 From: stuartmorgan-g Date: Tue, 1 Apr 2025 13:36:08 -0400 Subject: [PATCH 2/3] Adjust CHANGELOG wording --- packages/multicast_dns/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md index 74cdb5ab3cd..94aa14f7591 100644 --- a/packages/multicast_dns/CHANGELOG.md +++ b/packages/multicast_dns/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.3.2+9 -* Optional error callback for `MDnsClient::start` to prevent uncatched exceptions. +* Adds an optional error callback for `MDnsClient::start` to prevent uncaught exceptions. ## 0.3.2+8 From 27cdff35d4a14fb2fc7d773e0cae86aceb4c20c6 Mon Sep 17 00:00:00 2001 From: Alexander Irion Date: Wed, 2 Apr 2025 12:07:42 +0200 Subject: [PATCH 3/3] Change version and adapt comment - Change version to 0.3.3 - Adapt comment about new parameter --- packages/multicast_dns/CHANGELOG.md | 2 +- packages/multicast_dns/lib/multicast_dns.dart | 8 +++----- packages/multicast_dns/pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md index 94aa14f7591..dc613d54f97 100644 --- a/packages/multicast_dns/CHANGELOG.md +++ b/packages/multicast_dns/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.3.2+9 +## 0.3.3 * Adds an optional error callback for `MDnsClient::start` to prevent uncaught exceptions. diff --git a/packages/multicast_dns/lib/multicast_dns.dart b/packages/multicast_dns/lib/multicast_dns.dart index 6eef93d1112..9efd54ae5e3 100644 --- a/packages/multicast_dns/lib/multicast_dns.dart +++ b/packages/multicast_dns/lib/multicast_dns.dart @@ -84,11 +84,9 @@ class MDnsClient { /// for the mDNS query. If not provided, defaults to either `224.0.0.251` or /// or `FF02::FB`. /// - /// The [onError] function allows to provide a callback function, 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. By - /// default unhandled async errors are treated as if they were uncaught top-level - /// errors. + /// 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. diff --git a/packages/multicast_dns/pubspec.yaml b/packages/multicast_dns/pubspec.yaml index 131c00462ab..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+9 +version: 0.3.3 environment: sdk: ^3.4.0