From ec04707febc94bd9d6cfdecd6e6314f9c99c3538 Mon Sep 17 00:00:00 2001 From: LouiseHsu Date: Wed, 30 Oct 2024 14:20:25 -0700 Subject: [PATCH] Adds a new helpful tool exit message for SocketExceptions thrown during mdns discovery (#157638) Addresses https://github.com/flutter/flutter/issues/150131, but doesn't fix it, as there seem to be cases where the steps included in the messages added in this PR don't work. --- .../flutter_tools/lib/src/mdns_discovery.dart | 27 ++++++++++++++--- .../general.shard/mdns_discovery_test.dart | 30 +++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/packages/flutter_tools/lib/src/mdns_discovery.dart b/packages/flutter_tools/lib/src/mdns_discovery.dart index a2f0decf7f..1568757eb0 100644 --- a/packages/flutter_tools/lib/src/mdns_discovery.dart +++ b/packages/flutter_tools/lib/src/mdns_discovery.dart @@ -15,6 +15,7 @@ import 'base/logger.dart'; import 'build_info.dart'; import 'convert.dart'; import 'device.dart'; +import 'globals.dart' as globals; import 'reporting/reporting.dart'; /// A wrapper around [MDnsClient] to find a Dart VM Service instance. @@ -229,10 +230,28 @@ class MDnsVmServiceDiscovery { final Set uniqueDomainNamesInResults = {}; // Listen for mDNS connections until timeout. - final Stream ptrResourceStream = client.lookup( - ResourceRecordQuery.serverPointer(dartVmServiceName), - timeout: timeout - ); + final Stream ptrResourceStream; + + try { + ptrResourceStream = client.lookup( + ResourceRecordQuery.serverPointer(dartVmServiceName), + timeout: timeout, + ); + } on SocketException catch (e, stacktrace) { + _logger.printError(e.message); + _logger.printTrace(stacktrace.toString()); + if (globals.platform.isMacOS) { + throwToolExit( + 'You might be having a permissions issue with your IDE. ' + 'Please try going to ' + 'System Settings -> Privacy & Security -> Local Network -> ' + '[Find your IDE] -> Toggle ON, then restart your phone.' + ); + } else { + rethrow; + } + } + await for (final PtrResourceRecord ptr in ptrResourceStream) { uniqueDomainNames.add(ptr.domainName); diff --git a/packages/flutter_tools/test/general.shard/mdns_discovery_test.dart b/packages/flutter_tools/test/general.shard/mdns_discovery_test.dart index 27eb5a9a8b..7b1454564f 100644 --- a/packages/flutter_tools/test/general.shard/mdns_discovery_test.dart +++ b/packages/flutter_tools/test/general.shard/mdns_discovery_test.dart @@ -7,6 +7,7 @@ import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/device_port_forwarder.dart'; +import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/ios/devices.dart'; import 'package:flutter_tools/src/mdns_discovery.dart'; import 'package:flutter_tools/src/project.dart'; @@ -577,6 +578,30 @@ void main() { ); }); + test('On macOS, throw tool exit with a helpful message when client throws a SocketException on lookup', () async { + final MDnsClient client = FakeMDnsClient( + [], >{}, + socketExceptionOnStart: true); + + final MDnsVmServiceDiscovery portDiscovery = MDnsVmServiceDiscovery( + mdnsClient: client, + logger: BufferLogger.test(), + flutterUsage: TestUsage(), + analytics: const NoOpAnalytics(), + ); + + expect( + portDiscovery.firstMatchingVmService(client), + throwsToolExit( + message: + 'You might be having a permissions issue with your IDE. ' + 'Please try going to ' + 'System Settings -> Privacy & Security -> Local Network -> ' + '[Find your IDE] -> Toggle ON, then restart your phone.', + ) + ); + }, skip: !globals.platform.isMacOS); // [intended] This tool exit message only works for macOS + testWithoutContext('Correctly builds VM Service URI with hostVmservicePort == 0', () async { final MDnsClient client = FakeMDnsClient( [ @@ -991,6 +1016,7 @@ class FakeMDnsClient extends Fake implements MDnsClient { this.txtResponse = const >{}, this.ipResponse = const >{}, this.osErrorOnStart = false, + this.socketExceptionOnStart = false }); final List ptrRecords; @@ -998,6 +1024,7 @@ class FakeMDnsClient extends Fake implements MDnsClient { final Map> txtResponse; final Map> ipResponse; final bool osErrorOnStart; + final bool socketExceptionOnStart; @override Future start({ @@ -1016,6 +1043,9 @@ class FakeMDnsClient extends Fake implements MDnsClient { ResourceRecordQuery query, { Duration timeout = const Duration(seconds: 5), }) { + if (socketExceptionOnStart) { + throw const SocketException('Socket Exception'); + } if (T == PtrResourceRecord && query.fullyQualifiedName == MDnsVmServiceDiscovery.dartVmServiceName) { return Stream.fromIterable(ptrRecords) as Stream; }