From a80286270cd54c07471bf233677c3e4f0287d998 Mon Sep 17 00:00:00 2001 From: Lau Ching Jun Date: Tue, 19 Mar 2024 14:36:06 -0700 Subject: [PATCH] Fix remote DDS in proxied devices. (#145346) A ProxiedDevice has two port forwarder, one to forward remote host port and another to forward remote device port. During an attach workflow, the port was forwarded by the latter. Update ProxiedDDS to make sure that it works in such case. --- .../lib/src/proxied_devices/devices.dart | 20 ++++-- .../proxied_devices/proxied_devices_test.dart | 63 +++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) 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, );