blob: 8d52c6ef1ca2779577ab3627a3e10c84e9ca1fbc [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.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
class ServiceClient {
Completer<dynamic>? isolateStartedId;
Completer<dynamic>? isolatePausedId;
Completer<dynamic>? isolateResumeId;
ServiceClient(
this.client, {
this.isolateStartedId,
this.isolatePausedId,
this.isolateResumeId,
}) {
client.listen(_onData, onError: _onError, cancelOnError: true);
}
Future<Map<String, dynamic>> invokeRPC(String method,
[Map<String, dynamic>? params]) async {
final String key = _createKey();
final String request = json.encode(<String, dynamic>{
'jsonrpc': '2.0',
'method': method,
'params': params == null ? <String, dynamic>{} : params,
'id': key,
});
client.add(request);
final Completer<Map<String, dynamic>> completer =
Completer<Map<String, dynamic>>();
_outstandingRequests[key] = completer;
print('-> $key ($method)');
return completer.future;
}
String _createKey() {
final String key = '$_id';
_id++;
return key;
}
void _onData(dynamic message) {
final Map<String, dynamic> response =
json.decode(message as String) as Map<String, dynamic>;
final dynamic key = response['id'];
if (key != null) {
print('<- $key');
final dynamic completer = _outstandingRequests.remove(key);
assert(completer != null);
final dynamic result = response['result'];
final dynamic error = response['error'];
if (error != null) {
assert(result == null);
completer.completeError(error);
} else {
assert(result != null);
completer.complete(result);
}
} else {
if (response['method'] == 'streamNotify') {
_onServiceEvent(response['params'] as Map<String, dynamic>?);
}
}
}
void _onServiceEvent(Map<String, dynamic>? params) {
if (params == null) {
return;
}
final Map<String, dynamic>? event =
params['event'] as Map<String, dynamic>?;
if (event == null || event['type'] != 'Event') {
return;
}
final dynamic isolateId = event['isolate']['id'];
switch (params['streamId']) {
case 'Isolate':
if (event['kind'] == 'IsolateStart') {
isolateStartedId?.complete(isolateId);
}
break;
case 'Debug':
switch (event['kind']) {
case 'Resume':
isolateResumeId?.complete(isolateId);
break;
case 'PauseStart':
isolatePausedId?.complete(isolateId);
break;
}
break;
}
}
void _onError(dynamic error) {
print('WebSocket error: $error');
}
final WebSocket client;
final Map<String, Completer<dynamic>> _outstandingRequests =
<String, Completer<dynamic>>{};
int _id = 1;
}