7250fd6379
This reverts commit b8c5ecd5aa.
TEST=N/A
Change-Id: I38bbebe1e38bc9dbfdde764eff847aafb3e39353
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/200926
Reviewed-by: Siva Annamalai <asiva@google.com>
70 lines
2.7 KiB
Dart
70 lines
2.7 KiB
Dart
// 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.
|
|
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:async/async.dart';
|
|
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
|
|
import 'package:stream_channel/stream_channel.dart';
|
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
|
|
|
import 'stream_manager.dart';
|
|
|
|
/// Adds support for binary events send from the VM service, which are not part
|
|
/// of the official JSON RPC 2.0 specification.
|
|
///
|
|
/// A binary event from the VM service has the form:
|
|
/// ```
|
|
/// type BinaryEvent {
|
|
/// dataOffset : uint32,
|
|
/// metadata : uint8[dataOffset-4],
|
|
/// data : uint8[],
|
|
/// }
|
|
/// ```
|
|
/// where `metadata` is the JSON body of the event.
|
|
///
|
|
/// [BinaryCompatiblePeer] assumes that only stream events can contain a
|
|
/// binary payload (e.g., clients cannot send a `BinaryEvent` to the VM service).
|
|
class BinaryCompatiblePeer extends json_rpc.Peer {
|
|
BinaryCompatiblePeer(WebSocketChannel ws, StreamManager streamManager)
|
|
: super(
|
|
ws.transform<String>(
|
|
StreamChannelTransformer(
|
|
StreamTransformer<dynamic, String>.fromHandlers(
|
|
handleData: (data, EventSink<String> sink) =>
|
|
_transformStream(streamManager, data, sink)),
|
|
StreamSinkTransformer<String, dynamic>.fromHandlers(
|
|
handleData: (String data, EventSink<dynamic> sink) {
|
|
sink.add(data);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
// Allow for requests without the jsonrpc parameter.
|
|
strictProtocolChecks: false,
|
|
);
|
|
|
|
static void _transformStream(
|
|
StreamManager streamManager, dynamic data, EventSink<String> sink) {
|
|
if (data is String) {
|
|
// Non-binary messages come in as Strings. Simply forward to the sink.
|
|
sink.add(data);
|
|
} else if (data is Uint8List) {
|
|
// Only binary events will result in `data` being of type Uint8List. We
|
|
// need to manually forward them here.
|
|
final bytesView =
|
|
ByteData.view(data.buffer, data.offsetInBytes, data.lengthInBytes);
|
|
const metadataOffset = 4;
|
|
final dataOffset = bytesView.getUint32(0, Endian.little);
|
|
final metadataLength = dataOffset - metadataOffset;
|
|
final metadata = Utf8Decoder().convert(Uint8List.view(bytesView.buffer,
|
|
bytesView.offsetInBytes + metadataOffset, metadataLength));
|
|
final decodedMetadata = json.decode(metadata);
|
|
streamManager.streamNotify(decodedMetadata['params']['streamId'], data);
|
|
}
|
|
}
|
|
}
|