Add support for binding to IPv6 localhost in flutter run
(#13136)
This allows `flutter run` to work on hosts that are IPv6-only.
This commit is contained in:
parent
f5d9c7775d
commit
e792c6bb5b
@ -345,6 +345,7 @@ class AndroidDevice extends Device {
|
||||
bool prebuiltApplication: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
bool ipv6: false,
|
||||
}) async {
|
||||
if (!await _checkForSupportedAdbVersion() || !await _checkForSupportedAndroidVersion())
|
||||
return new LaunchResult.failed();
|
||||
@ -381,7 +382,11 @@ class AndroidDevice extends Device {
|
||||
// TODO(devoncarew): Remember the forwarding information (so we can later remove the
|
||||
// port forwarding or set it up again when adb fails on us).
|
||||
observatoryDiscovery = new ProtocolDiscovery.observatory(
|
||||
getLogReader(), portForwarder: portForwarder, hostPort: debuggingOptions.observatoryPort);
|
||||
getLogReader(),
|
||||
portForwarder: portForwarder,
|
||||
hostPort: debuggingOptions.observatoryPort,
|
||||
ipv6: ipv6,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> cmd;
|
||||
|
@ -28,6 +28,12 @@ abstract class RunCommandBase extends FlutterCommand {
|
||||
negatable: true,
|
||||
defaultsTo: false,
|
||||
help: 'Start tracing during startup.');
|
||||
argParser.addFlag('ipv6',
|
||||
hide: true,
|
||||
negatable: false,
|
||||
defaultsTo: false,
|
||||
help: 'Binds to IPv6 localhost instead of IPv4 when the flutter tool\n'
|
||||
'forwards the host port to a device port.');
|
||||
argParser.addOption('route',
|
||||
help: 'Which route to load when running the app.');
|
||||
usesTargetOption();
|
||||
@ -36,6 +42,7 @@ abstract class RunCommandBase extends FlutterCommand {
|
||||
}
|
||||
|
||||
bool get traceStartup => argResults['trace-startup'];
|
||||
bool get ipv6 => argResults['ipv6'];
|
||||
String get route => argResults['route'];
|
||||
|
||||
void usesPortOptions() {
|
||||
@ -304,6 +311,7 @@ class RunCommand extends RunCommandBase {
|
||||
packagesFilePath: argResults['packages'],
|
||||
projectAssets: argResults['project-assets'],
|
||||
stayResident: stayResident,
|
||||
ipv6: ipv6,
|
||||
);
|
||||
} else {
|
||||
runner = new ColdRunner(
|
||||
@ -314,6 +322,7 @@ class RunCommand extends RunCommandBase {
|
||||
applicationBinary: argResults['use-application-binary'],
|
||||
previewDart2: argResults['preview-dart-2'],
|
||||
stayResident: stayResident,
|
||||
ipv6: ipv6,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -227,6 +227,7 @@ abstract class Device {
|
||||
bool prebuiltApplication: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
bool ipv6: false,
|
||||
});
|
||||
|
||||
/// Does this device implement support for hot reloading / restarting?
|
||||
|
@ -68,6 +68,7 @@ class FuchsiaDevice extends Device {
|
||||
bool previewDart2: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: false,
|
||||
bool ipv6: false,
|
||||
}) => new Future<Null>.error('unimplemented');
|
||||
|
||||
@override
|
||||
|
@ -163,6 +163,7 @@ class IOSDevice extends Device {
|
||||
bool previewDart2: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
bool ipv6: false,
|
||||
}) async {
|
||||
if (!prebuiltApplication) {
|
||||
// TODO(chinmaygarde): Use mainPath, route.
|
||||
@ -255,7 +256,11 @@ class IOSDevice extends Device {
|
||||
// TODO(danrubel): The Android device class does something similar to this code below.
|
||||
// The various Device subclasses should be refactored and common code moved into the superclass.
|
||||
final ProtocolDiscovery observatoryDiscovery = new ProtocolDiscovery.observatory(
|
||||
getLogReader(app: app), portForwarder: portForwarder, hostPort: debuggingOptions.observatoryPort);
|
||||
getLogReader(app: app),
|
||||
portForwarder: portForwarder,
|
||||
hostPort: debuggingOptions.observatoryPort,
|
||||
ipv6: ipv6,
|
||||
);
|
||||
|
||||
final Future<Uri> forwardObservatoryUri = observatoryDiscovery.uri;
|
||||
|
||||
|
@ -312,6 +312,7 @@ class IOSSimulator extends Device {
|
||||
bool prebuiltApplication: false,
|
||||
bool applicationNeedsRebuild: false,
|
||||
bool usesTerminalUi: true,
|
||||
bool ipv6: false,
|
||||
}) async {
|
||||
if (!prebuiltApplication) {
|
||||
printTrace('Building ${app.name} for $id.');
|
||||
@ -352,7 +353,8 @@ class IOSSimulator extends Device {
|
||||
|
||||
ProtocolDiscovery observatoryDiscovery;
|
||||
if (debuggingOptions.debuggingEnabled)
|
||||
observatoryDiscovery = new ProtocolDiscovery.observatory(getLogReader(app: app));
|
||||
observatoryDiscovery = new ProtocolDiscovery.observatory(
|
||||
getLogReader(app: app), ipv6: ipv6);
|
||||
|
||||
// Launch the updated application in the simulator.
|
||||
try {
|
||||
|
@ -5,6 +5,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'base/common.dart';
|
||||
import 'base/io.dart';
|
||||
import 'base/port_scanner.dart';
|
||||
import 'device.dart';
|
||||
import 'globals.dart';
|
||||
@ -18,6 +19,7 @@ class ProtocolDiscovery {
|
||||
this.portForwarder,
|
||||
this.hostPort,
|
||||
this.defaultHostPort,
|
||||
this.ipv6,
|
||||
}) : assert(logReader != null),
|
||||
assert(portForwarder == null || defaultHostPort != null),
|
||||
_prefix = '$serviceName listening on ' {
|
||||
@ -28,6 +30,7 @@ class ProtocolDiscovery {
|
||||
DeviceLogReader logReader, {
|
||||
DevicePortForwarder portForwarder,
|
||||
int hostPort,
|
||||
bool ipv6: false,
|
||||
}) {
|
||||
const String kObservatoryService = 'Observatory';
|
||||
return new ProtocolDiscovery._(
|
||||
@ -35,6 +38,7 @@ class ProtocolDiscovery {
|
||||
portForwarder: portForwarder,
|
||||
hostPort: hostPort,
|
||||
defaultHostPort: kDefaultObservatoryPort,
|
||||
ipv6: ipv6,
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,6 +47,7 @@ class ProtocolDiscovery {
|
||||
final DevicePortForwarder portForwarder;
|
||||
final int hostPort;
|
||||
final int defaultHostPort;
|
||||
final bool ipv6;
|
||||
|
||||
final String _prefix;
|
||||
final Completer<Uri> _completer = new Completer<Uri>();
|
||||
@ -90,6 +95,11 @@ class ProtocolDiscovery {
|
||||
hostUri = deviceUri.replace(port: hostPort);
|
||||
}
|
||||
|
||||
assert(new InternetAddress(hostUri.host).isLoopback);
|
||||
if (ipv6) {
|
||||
hostUri = hostUri.replace(host: InternetAddress.LOOPBACK_IP_V6.host);
|
||||
}
|
||||
|
||||
return hostUri;
|
||||
}
|
||||
}
|
||||
|
@ -273,6 +273,7 @@ class FlutterDevice {
|
||||
prebuiltApplication: prebuiltMode,
|
||||
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies,
|
||||
usesTerminalUi: hotRunner.usesTerminalUI,
|
||||
ipv6: hotRunner.ipv6,
|
||||
);
|
||||
|
||||
final LaunchResult result = await futureResult;
|
||||
@ -316,9 +317,9 @@ class FlutterDevice {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Map<String, dynamic> platformArgs;
|
||||
final Map<String, dynamic> platformArgs = <String, dynamic>{};
|
||||
if (coldRunner.traceStartup != null)
|
||||
platformArgs = <String, dynamic>{ 'trace-startup': coldRunner.traceStartup };
|
||||
platformArgs['trace-startup'] = coldRunner.traceStartup;
|
||||
|
||||
startEchoingDeviceLog();
|
||||
|
||||
@ -332,6 +333,7 @@ class FlutterDevice {
|
||||
prebuiltApplication: prebuiltMode,
|
||||
applicationNeedsRebuild: shouldBuild || hasDirtyDependencies,
|
||||
usesTerminalUi: coldRunner.usesTerminalUI,
|
||||
ipv6: coldRunner.ipv6,
|
||||
);
|
||||
|
||||
if (!result.started) {
|
||||
@ -394,6 +396,7 @@ abstract class ResidentRunner {
|
||||
String packagesFilePath,
|
||||
String projectAssets,
|
||||
this.stayResident,
|
||||
this.ipv6,
|
||||
}) {
|
||||
_mainPath = findMainDartFile(target);
|
||||
_projectRootPath = projectRootPath ?? fs.currentDirectory.path;
|
||||
@ -410,6 +413,7 @@ abstract class ResidentRunner {
|
||||
final DebuggingOptions debuggingOptions;
|
||||
final bool usesTerminalUI;
|
||||
final bool stayResident;
|
||||
final bool ipv6;
|
||||
final Completer<int> _finished = new Completer<int>();
|
||||
bool _stopped = false;
|
||||
String _packagesFilePath;
|
||||
|
@ -22,11 +22,13 @@ class ColdRunner extends ResidentRunner {
|
||||
this.applicationBinary,
|
||||
this.previewDart2 : false,
|
||||
bool stayResident: true,
|
||||
bool ipv6: false,
|
||||
}) : super(devices,
|
||||
target: target,
|
||||
debuggingOptions: debuggingOptions,
|
||||
usesTerminalUI: usesTerminalUI,
|
||||
stayResident: stayResident);
|
||||
stayResident: stayResident,
|
||||
ipv6: ipv6);
|
||||
|
||||
final bool traceStartup;
|
||||
final String applicationBinary;
|
||||
|
@ -45,6 +45,7 @@ class HotRunner extends ResidentRunner {
|
||||
String packagesFilePath,
|
||||
String projectAssets,
|
||||
bool stayResident: true,
|
||||
bool ipv6: false,
|
||||
}) : super(devices,
|
||||
target: target,
|
||||
debuggingOptions: debuggingOptions,
|
||||
@ -52,7 +53,8 @@ class HotRunner extends ResidentRunner {
|
||||
projectRootPath: projectRootPath,
|
||||
packagesFilePath: packagesFilePath,
|
||||
projectAssets: projectAssets,
|
||||
stayResident: stayResident);
|
||||
stayResident: stayResident,
|
||||
ipv6: ipv6);
|
||||
|
||||
final String applicationBinary;
|
||||
final bool hostIsIde;
|
||||
|
@ -104,47 +104,68 @@ void main() {
|
||||
testUsingContext('discovers uri if log line contains non-localhost', () async {
|
||||
initialize();
|
||||
final Future<Uri> uriFuture = discoverer.uri;
|
||||
logReader.addLine('I/flutter : Observatory listening on http://somehost:54804/PTwjm8Ii8qg=/');
|
||||
logReader.addLine('I/flutter : Observatory listening on http://127.0.0.1:54804/PTwjm8Ii8qg=/');
|
||||
final Uri uri = await uriFuture;
|
||||
expect(uri.port, 54804);
|
||||
expect('$uri', 'http://somehost:54804/PTwjm8Ii8qg=/');
|
||||
expect('$uri', 'http://127.0.0.1:54804/PTwjm8Ii8qg=/');
|
||||
});
|
||||
});
|
||||
|
||||
testUsingContext('port forwarding - default port', () async {
|
||||
final MockDeviceLogReader logReader = new MockDeviceLogReader();
|
||||
final ProtocolDiscovery discoverer = new ProtocolDiscovery.observatory(
|
||||
logReader,
|
||||
portForwarder: new MockPortForwarder(99),
|
||||
hostPort: 54777);
|
||||
group('port forwarding', () {
|
||||
testUsingContext('default port', () async {
|
||||
final MockDeviceLogReader logReader = new MockDeviceLogReader();
|
||||
final ProtocolDiscovery discoverer = new ProtocolDiscovery.observatory(
|
||||
logReader,
|
||||
portForwarder: new MockPortForwarder(99),
|
||||
hostPort: 54777);
|
||||
|
||||
// Get next port future.
|
||||
final Future<Uri> nextUri = discoverer.uri;
|
||||
logReader.addLine('I/flutter : Observatory listening on http://somehost:54804/PTwjm8Ii8qg=/');
|
||||
final Uri uri = await nextUri;
|
||||
expect(uri.port, 54777);
|
||||
expect('$uri', 'http://somehost:54777/PTwjm8Ii8qg=/');
|
||||
// Get next port future.
|
||||
final Future<Uri> nextUri = discoverer.uri;
|
||||
logReader.addLine('I/flutter : Observatory listening on http://127.0.0.1:54804/PTwjm8Ii8qg=/');
|
||||
final Uri uri = await nextUri;
|
||||
expect(uri.port, 54777);
|
||||
expect('$uri', 'http://127.0.0.1:54777/PTwjm8Ii8qg=/');
|
||||
|
||||
discoverer.cancel();
|
||||
logReader.dispose();
|
||||
});
|
||||
discoverer.cancel();
|
||||
logReader.dispose();
|
||||
});
|
||||
|
||||
testUsingContext('port forwarding - specified port', () async {
|
||||
final MockDeviceLogReader logReader = new MockDeviceLogReader();
|
||||
final ProtocolDiscovery discoverer = new ProtocolDiscovery.observatory(
|
||||
logReader,
|
||||
portForwarder: new MockPortForwarder(99),
|
||||
hostPort: 1243);
|
||||
testUsingContext('specified port', () async {
|
||||
final MockDeviceLogReader logReader = new MockDeviceLogReader();
|
||||
final ProtocolDiscovery discoverer = new ProtocolDiscovery.observatory(
|
||||
logReader,
|
||||
portForwarder: new MockPortForwarder(99),
|
||||
hostPort: 1243);
|
||||
|
||||
// Get next port future.
|
||||
final Future<Uri> nextUri = discoverer.uri;
|
||||
logReader.addLine('I/flutter : Observatory listening on http://somehost:54804/PTwjm8Ii8qg=/');
|
||||
final Uri uri = await nextUri;
|
||||
expect(uri.port, 1243);
|
||||
expect('$uri', 'http://somehost:1243/PTwjm8Ii8qg=/');
|
||||
// Get next port future.
|
||||
final Future<Uri> nextUri = discoverer.uri;
|
||||
logReader.addLine('I/flutter : Observatory listening on http://127.0.0.1:54804/PTwjm8Ii8qg=/');
|
||||
final Uri uri = await nextUri;
|
||||
expect(uri.port, 1243);
|
||||
expect('$uri', 'http://127.0.0.1:1243/PTwjm8Ii8qg=/');
|
||||
|
||||
discoverer.cancel();
|
||||
logReader.dispose();
|
||||
discoverer.cancel();
|
||||
logReader.dispose();
|
||||
});
|
||||
|
||||
testUsingContext('ipv6', () async {
|
||||
final MockDeviceLogReader logReader = new MockDeviceLogReader();
|
||||
final ProtocolDiscovery discoverer = new ProtocolDiscovery.observatory(
|
||||
logReader,
|
||||
portForwarder: new MockPortForwarder(99),
|
||||
hostPort: 54777,
|
||||
ipv6: true);
|
||||
|
||||
// Get next port future.
|
||||
final Future<Uri> nextUri = discoverer.uri;
|
||||
logReader.addLine('I/flutter : Observatory listening on http://127.0.0.1:54804/PTwjm8Ii8qg=/');
|
||||
final Uri uri = await nextUri;
|
||||
expect(uri.port, 54777);
|
||||
expect('$uri', 'http://[::1]:54777/PTwjm8Ii8qg=/');
|
||||
|
||||
discoverer.cancel();
|
||||
logReader.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user