blob: f9c057cf96dda63c7709c35272b4cb3f66f4d153 [file] [log] [blame]
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// A library used to spawn the Dart Developer Service, used to communicate
/// with a Dart VM Service instance.
library dds;
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:async/async.dart';
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
import 'package:meta/meta.dart';
import 'package:pedantic/pedantic.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_proxy/shelf_proxy.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:sse/server/sse_handler.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
part 'src/binary_compatible_peer.dart';
part 'src/client.dart';
part 'src/client_manager.dart';
part 'src/constants.dart';
part 'src/dds_impl.dart';
part 'src/expression_evaluator.dart';
part 'src/logging_repository.dart';
part 'src/isolate_manager.dart';
part 'src/named_lookup.dart';
part 'src/rpc_error_codes.dart';
part 'src/stream_manager.dart';
/// An intermediary between a Dart VM service and its clients that offers
/// additional functionality on top of the standard VM service protocol.
///
/// See the [Dart Development Service Protocol](https://github.com/dart-lang/sdk/blob/master/pkg/dds/dds_protocol.md)
/// for details.
abstract class DartDevelopmentService {
/// Creates a [DartDevelopmentService] instance which will communicate with a
/// VM service. Requires the target VM service to have no other connected
/// clients.
///
/// [remoteVmServiceUri] is the address of the VM service that this
/// development service will communicate with.
///
/// If provided, [serviceUri] will determine the address and port of the
/// spawned Dart Development Service.
///
/// [enableAuthCodes] controls whether or not an authentication code must
/// be provided by clients when communicating with this instance of
/// [DartDevelopmentService]. Authentication codes take the form of a base64
/// encoded string provided as the first element of the DDS path and is meant
/// to make it more difficult for unintended clients to connect to this
/// service. Authentication codes are enabled by default.
static Future<DartDevelopmentService> startDartDevelopmentService(
Uri remoteVmServiceUri, {
Uri serviceUri,
bool enableAuthCodes = true,
}) async {
if (remoteVmServiceUri == null) {
throw ArgumentError.notNull('remoteVmServiceUri');
}
if (remoteVmServiceUri.scheme != 'http') {
throw ArgumentError(
'remoteVmServiceUri must have an HTTP scheme. Actual: ${remoteVmServiceUri.scheme}',
);
}
if (serviceUri != null && serviceUri.scheme != 'http') {
throw ArgumentError(
'serviceUri must have an HTTP scheme. Actual: ${serviceUri.scheme}',
);
}
final service = _DartDevelopmentService(
remoteVmServiceUri,
serviceUri,
enableAuthCodes,
);
await service.startService();
return service;
}
DartDevelopmentService._();
/// Stop accepting requests after gracefully handling existing requests.
Future<void> shutdown();
/// Set to `true` if this isntance of [DartDevelopmentService] requires an
/// authentication code to connect.
bool get authCodesEnabled;
/// The HTTP [Uri] of the remote VM service instance that this service will
/// forward requests to.
Uri get remoteVmServiceUri;
/// The web socket [Uri] of the remote VM service instance that this service
/// will forward requests to.
///
/// Can be used with [WebSocket] to communicate directly with the VM service.
Uri get remoteVmServiceWsUri;
/// The [Uri] VM service clients can use to communicate with this
/// [DartDevelopmentService] via HTTP.
///
/// Returns `null` if the service is not running.
Uri get uri;
/// The [Uri] VM service clients can use to communicate with this
/// [DartDevelopmentService] via server-sent events (SSE).
///
/// Returns `null` if the service is not running.
Uri get sseUri;
/// The [Uri] VM service clients can use to communicate with this
/// [DartDevelopmentService] via a [WebSocket].
///
/// Returns `null` if the service is not running.
Uri get wsUri;
/// Set to `true` if this instance of [DartDevelopmentService] is accepting
/// requests.
bool get isRunning;
/// The version of the DDS protocol supported by this [DartDevelopmentService]
/// instance.
static const String protocolVersion = '1.1';
}
class DartDevelopmentServiceException implements Exception {
DartDevelopmentServiceException._(this.message);
String toString() => 'DartDevelopmentServiceException: $message';
final String message;
}