| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library service_common; | 5 library service_common; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:typed_data'; | 9 import 'dart:typed_data'; |
| 10 | 10 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 abstract class CommonWebSocketVM extends VM { | 81 abstract class CommonWebSocketVM extends VM { |
| 82 final Completer _connected = new Completer(); | 82 final Completer _connected = new Completer(); |
| 83 final Completer _disconnected = new Completer<String>(); | 83 final Completer _disconnected = new Completer<String>(); |
| 84 final WebSocketVMTarget target; | 84 final WebSocketVMTarget target; |
| 85 final Map<String, _WebSocketRequest> _delayedRequests = | 85 final Map<String, _WebSocketRequest> _delayedRequests = |
| 86 new Map<String, _WebSocketRequest>(); | 86 new Map<String, _WebSocketRequest>(); |
| 87 final Map<String, _WebSocketRequest> _pendingRequests = | 87 final Map<String, _WebSocketRequest> _pendingRequests = |
| 88 new Map<String, _WebSocketRequest>(); | 88 new Map<String, _WebSocketRequest>(); |
| 89 int _requestSerial = 0; | 89 int _requestSerial = 0; |
| 90 bool _hasInitiatedConnect = false; | 90 bool _hasInitiatedConnect = false; |
| 91 bool _hasFinishedConnect = false; | |
| 92 Utf8Decoder _utf8Decoder = const Utf8Decoder(); | 91 Utf8Decoder _utf8Decoder = const Utf8Decoder(); |
| 93 | 92 |
| 94 String get displayName => '${name}@${target.name}'; | 93 String get displayName => '${name}@${target.name}'; |
| 95 | 94 |
| 96 CommonWebSocket _webSocket; | 95 CommonWebSocket _webSocket; |
| 97 | 96 |
| 98 CommonWebSocketVM(this.target, this._webSocket) { | 97 CommonWebSocketVM(this.target, this._webSocket) { |
| 99 assert(target != null); | 98 assert(target != null); |
| 100 } | 99 } |
| 101 | 100 |
| 102 void _notifyConnect() { | 101 void _notifyConnect() { |
| 103 _hasFinishedConnect = true; | |
| 104 if (!_connected.isCompleted) { | 102 if (!_connected.isCompleted) { |
| 105 Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}'
); | 103 Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}'
); |
| 106 _connected.complete(this); | 104 _connected.complete(this); |
| 107 } | 105 } |
| 108 } | 106 } |
| 109 Future get onConnect => _connected.future; | 107 Future get onConnect => _connected.future; |
| 108 bool get wasOrIsConnected => _connected.isCompleted; |
| 109 bool get isConnected => wasOrIsConnected && !isDisconnected; |
| 110 void _notifyDisconnect(String reason) { | 110 void _notifyDisconnect(String reason) { |
| 111 if (!_hasFinishedConnect) { | |
| 112 return; | |
| 113 } | |
| 114 if (!_disconnected.isCompleted) { | 111 if (!_disconnected.isCompleted) { |
| 115 Logger.root.info('WebSocketVM connection error: ${target.networkAddress}')
; | 112 Logger.root.info('WebSocketVM connection error: ${target.networkAddress}')
; |
| 116 _disconnected.complete(reason); | 113 _disconnected.complete(reason); |
| 117 } | 114 } |
| 118 } | 115 } |
| 119 Future get onDisconnect => _disconnected.future; | 116 Future get onDisconnect => _disconnected.future; |
| 120 bool get isDisconnected => _disconnected.isCompleted; | 117 bool get isDisconnected => _disconnected.isCompleted; |
| 121 | 118 |
| 122 void disconnect({String reason : 'WebSocket closed'}) { | 119 void disconnect({String reason : 'WebSocket closed'}) { |
| 123 if (_hasInitiatedConnect) { | 120 if (_hasInitiatedConnect) { |
| 124 _webSocket.close(); | 121 if (_webSocket != null) { |
| 122 _webSocket.close(); |
| 123 } |
| 125 } | 124 } |
| 126 // We don't need to cancel requests and notify here. These | 125 // We don't need to cancel requests and notify here. These |
| 127 // functions will be called again when the onClose callback | 126 // functions will be called again when the onClose callback |
| 128 // fires. However, we may have a better 'reason' string now, so | 127 // fires. However, we may have a better 'reason' string now, so |
| 129 // let's take care of business. | 128 // let's take care of business. |
| 130 _cancelAllRequests(reason); | 129 _cancelAllRequests(reason); |
| 131 _notifyDisconnect(reason); | 130 _notifyDisconnect(reason); |
| 132 } | 131 } |
| 133 | 132 |
| 134 Future<Map> invokeRpcRaw(String method, Map params) { | 133 Future<Map> invokeRpcRaw(String method, Map params) { |
| 135 if (!_hasInitiatedConnect) { | 134 if (!_hasInitiatedConnect) { |
| 136 _hasInitiatedConnect = true; | 135 _hasInitiatedConnect = true; |
| 137 _webSocket.connect( | 136 try { |
| 138 target.networkAddress, _onOpen, _onMessage, _onError, _onClose); | 137 _webSocket.connect( |
| 138 target.networkAddress, _onOpen, _onMessage, _onError, _onClose); |
| 139 } catch (_) { |
| 140 _webSocket = null; |
| 141 var exception = new NetworkRpcException('WebSocket closed'); |
| 142 return new Future.error(exception); |
| 143 } |
| 139 } | 144 } |
| 140 if (_disconnected.isCompleted) { | 145 if (_disconnected.isCompleted) { |
| 141 // This connection was closed already. | 146 // This connection was closed already. |
| 142 var exception = new NetworkRpcException('WebSocket closed'); | 147 var exception = new NetworkRpcException('WebSocket closed'); |
| 143 return new Future.error(exception); | 148 return new Future.error(exception); |
| 144 } | 149 } |
| 145 String serial = (_requestSerial++).toString(); | 150 String serial = (_requestSerial++).toString(); |
| 146 var request = new _WebSocketRequest(method, params); | 151 var request = new _WebSocketRequest(method, params); |
| 147 if (_webSocket.isOpen) { | 152 if ((_webSocket != null) && _webSocket.isOpen) { |
| 148 // Already connected, send request immediately. | 153 // Already connected, send request immediately. |
| 149 _sendRequest(serial, request); | 154 _sendRequest(serial, request); |
| 150 } else { | 155 } else { |
| 151 // Not connected yet, add to delayed requests. | 156 // Not connected yet, add to delayed requests. |
| 152 _delayedRequests[serial] = request; | 157 _delayedRequests[serial] = request; |
| 153 } | 158 } |
| 154 return request.completer.future; | 159 return request.completer.future; |
| 155 } | 160 } |
| 156 | 161 |
| 157 void _onClose() { | 162 void _onClose() { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 void _onMessage(dynamic data) { | 263 void _onMessage(dynamic data) { |
| 259 if (data is! String) { | 264 if (data is! String) { |
| 260 _onBinaryMessage(data); | 265 _onBinaryMessage(data); |
| 261 } else { | 266 } else { |
| 262 _onStringMessage(data); | 267 _onStringMessage(data); |
| 263 } | 268 } |
| 264 } | 269 } |
| 265 | 270 |
| 266 void _cancelRequests(Map<String,_WebSocketRequest> requests, | 271 void _cancelRequests(Map<String,_WebSocketRequest> requests, |
| 267 String message) { | 272 String message) { |
| 268 requests.forEach((_, _WebSocketRequest request) { | 273 requests.forEach((String serial, _WebSocketRequest request) { |
| 269 var exception = new NetworkRpcException(message); | 274 var exception = new NetworkRpcException(message + |
| 275 '(id: $serial method: ${request.method} params: ${request.params})'); |
| 270 request.completer.completeError(exception); | 276 request.completer.completeError(exception); |
| 271 }); | 277 }); |
| 272 requests.clear(); | 278 requests.clear(); |
| 273 } | 279 } |
| 274 | 280 |
| 275 /// Cancel all pending and delayed requests by completing them with an error. | 281 /// Cancel all pending and delayed requests by completing them with an error. |
| 276 void _cancelAllRequests(String reason) { | 282 void _cancelAllRequests(String reason) { |
| 277 String message = 'Canceling request: $reason'; | 283 String message = 'Canceling request: $reason'; |
| 278 if (_pendingRequests.length > 0) { | 284 if (_pendingRequests.length > 0) { |
| 279 Logger.root.info('Canceling all pending requests.'); | 285 Logger.root.info('Canceling all pending requests.'); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 } | 328 } |
| 323 if (request.method != 'getTagProfile' && | 329 if (request.method != 'getTagProfile' && |
| 324 request.method != 'getIsolateMetric' && | 330 request.method != 'getIsolateMetric' && |
| 325 request.method != 'getVMMetric') { | 331 request.method != 'getVMMetric') { |
| 326 Logger.root.info( | 332 Logger.root.info( |
| 327 'GET [${serial}] ${request.method}(${request.params}) from ${target.ne
tworkAddress}'); | 333 'GET [${serial}] ${request.method}(${request.params}) from ${target.ne
tworkAddress}'); |
| 328 } | 334 } |
| 329 // Send message. | 335 // Send message. |
| 330 _webSocket.send(message); | 336 _webSocket.send(message); |
| 331 } | 337 } |
| 338 |
| 339 String toString() => displayName; |
| 332 } | 340 } |
| OLD | NEW |