blob: f9d74e31d4d0a25f29c8948ec7fc047cdf86562f [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:convert';
import 'dart:io';
class ServiceClient {
ServiceClient(
this.client, {
this.isolateStartedId,
this.isolatePausedId,
this.isolateResumeId,
}) {
client.listen(_onData, onError: _onError, cancelOnError: true);
}
Completer<Object?>? isolateStartedId;
Completer<Object?>? isolatePausedId;
Completer<Object?>? isolateResumeId;
Future<Map<String, Object?>> invokeRPC(
String method, [
Map<String, Object?>? params,
]) async {
final String key = _createKey();
final String request = json.encode({
'jsonrpc': '2.0',
'method': method,
'params': params ?? <String, Object?>{},
'id': key,
});
client.add(request);
final completer = Completer<Map<String, Object?>>();
_outstandingRequests[key] = completer;
print('-> $key ($method)');
return completer.future;
}
String _createKey() {
final String key = '$_id';
_id++;
return key;
}
void _onData(dynamic message) {
final response = json.decode(message as String) as Map<String, Object?>;
final dynamic key = response['id'];
if (key != null) {
print('<- $key');
final completer = _outstandingRequests.remove(key)!;
final result = response['result'];
final error = response['error'];
if (error != null) {
completer.completeError(error);
} else {
completer.complete(result);
}
} else {
if (response['method'] == 'streamNotify') {
_onServiceEvent(response['params'] as Map<String, Object?>?);
}
}
}
void _onServiceEvent(Map<String, Object?>? params) {
if (params == null) {
return;
}
final event = params['event'] as Map<String, Object?>?;
if (event == null || event['type'] != 'Event') {
return;
}
final dynamic isolateId = (event['isolate']! as Map<String, Object?>)['id'];
switch (params['streamId']) {
case 'Isolate':
if (event['kind'] == 'IsolateStart') {
isolateStartedId?.complete(isolateId);
}
case 'Debug':
switch (event['kind']) {
case 'Resume':
isolateResumeId?.complete(isolateId);
case 'PauseStart':
isolatePausedId?.complete(isolateId);
}
}
}
void _onError(dynamic error) {
print('WebSocket error: $error');
}
final WebSocket client;
final _outstandingRequests = <String, Completer<dynamic>>{};
int _id = 1;
}