diff --git a/packages/flutter_tools/lib/src/proxied_devices/devices.dart b/packages/flutter_tools/lib/src/proxied_devices/devices.dart index 12142a471db..25f2cf4608f 100644 --- a/packages/flutter_tools/lib/src/proxied_devices/devices.dart +++ b/packages/flutter_tools/lib/src/proxied_devices/devices.dart @@ -277,11 +277,11 @@ class ProxiedDevice extends Device { /// [proxiedPortForwarder] forwards a port from the remote host to local host. ProxiedPortForwarder get proxiedPortForwarder => _proxiedPortForwarder ??= ProxiedPortForwarder(connection, logger: _logger); - DevicePortForwarder? _portForwarder; + ProxiedPortForwarder? _portForwarder; /// [portForwarder] forwards a port from the remote device to remote host, and /// then forward the port from remote host to local host. @override - DevicePortForwarder get portForwarder => _portForwarder ??= ProxiedPortForwarder(connection, deviceId: id, logger: _logger); + ProxiedPortForwarder get portForwarder => _portForwarder ??= ProxiedPortForwarder(connection, deviceId: id, logger: _logger); ProxiedDartDevelopmentService? _proxiedDds; @override @@ -290,7 +290,7 @@ class ProxiedDevice extends Device { return super.dds; } return _proxiedDds ??= ProxiedDartDevelopmentService(connection, id, - logger: _logger, proxiedPortForwarder: proxiedPortForwarder); + logger: _logger, proxiedPortForwarder: proxiedPortForwarder, devicePortForwarder: portForwarder); } @override @@ -715,9 +715,11 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService { this.deviceId, { required Logger logger, required ProxiedPortForwarder proxiedPortForwarder, + required ProxiedPortForwarder devicePortForwarder, @visibleForTesting DartDevelopmentService? localDds, }) : _logger = logger, _proxiedPortForwarder = proxiedPortForwarder, + _devicePortForwarder = devicePortForwarder, _localDds = localDds ?? DartDevelopmentService(); final String deviceId; @@ -727,8 +729,14 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService { /// [DaemonConnection] used to communicate with the daemon. final DaemonConnection connection; + /// [_proxiedPortForwarder] matches the [proxiedPortForwarder] of a ProxiedDevice. + /// It forwards a port on the remote host to the local host. final ProxiedPortForwarder _proxiedPortForwarder; + /// [_devicePortForwarder] matches the [portForwarder] of a ProxiedDevice. + /// It forwards a port on the remotely connected device, to the remote host, then to the local host. + final ProxiedPortForwarder _devicePortForwarder; + Uri? _localUri; @override @@ -752,7 +760,11 @@ class ProxiedDartDevelopmentService implements DartDevelopmentService { bool cacheStartupProfile = false, }) async { // Locate the original VM service port on the remote daemon. - final int? remoteVMServicePort = _proxiedPortForwarder.originalRemotePort(vmServiceUri.port); + // A proxied device has two PortForwarder. Check both to determine which + // one forwarded the VM service port. + final int? remoteVMServicePort = + _proxiedPortForwarder.originalRemotePort(vmServiceUri.port) ?? + _devicePortForwarder.originalRemotePort(vmServiceUri.port); if (remoteVMServicePort == null) { _logger.printTrace('VM service port is not a forwarded port. Start DDS locally.'); diff --git a/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart b/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart index 7cbcdf5fc55..e7e4fae67a0 100644 --- a/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart +++ b/packages/flutter_tools/test/general.shard/proxied_devices/proxied_devices_test.dart @@ -607,11 +607,70 @@ void main() { final FakeProxiedPortForwarder portForwarder = FakeProxiedPortForwarder(); portForwarder.originalRemotePortReturnValue = 200; portForwarder.forwardReturnValue = 400; + final FakeProxiedPortForwarder devicePortForwarder = FakeProxiedPortForwarder(); final ProxiedDartDevelopmentService dds = ProxiedDartDevelopmentService( clientDaemonConnection, 'test_id', logger: bufferLogger, proxiedPortForwarder: portForwarder, + devicePortForwarder: devicePortForwarder, + ); + + final Stream broadcastOutput = serverDaemonConnection.incomingCommands.asBroadcastStream(); + + final Future startFuture = dds.startDartDevelopmentService( + Uri.parse('http://127.0.0.1:100/fake'), + disableServiceAuthCodes: true, + hostPort: 150, + ipv6: false, + logger: bufferLogger, + ); + + final DaemonMessage startMessage = await broadcastOutput.first; + expect(startMessage.data['id'], isNotNull); + expect(startMessage.data['method'], 'device.startDartDevelopmentService'); + expect(startMessage.data['params'], { + 'deviceId': 'test_id', + 'vmServiceUri': 'http://127.0.0.1:200/fake', + 'disableServiceAuthCodes': true, + }); + + serverDaemonConnection.sendResponse(startMessage.data['id']!, 'http://127.0.0.1:300/remote'); + + await startFuture; + expect(portForwarder.receivedLocalForwardedPort, 100); + expect(portForwarder.forwardedDevicePort, 300); + expect(portForwarder.forwardedHostPort, 150); + expect(portForwarder.forwardedIpv6, false); + + expect(dds.uri, Uri.parse('http://127.0.0.1:400/remote')); + + expect( + bufferLogger.eventText.trim(), + '{"name":"device.proxied_dds_forwarded","args":{"deviceId":"test_id","remoteUri":"http://127.0.0.1:300/remote","localUri":"http://127.0.0.1:400/remote"}}', + ); + + unawaited(dds.shutdown()); + + final DaemonMessage shutdownMessage = await broadcastOutput.first; + expect(shutdownMessage.data['id'], isNotNull); + expect(shutdownMessage.data['method'], 'device.shutdownDartDevelopmentService'); + expect(shutdownMessage.data['params'], { + 'deviceId': 'test_id', + }); + }); + + testWithoutContext('forwards start and shutdown to remote if port was forwarded by the device port forwarder', () async { + final FakeProxiedPortForwarder portForwarder = FakeProxiedPortForwarder(); + portForwarder.forwardReturnValue = 400; + final FakeProxiedPortForwarder devicePortForwarder = FakeProxiedPortForwarder(); + devicePortForwarder.originalRemotePortReturnValue = 200; + final ProxiedDartDevelopmentService dds = ProxiedDartDevelopmentService( + clientDaemonConnection, + 'test_id', + logger: bufferLogger, + proxiedPortForwarder: portForwarder, + devicePortForwarder: devicePortForwarder, ); final Stream broadcastOutput = serverDaemonConnection.incomingCommands.asBroadcastStream(); @@ -660,6 +719,7 @@ void main() { testWithoutContext('starts a local dds if the VM service port is not a forwarded port', () async { final FakeProxiedPortForwarder portForwarder = FakeProxiedPortForwarder(); + final FakeProxiedPortForwarder devicePortForwarder = FakeProxiedPortForwarder(); final FakeDartDevelopmentService localDds = FakeDartDevelopmentService(); localDds.uri = Uri.parse('http://127.0.0.1:450/local'); final ProxiedDartDevelopmentService dds = ProxiedDartDevelopmentService( @@ -667,6 +727,7 @@ void main() { 'test_id', logger: bufferLogger, proxiedPortForwarder: portForwarder, + devicePortForwarder: devicePortForwarder, localDds: localDds, ); @@ -696,6 +757,7 @@ void main() { testWithoutContext('starts a local dds if the remote VM does not support starting DDS', () async { final FakeProxiedPortForwarder portForwarder = FakeProxiedPortForwarder(); portForwarder.originalRemotePortReturnValue = 200; + final FakeProxiedPortForwarder devicePortForwarder = FakeProxiedPortForwarder(); final FakeDartDevelopmentService localDds = FakeDartDevelopmentService(); localDds.uri = Uri.parse('http://127.0.0.1:450/local'); final ProxiedDartDevelopmentService dds = ProxiedDartDevelopmentService( @@ -703,6 +765,7 @@ void main() { 'test_id', logger: bufferLogger, proxiedPortForwarder: portForwarder, + devicePortForwarder: devicePortForwarder, localDds: localDds, );