protocol_discovery.dart 3.07 KB
Newer Older
1 2 3 4 5 6
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

7
import 'base/common.dart';
8
import 'base/port_scanner.dart';
9
import 'device.dart';
10
import 'globals.dart';
11

12
/// Discovers a specific service protocol on a device, and forwards the service
13
/// protocol device port to the host.
14
class ProtocolDiscovery {
15
  ProtocolDiscovery._(
16 17
    this.logReader,
    this.serviceName, {
18 19 20
    this.portForwarder,
    this.hostPort,
    this.defaultHostPort,
21 22
  }) : _prefix = '$serviceName listening on ' {
    assert(logReader != null);
23
    assert(portForwarder == null || defaultHostPort != null);
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
    _deviceLogSubscription = logReader.logLines.listen(_handleLine);
  }

  factory ProtocolDiscovery.observatory(
    DeviceLogReader logReader, {
    DevicePortForwarder portForwarder,
    int hostPort,
  }) {
    const String kObservatoryService = 'Observatory';
    return new ProtocolDiscovery._(
      logReader, kObservatoryService,
      portForwarder: portForwarder,
      hostPort: hostPort,
      defaultHostPort: kDefaultObservatoryPort,
    );
39 40
  }

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
  factory ProtocolDiscovery.diagnosticService(
    DeviceLogReader logReader, {
    DevicePortForwarder portForwarder,
    int hostPort,
  }) {
    const String kDiagnosticService = 'Diagnostic server';
    return new ProtocolDiscovery._(
      logReader, kDiagnosticService,
      portForwarder: portForwarder,
      hostPort: hostPort,
      defaultHostPort: kDefaultDiagnosticPort,
    );
  }

  final DeviceLogReader logReader;
  final String serviceName;
57
  final DevicePortForwarder portForwarder;
58
  final int hostPort;
59
  final int defaultHostPort;
60 61

  final String _prefix;
62
  final Completer<Uri> _completer = new Completer<Uri>();
Devon Carew's avatar
Devon Carew committed
63

64
  StreamSubscription<String> _deviceLogSubscription;
65

66
  /// The discovered service URI.
67
  Future<Uri> get uri => _completer.future;
68

69 70 71 72 73
  Future<Null> cancel() => _stopScrapingLogs();

  Future<Null> _stopScrapingLogs() async {
    await _deviceLogSubscription?.cancel();
    _deviceLogSubscription = null;
Devon Carew's avatar
Devon Carew committed
74 75
  }

76
  void _handleLine(String line) {
77
    Uri uri;
78
    final int index = line.indexOf(_prefix + 'http://');
79
    if (index >= 0) {
80
      try {
81
        uri = Uri.parse(line.substring(index + _prefix.length));
82 83 84
      } catch (error) {
        _stopScrapingLogs();
        _completer.completeError(error);
85 86
      }
    }
87 88 89 90 91 92

    if (uri != null) {
      assert(!_completer.isCompleted);
      _stopScrapingLogs();
      _completer.complete(_forwardPort(uri));
    }
93 94
  }

95
  Future<Uri> _forwardPort(Uri deviceUri) async {
96
    printTrace('$serviceName URL on device: $deviceUri');
97 98 99 100 101
    Uri hostUri = deviceUri;

    if (portForwarder != null) {
      final int devicePort = deviceUri.port;
      int hostPort = this.hostPort ?? await portScanner.findPreferredPort(defaultHostPort);
102
      hostPort = await portForwarder.forward(devicePort, hostPort: hostPort);
103
      printTrace('Forwarded host port $hostPort to device port $devicePort for $serviceName');
104 105
      hostUri = deviceUri.replace(port: hostPort);
    }
Devon Carew's avatar
Devon Carew committed
106

107
    return hostUri;
108 109
  }
}