Skip to content

Commit 07496eb

Browse files
[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. Fixes flutter/flutter#165482 ## Pre-Review Checklist [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. How can a test be added? It would need to disconnect the device from WLAN beforehand.
1 parent 5cee152 commit 07496eb

File tree

4 files changed

+64
-2
lines changed

4 files changed

+64
-2
lines changed

packages/multicast_dns/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.3.3
2+
3+
* Adds an optional error callback for `MDnsClient::start` to prevent uncaught exceptions.
4+
15
## 0.3.2+8
26

37
* Fixes stack overflows ocurring during the parsing of domain names in MDNS messages.

packages/multicast_dns/lib/multicast_dns.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,18 @@ class MDnsClient {
8484
/// for the mDNS query. If not provided, defaults to either `224.0.0.251` or
8585
/// or `FF02::FB`.
8686
///
87+
/// If provided, [onError] will be called in case of a stream error. If
88+
/// omitted any errors on the stream are considered unhandled, and will be
89+
/// passed to the current [Zone]'s error handler.
90+
///
8791
/// Subsequent calls to this method are ignored while the mDNS client is in
8892
/// started state.
8993
Future<void> start({
9094
InternetAddress? listenAddress,
9195
NetworkInterfacesFactory? interfacesFactory,
9296
int mDnsPort = mDnsPort,
9397
InternetAddress? mDnsAddress,
98+
Function? onError,
9499
}) async {
95100
listenAddress ??= InternetAddress.anyIPv4;
96101
interfacesFactory ??= allInterfacesFactory;
@@ -152,7 +157,10 @@ class MDnsClient {
152157
// Join multicast on this interface.
153158
incoming.joinMulticast(_mDnsAddress!, interface);
154159
}
155-
incoming.listen((RawSocketEvent event) => _handleIncoming(event, incoming));
160+
incoming.listen(
161+
(RawSocketEvent event) => _handleIncoming(event, incoming),
162+
onError: onError,
163+
);
156164
_started = true;
157165
_starting = false;
158166
}

packages/multicast_dns/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: multicast_dns
22
description: Dart package for performing mDNS queries (e.g. Bonjour, Avahi).
33
repository: https://github.com/flutter/packages/tree/main/packages/multicast_dns
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+multicast_dns%22
5-
version: 0.3.2+8
5+
version: 0.3.3
66

77
environment:
88
sdk: ^3.4.0

packages/multicast_dns/test/client_test.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,35 @@ void main() {
158158
});
159159
}
160160
});
161+
162+
test('Calls onError callback in case of socket error', () async {
163+
final FakeRawDatagramSocketThatSendsError datagramSocket =
164+
FakeRawDatagramSocketThatSendsError();
165+
final MDnsClient client = MDnsClient(
166+
rawDatagramSocketFactory: (
167+
dynamic host,
168+
int port, {
169+
bool reuseAddress = true,
170+
bool reusePort = true,
171+
int ttl = 1,
172+
}) async {
173+
return datagramSocket;
174+
},
175+
);
176+
177+
final Completer<void> onErrorCalledCompleter = Completer<void>();
178+
await client.start(
179+
mDnsPort: 1234,
180+
interfacesFactory: (InternetAddressType type) async =>
181+
<NetworkInterface>[],
182+
onError: (Object e) {
183+
expect(e, 'Error');
184+
onErrorCalledCompleter.complete();
185+
},
186+
);
187+
188+
await onErrorCalledCompleter.future.timeout(const Duration(seconds: 5));
189+
});
161190
}
162191

163192
class FakeRawDatagramSocket extends Fake implements RawDatagramSocket {
@@ -196,6 +225,27 @@ class FakeRawDatagramSocket extends Fake implements RawDatagramSocket {
196225
}
197226
}
198227

228+
class FakeRawDatagramSocketThatSendsError extends Fake
229+
implements RawDatagramSocket {
230+
@override
231+
InternetAddress address = InternetAddress.anyIPv4;
232+
233+
@override
234+
StreamSubscription<RawSocketEvent> listen(
235+
void Function(RawSocketEvent event)? onData, {
236+
Function? onError,
237+
void Function()? onDone,
238+
bool? cancelOnError,
239+
}) {
240+
return Stream<RawSocketEvent>.error('Error').listen(
241+
onData,
242+
onError: onError,
243+
cancelOnError: cancelOnError,
244+
onDone: onDone,
245+
);
246+
}
247+
}
248+
199249
class FakeNetworkInterface implements NetworkInterface {
200250
FakeNetworkInterface(this._name, this._addresses, this._index);
201251

0 commit comments

Comments
 (0)