Commit 737a55ef authored by Dan Rubel's avatar Dan Rubel Committed by GitHub

handle new Observatory URL (#6992)

parent 27cceff2
......@@ -259,14 +259,15 @@ class AndroidDevice extends Device {
return true;
}
Future<int> _forwardPort(String service, int devicePort, int port) async {
Future<Uri> _forwardUriToNewPort(String service, Uri deviceUri, int port) async {
try {
// Set up port forwarding for observatory.
port = await portForwarder.forward(devicePort, hostPort: port);
printTrace('$service listening on http://127.0.0.1:$port');
return port;
port = await portForwarder.forward(deviceUri.port, hostPort: port);
Uri localUri = deviceUri.replace(port: port);
printTrace('$service listening on $localUri');
return localUri;
} catch (e) {
printError('Unable to forward port $port: $e');
printError('Unable to forward device port ${deviceUri.port} to $port: $e');
}
return null;
}
......@@ -355,35 +356,35 @@ class AndroidDevice extends Device {
printTrace('Waiting for observatory port to be available...');
try {
int observatoryDevicePort, diagnosticDevicePort;
Uri observatoryDeviceUri, diagnosticDeviceUri;
if (debuggingOptions.buildMode == BuildMode.debug) {
Future<List<int>> scrapeServicePorts = Future.wait(
<Future<int>>[observatoryDiscovery.nextPort(), diagnosticDiscovery.nextPort()]
Future<List<Uri>> scrapeServiceUris = Future.wait(
<Future<Uri>>[observatoryDiscovery.nextUri(), diagnosticDiscovery.nextUri()]
);
List<int> devicePorts = await scrapeServicePorts.timeout(new Duration(seconds: 20));
observatoryDevicePort = devicePorts[0];
diagnosticDevicePort = devicePorts[1];
List<Uri> deviceUris = await scrapeServiceUris.timeout(new Duration(seconds: 20));
observatoryDeviceUri = deviceUris[0];
diagnosticDeviceUri = deviceUris[1];
} else {
observatoryDevicePort = await observatoryDiscovery.nextPort().timeout(new Duration(seconds: 20));
observatoryDeviceUri = await observatoryDiscovery.nextUri().timeout(new Duration(seconds: 20));
}
printTrace('observatory port on device: $observatoryDevicePort');
printTrace('Observatory Uri on device: $observatoryDeviceUri');
int observatoryLocalPort = await debuggingOptions.findBestObservatoryPort();
// TODO(devoncarew): Remember the forwarding information (so we can later remove the
// port forwarding).
observatoryLocalPort = await _forwardPort(ProtocolDiscovery.kObservatoryService, observatoryDevicePort, observatoryLocalPort);
Uri observatoryLocalUri = await _forwardUriToNewPort(ProtocolDiscovery.kObservatoryService, observatoryDeviceUri, observatoryLocalPort);
int diagnosticLocalPort;
if (diagnosticDevicePort != null) {
printTrace('diagnostic port on device: $diagnosticDevicePort');
diagnosticLocalPort = await debuggingOptions.findBestDiagnosticPort();
diagnosticLocalPort = await _forwardPort(ProtocolDiscovery.kDiagnosticService, diagnosticDevicePort, diagnosticLocalPort);
Uri diagnosticLocalUri;
if (diagnosticDeviceUri != null) {
printTrace('Diagnostic Server Uri on device: $diagnosticDeviceUri');
int diagnosticLocalPort = await debuggingOptions.findBestDiagnosticPort();
diagnosticLocalUri = await _forwardUriToNewPort(ProtocolDiscovery.kDiagnosticService, diagnosticDeviceUri, diagnosticLocalPort);
}
return new LaunchResult.succeeded(
observatoryPort: observatoryLocalPort,
diagnosticPort: diagnosticLocalPort
observatoryUri: observatoryLocalUri,
diagnosticUri: diagnosticLocalUri,
);
} catch (error) {
if (error is TimeoutException)
......
......@@ -359,8 +359,8 @@ class AppDomain extends Domain {
connectionInfoCompleter = new Completer<DebugConnectionInfo>();
connectionInfoCompleter.future.then((DebugConnectionInfo info) {
Map<String, dynamic> params = <String, dynamic>{
'port': info.port,
'wsUri': info.wsUri
'port': info.httpUri.port,
'wsUri': info.wsUri.toString(),
};
if (info.baseUri != null)
params['baseUri'] = info.baseUri;
......
......@@ -55,10 +55,14 @@ class TraceCommand extends FlutterCommand {
Future<Null> runCommand() async {
int observatoryPort = int.parse(argResults['debug-port']);
// TODO(danrubel): this will break if we move to the new observatory URL
// See https://github.com/flutter/flutter/issues/7038
Uri observatoryUri = Uri.parse('http://127.0.0.1:$observatoryPort');
Tracing tracing;
try {
tracing = await Tracing.connect(observatoryPort);
tracing = await Tracing.connect(observatoryUri);
} catch (error) {
throwToolExit('Error connecting to observatory: $error');
}
......@@ -100,8 +104,8 @@ class TraceCommand extends FlutterCommand {
class Tracing {
Tracing(this.vmService);
static Future<Tracing> connect(int port) {
return VMService.connect(port).then((VMService observatory) => new Tracing(observatory));
static Future<Tracing> connect(Uri uri) {
return VMService.connect(uri).then((VMService observatory) => new Tracing(observatory));
}
final VMService vmService;
......
......@@ -296,22 +296,22 @@ class DebuggingOptions {
}
class LaunchResult {
LaunchResult.succeeded({ this.observatoryPort, this.diagnosticPort }) : started = true;
LaunchResult.failed() : started = false, observatoryPort = null, diagnosticPort = null;
LaunchResult.succeeded({ this.observatoryUri, this.diagnosticUri }) : started = true;
LaunchResult.failed() : started = false, observatoryUri = null, diagnosticUri = null;
bool get hasObservatory => observatoryPort != null;
bool get hasObservatory => observatoryUri != null;
final bool started;
final int observatoryPort;
final int diagnosticPort;
final Uri observatoryUri;
final Uri diagnosticUri;
@override
String toString() {
StringBuffer buf = new StringBuffer('started=$started');
if (observatoryPort != null)
buf.write(', observatory=$observatoryPort');
if (diagnosticPort != null)
buf.write(', diagnostic=$diagnosticPort');
if (observatoryUri != null)
buf.write(', observatory=$observatoryUri');
if (diagnosticUri != null)
buf.write(', diagnostic=$diagnosticUri');
return buf.toString();
}
}
......
......@@ -108,7 +108,7 @@ class HotRunner extends ResidentRunner {
final String applicationBinary;
bool get prebuiltMode => applicationBinary != null;
Set<String> _dartDependencies;
int _observatoryPort;
Uri _observatoryUri;
AssetBundle _bundle;
AssetBundle get bundle => _bundle;
final bool benchmarkMode;
......@@ -216,9 +216,9 @@ class HotRunner extends ResidentRunner {
return 2;
}
_observatoryPort = result.observatoryPort;
_observatoryUri = result.observatoryUri;
try {
await connectToServiceProtocol(_observatoryPort);
await connectToServiceProtocol(_observatoryUri);
} catch (error) {
printError('Error connecting to the service protocol: $error');
return 2;
......@@ -230,8 +230,8 @@ class HotRunner extends ResidentRunner {
if (connectionInfoCompleter != null) {
connectionInfoCompleter.complete(
new DebugConnectionInfo(
port: _observatoryPort,
wsUri: 'ws://localhost:$_observatoryPort/ws',
httpUri: _observatoryUri,
wsUri: vmService.wsAddress,
baseUri: baseUri.toString()
)
);
......@@ -533,7 +533,7 @@ class HotRunner extends ResidentRunner {
ansiAlternative: '$red$fire$bold To hot reload your app on the fly, '
'press "r" or F5. To restart the app entirely, press "R".$reset'
);
printStatus('The Observatory debugger and profiler is available at: http://127.0.0.1:$_observatoryPort/');
printStatus('The Observatory debugger and profiler is available at: $_observatoryUri');
if (details) {
printHelpDetails();
printStatus('To repeat this help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.');
......
......@@ -244,8 +244,8 @@ class IOSDevice extends Device {
}
int installationResult = -1;
int localObsPort;
int localDiagPort;
Uri localObsUri;
Uri localDiagUri;
if (!debuggingOptions.debuggingEnabled) {
// If debugging is not enabled, just launch the application and continue.
......@@ -256,30 +256,34 @@ class IOSDevice extends Device {
// ports post launch.
printTrace("Debugging is enabled, connecting to observatory and the diagnostic server");
Future<int> forwardObsPort = _acquireAndForwardPort(app,
ProtocolDiscovery.kObservatoryService,
debuggingOptions.observatoryPort);
Future<int> forwardDiagPort;
Future<Uri> forwardObsUri = _acquireAndForwardUriToNewPort(
app,
ProtocolDiscovery.kObservatoryService,
debuggingOptions.observatoryPort,
);
Future<Uri> forwardDiagUri;
if (debuggingOptions.buildMode == BuildMode.debug) {
forwardDiagPort = _acquireAndForwardPort(app,
ProtocolDiscovery.kDiagnosticService,
debuggingOptions.diagnosticPort);
forwardDiagUri = _acquireAndForwardUriToNewPort(
app,
ProtocolDiscovery.kDiagnosticService,
debuggingOptions.diagnosticPort,
);
} else {
forwardDiagPort = new Future<int>.value(null);
forwardDiagUri = new Future<Uri>.value(null);
}
Future<int> launch = runCommandAndStreamOutput(launchCommand, trace: true);
List<int> ports = await launch.then((int result) async {
List<Uri> uris = await launch.then((int result) async {
installationResult = result;
if (result != 0) {
printTrace("Failed to launch the application on device.");
return <int>[null, null];
return <Uri>[null, null];
}
printTrace("Application launched on the device. Attempting to forward ports.");
return await Future.wait(<Future<int>>[forwardObsPort, forwardDiagPort])
return await Future.wait(<Future<Uri>>[forwardObsUri, forwardDiagUri])
.timeout(
kPortForwardTimeout,
onTimeout: () {
......@@ -288,11 +292,11 @@ class IOSDevice extends Device {
);
});
printTrace("Local Observatory Port: ${ports[0]}");
printTrace("Local Diagnostic Server Port: ${ports[1]}");
printTrace("Observatory Uri on device: ${uris[0]}");
printTrace("Diagnostic Server Uri on device: ${uris[1]}");
localObsPort = ports[0];
localDiagPort = ports[1];
localObsUri = uris[0];
localDiagUri = uris[1];
}
if (installationResult != 0) {
......@@ -303,25 +307,25 @@ class IOSDevice extends Device {
return new LaunchResult.failed();
}
return new LaunchResult.succeeded(observatoryPort: localObsPort, diagnosticPort: localDiagPort);
return new LaunchResult.succeeded(observatoryUri: localObsUri, diagnosticUri: localDiagUri);
}
Future<int> _acquireAndForwardPort(
Future<Uri> _acquireAndForwardUriToNewPort(
ApplicationPackage app,
String serviceName,
int localPort) async {
Duration stepTimeout = const Duration(seconds: 60);
Future<int> remote = new ProtocolDiscovery(getLogReader(app: app), serviceName).nextPort();
Future<Uri> remote = new ProtocolDiscovery(getLogReader(app: app), serviceName).nextUri();
int remotePort = await remote.timeout(stepTimeout,
Uri remoteUri = await remote.timeout(stepTimeout,
onTimeout: () {
printTrace("Timeout while attempting to retrieve remote port for $serviceName");
printTrace("Timeout while attempting to retrieve remote Uri for $serviceName");
return null;
});
if (remotePort == null) {
printTrace("Could not read port on device for $serviceName");
if (remoteUri == null) {
printTrace("Could not read Uri on device for $serviceName");
return null;
}
......@@ -330,19 +334,22 @@ class IOSDevice extends Device {
printTrace("Auto selected local port to $localPort");
}
int forwardResult = await portForwarder.forward(remotePort,
hostPort: localPort).timeout(stepTimeout, onTimeout: () {
printTrace("Timeout while atempting to foward port for $serviceName");
return null;
});
int forwardResult = await portForwarder
.forward(remoteUri.port, hostPort: localPort)
.timeout(stepTimeout, onTimeout: () {
printTrace("Timeout while atempting to foward port for $serviceName");
return null;
});
if (forwardResult == null) {
printTrace("Could not foward remote $serviceName port $remotePort to local port $localPort");
printTrace("Could not foward remote $serviceName port $remoteUri to local port $localPort");
return null;
}
printStatus('$serviceName listening on http://127.0.0.1:$localPort');
return localPort;
Uri forwardUri = remoteUri.replace(port: forwardResult);
printStatus('$serviceName listening on $forwardUri');
return forwardUri;
}
@override
......
......@@ -474,12 +474,12 @@ class IOSSimulator extends Device {
printTrace('Waiting for observatory port to be available...');
try {
int devicePort = await observatoryDiscovery
.nextPort()
Uri deviceUri = await observatoryDiscovery
.nextUri()
.timeout(new Duration(seconds: 20));
printTrace('service protocol port = $devicePort');
printStatus('Observatory listening on http://127.0.0.1:$devicePort');
return new LaunchResult.succeeded(observatoryPort: devicePort);
printTrace('Observatory Uri on simulator: $deviceUri');
printStatus('Observatory listening on $deviceUri');
return new LaunchResult.succeeded(observatoryUri: deviceUri);
} catch (error) {
if (error is TimeoutException)
printError('Timed out while waiting for a debug connection.');
......
......@@ -21,37 +21,38 @@ class ProtocolDiscovery {
final DeviceLogReader _logReader;
final String _serviceName;
Completer<int> _completer = new Completer<int>();
Completer<Uri> _completer = new Completer<Uri>();
StreamSubscription<String> _subscription;
/// The [Future] returned by this function will complete when the next service
/// protocol port is found.
Future<int> nextPort() => _completer.future;
/// Uri is found.
Future<Uri> nextUri() => _completer.future;
void cancel() {
_subscription.cancel();
}
void _onLine(String line) {
int portNumber = 0;
Uri uri;
if (line.contains('$_serviceName listening on http://')) {
RegExp portExp = new RegExp(r"http://\d+.\d+.\d+.\d+:\d+\S*");
try {
RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)");
String port = portExp.firstMatch(line).group(1);
portNumber = int.parse(port);
String match = portExp.stringMatch(line);
if (match != null)
uri = Uri.parse(match);
} catch (_) {
// Ignore errors.
}
}
if (portNumber != 0)
_located(portNumber);
if (uri != null)
_located(uri);
}
void _located(int port) {
void _located(Uri uri) {
assert(_completer != null);
assert(!_completer.isCompleted);
_completer.complete(port);
_completer = new Completer<int>();
_completer.complete(uri);
_completer = new Completer<Uri>();
}
}
......@@ -119,12 +119,12 @@ abstract class ResidentRunner {
_loggingSubscription = null;
}
Future<Null> connectToServiceProtocol(int port) async {
Future<Null> connectToServiceProtocol(Uri uri) async {
if (!debuggingOptions.debuggingEnabled) {
return new Future<Null>.error('Error the service protocol is not enabled.');
}
vmService = await VMService.connect(port);
printTrace('Connected to service protocol on port $port');
vmService = await VMService.connect(uri);
printTrace('Connected to service protocol: $uri');
await vmService.getVM();
// Refresh the view list.
......@@ -287,9 +287,9 @@ String getMissingPackageHintForPlatform(TargetPlatform platform) {
}
class DebugConnectionInfo {
DebugConnectionInfo({ this.port, this.wsUri, this.baseUri });
DebugConnectionInfo({ this.httpUri, this.wsUri, this.baseUri });
final int port;
final String wsUri;
final Uri httpUri;
final Uri wsUri;
final String baseUri;
}
......@@ -119,19 +119,18 @@ class RunAndStayResident extends ResidentRunner {
startTime.stop();
// Connect to observatory.
if (debuggingOptions.debuggingEnabled) {
await connectToServiceProtocol(_result.observatoryUri);
}
if (_result.hasObservatory) {
int port = _result.observatoryPort;
connectionInfoCompleter?.complete(new DebugConnectionInfo(
port: port,
wsUri: 'ws://localhost:$port/ws'
httpUri: _result.observatoryUri,
wsUri: vmService.wsAddress,
));
}
// Connect to observatory.
if (debuggingOptions.debuggingEnabled) {
await connectToServiceProtocol(_result.observatoryPort);
}
printTrace('Application running.');
if (vmService != null) {
......@@ -176,7 +175,7 @@ class RunAndStayResident extends ResidentRunner {
void printHelp({ @required bool details }) {
bool haveDetails = false;
if (_result.hasObservatory)
printStatus('The Observatory debugger and profiler is available at: http://127.0.0.1:${_result.observatoryPort}/');
printStatus('The Observatory debugger and profiler is available at: ${_result.observatoryUri}');
if (supportsServiceProtocol) {
haveDetails = true;
if (details)
......
......@@ -14,7 +14,7 @@ import 'globals.dart';
/// A connection to the Dart VM Service.
class VMService {
VMService._(this.peer, this.port, this.httpAddress) {
VMService._(this.peer, this.httpAddress, this.wsAddress) {
_vm = new VM._empty(this);
peer.registerMethod('streamNotify', (rpc.Parameters event) {
......@@ -23,21 +23,24 @@ class VMService {
}
/// Connect to '127.0.0.1' at [port].
static Future<VMService> connect(int port) async {
Uri uri = new Uri(scheme: 'ws', host: '127.0.0.1', port: port, path: 'ws');
static Future<VMService> connect(Uri httpUri) async {
String wsPath = httpUri.path;
if (!wsPath.endsWith('/'))
wsPath += '/';
wsPath += 'ws';
Uri wsUri = httpUri.replace(scheme: 'ws', path: wsPath);
WebSocket ws;
try {
ws = await WebSocket.connect(uri.toString());
ws = await WebSocket.connect(wsUri.toString());
} catch (e) {
return new Future<VMService>.error('Failed to connect to $uri\n $e');
return new Future<VMService>.error('Failed to connect to $wsUri\n $e');
}
rpc.Peer peer = new rpc.Peer(new IOWebSocketChannel(ws).cast());
peer.listen();
Uri httpAddress = new Uri(scheme: 'http', host: '127.0.0.1', port: port);
return new VMService._(peer, port, httpAddress);
return new VMService._(peer, httpUri, wsUri);
}
final Uri httpAddress;
final int port;
final Uri wsAddress;
final rpc.Peer peer;
VM _vm;
......
......@@ -17,35 +17,48 @@ void main() {
new ProtocolDiscovery(logReader, ProtocolDiscovery.kObservatoryService);
// Get next port future.
Future<int> nextPort = discoverer.nextPort();
expect(nextPort, isNotNull);
Future<Uri> nextUri = discoverer.nextUri();
expect(nextUri, isNotNull);
// Inject some lines.
logReader.addLine('HELLO WORLD');
logReader.addLine('Observatory listening on http://127.0.0.1:9999');
// Await the port.
expect(await nextPort, 9999);
Uri uri = await nextUri;
expect(uri.port, 9999);
expect('$uri', 'http://127.0.0.1:9999');
// Get next port future.
nextPort = discoverer.nextPort();
nextUri = discoverer.nextUri();
logReader.addLine('Observatory listening on http://127.0.0.1:3333');
expect(await nextPort, 3333);
uri = await nextUri;
expect(uri.port, 3333);
expect('$uri', 'http://127.0.0.1:3333');
// Get next port future.
nextPort = discoverer.nextPort();
nextUri = discoverer.nextUri();
// Inject some bad lines.
logReader.addLine('Observatory listening on http://127.0.0.1');
logReader.addLine('Observatory listening on http://127.0.0.1:');
logReader.addLine('Observatory listening on http://127.0.0.1:apple');
int port = await nextPort.timeout(
const Duration(milliseconds: 100), onTimeout: () => 77);
// Expect the timeout port.
expect(port, 77);
Uri timeoutUri = Uri.parse('http://timeout');
Uri actualUri = await nextUri.timeout(
const Duration(milliseconds: 100), onTimeout: () => timeoutUri);
expect(actualUri, timeoutUri);
// Get next port future.
nextPort = discoverer.nextPort();
nextUri = discoverer.nextUri();
logReader.addLine('I/flutter : Observatory listening on http://127.0.0.1:52584');
expect(await nextPort, 52584);
uri = await nextUri;
expect(uri.port, 52584);
expect('$uri', 'http://127.0.0.1:52584');
// Get next port future.
nextUri = discoverer.nextUri();
logReader.addLine('I/flutter : Observatory listening on http://127.0.0.1:54804/PTwjm8Ii8qg=/');
uri = await nextUri;
expect(uri.port, 54804);
expect('$uri', 'http://127.0.0.1:54804/PTwjm8Ii8qg=/');
discoverer.cancel();
logReader.dispose();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment