diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md index 4b23be31ce2d..c57d95689db2 100644 --- a/packages/multicast_dns/CHANGELOG.md +++ b/packages/multicast_dns/CHANGELOG.md @@ -1,6 +1,7 @@ -## NEXT +## 0.3.2+8 * Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. +* Adds `onSocketError` to `MDnsClient.start`. ## 0.3.2+7 diff --git a/packages/multicast_dns/lib/multicast_dns.dart b/packages/multicast_dns/lib/multicast_dns.dart index d6e2e6b06c0b..41accb139682 100644 --- a/packages/multicast_dns/lib/multicast_dns.dart +++ b/packages/multicast_dns/lib/multicast_dns.dart @@ -84,6 +84,11 @@ class MDnsClient { /// for the mDNS query. If not provided, defaults to either `224.0.0.251` or /// or `FF02::FB`. /// + /// On socket errors, the [onSocketError] handler is called with the error + /// object and possibly a stack trace. The [onSocketError] callback must be of + /// type `void Function(Object error)` or + /// `void Function(Object error, StackTrace)`. + /// /// Subsequent calls to this method are ignored while the mDNS client is in /// started state. Future start({ @@ -91,6 +96,7 @@ class MDnsClient { NetworkInterfacesFactory? interfacesFactory, int mDnsPort = mDnsPort, InternetAddress? mDnsAddress, + Function? onSocketError, }) async { listenAddress ??= InternetAddress.anyIPv4; interfacesFactory ??= allInterfacesFactory; @@ -152,7 +158,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: onSocketError, + ); _started = true; _starting = false; } diff --git a/packages/multicast_dns/lib/src/lookup_resolver.dart b/packages/multicast_dns/lib/src/lookup_resolver.dart index ceaa13a72623..77bd3e61e29f 100644 --- a/packages/multicast_dns/lib/src/lookup_resolver.dart +++ b/packages/multicast_dns/lib/src/lookup_resolver.dart @@ -48,7 +48,7 @@ class LookupResolver { return controller.stream; } - /// Parses [ResoureRecord]s received and delivers them to the appropriate + /// Parses [ResourceRecord]s received and delivers them to the appropriate /// listener(s) added via [addPendingRequest]. void handleResponse(List response) { for (final ResourceRecord r in response) { diff --git a/packages/multicast_dns/test/client_test.dart b/packages/multicast_dns/test/client_test.dart index f3047e5deeed..cf038e9d02e7 100644 --- a/packages/multicast_dns/test/client_test.dart +++ b/packages/multicast_dns/test/client_test.dart @@ -158,19 +158,43 @@ void main() { }); } }); + + test('Reports socket errors', () async { + final FakeRawDatagramSocket datagramSocket = FakeRawDatagramSocket(); + final MDnsClient client = MDnsClient(rawDatagramSocketFactory: + (dynamic host, int port, + {bool reuseAddress = true, + bool reusePort = true, + int ttl = 1}) async { + return datagramSocket; + }); + + final Completer errorCompleter = Completer(); + + await client.start(onError: (Object e, StackTrace stacktrace) { + expect(e, 'Hello world'); + errorCompleter.complete(); + }); + + datagramSocket.controller.addError('Hello world'); + await errorCompleter.future; + }); } class FakeRawDatagramSocket extends Fake implements RawDatagramSocket { @override InternetAddress address = InternetAddress.anyIPv4; + final StreamController controller = + StreamController(); + @override StreamSubscription listen( void Function(RawSocketEvent event)? onData, {Function? onError, void Function()? onDone, bool? cancelOnError}) { - return const Stream.empty().listen(onData, + return controller.stream.listen(onData, onError: onError, cancelOnError: cancelOnError, onDone: onDone); } @@ -178,6 +202,7 @@ class FakeRawDatagramSocket extends Fake implements RawDatagramSocket { @override void close() { + controller.close(); closed = true; }