OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dart._vmservice; | 5 library dart._vmservice; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
| 10 import 'dart:developer' show ServiceProtocolInfo; |
10 import 'dart:isolate'; | 11 import 'dart:isolate'; |
| 12 import 'dart:math'; |
11 import 'dart:typed_data'; | 13 import 'dart:typed_data'; |
12 | 14 |
13 part 'asset.dart'; | 15 part 'asset.dart'; |
14 part 'client.dart'; | 16 part 'client.dart'; |
15 part 'devfs.dart'; | 17 part 'devfs.dart'; |
16 part 'constants.dart'; | 18 part 'constants.dart'; |
17 part 'running_isolate.dart'; | 19 part 'running_isolate.dart'; |
18 part 'running_isolates.dart'; | 20 part 'running_isolates.dart'; |
19 part 'message.dart'; | 21 part 'message.dart'; |
20 part 'message_router.dart'; | 22 part 'message_router.dart'; |
21 | 23 |
22 final RawReceivePort isolateLifecyclePort = new RawReceivePort(); | 24 final RawReceivePort isolateControlPort = new RawReceivePort(); |
23 final RawReceivePort scriptLoadPort = new RawReceivePort(); | 25 final RawReceivePort scriptLoadPort = new RawReceivePort(); |
24 | 26 |
25 abstract class IsolateEmbedderData { | 27 abstract class IsolateEmbedderData { |
26 void cleanup(); | 28 void cleanup(); |
27 } | 29 } |
28 | 30 |
| 31 String _makeAuthToken() { |
| 32 final kTokenByteSize = 8; |
| 33 Uint8List bytes = new Uint8List(kTokenByteSize); |
| 34 Random random = new Random.secure(); |
| 35 for (int i = 0; i < kTokenByteSize; i++) { |
| 36 bytes[i] = random.nextInt(256); |
| 37 } |
| 38 return BASE64URL.encode(bytes); |
| 39 } |
| 40 |
| 41 // The randomly generated auth token used to access the VM service. |
| 42 final String serviceAuthToken = _makeAuthToken(); |
| 43 |
29 // This is for use by the embedder. It is a map from the isolateId to | 44 // This is for use by the embedder. It is a map from the isolateId to |
30 // anything implementing IsolateEmbedderData. When an isolate goes away, | 45 // anything implementing IsolateEmbedderData. When an isolate goes away, |
31 // the cleanup method will be invoked after being removed from the map. | 46 // the cleanup method will be invoked after being removed from the map. |
32 final Map<int, IsolateEmbedderData> isolateEmbedderData = | 47 final Map<int, IsolateEmbedderData> isolateEmbedderData = |
33 new Map<int, IsolateEmbedderData>(); | 48 new Map<int, IsolateEmbedderData>(); |
34 | 49 |
35 // These must be kept in sync with the declarations in vm/json_stream.h. | 50 // These must be kept in sync with the declarations in vm/json_stream.h. |
36 const kInvalidParams = -32602; | 51 const kInvalidParams = -32602; |
37 const kInternalError = -32603; | 52 const kInternalError = -32603; |
38 const kFeatureDisabled = 100; | 53 const kFeatureDisabled = 100; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 | 133 |
119 /// Called to write a stream into a file. | 134 /// Called to write a stream into a file. |
120 typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes); | 135 typedef Future WriteStreamFileCallback(Uri path, Stream<List<int>> bytes); |
121 | 136 |
122 /// Called to read a file. | 137 /// Called to read a file. |
123 typedef Future<List<int>> ReadFileCallback(Uri path); | 138 typedef Future<List<int>> ReadFileCallback(Uri path); |
124 | 139 |
125 /// Called to list all files under some path. | 140 /// Called to list all files under some path. |
126 typedef Future<List<Map<String,String>>> ListFilesCallback(Uri path); | 141 typedef Future<List<Map<String,String>>> ListFilesCallback(Uri path); |
127 | 142 |
| 143 /// Called when we need information about the server. |
| 144 typedef Future<Uri> ServerInformationCallback(); |
| 145 |
| 146 /// Called when we want to [enable] or disable the web server. |
| 147 typedef Future<Uri> WebServerControlCallback(bool enable); |
| 148 |
128 /// Hooks that are setup by the embedder. | 149 /// Hooks that are setup by the embedder. |
129 class VMServiceEmbedderHooks { | 150 class VMServiceEmbedderHooks { |
130 static ServerStartCallback serverStart; | 151 static ServerStartCallback serverStart; |
131 static ServerStopCallback serverStop; | 152 static ServerStopCallback serverStop; |
132 static CleanupCallback cleanup; | 153 static CleanupCallback cleanup; |
133 static CreateTempDirCallback createTempDir; | 154 static CreateTempDirCallback createTempDir; |
134 static DeleteDirCallback deleteDir; | 155 static DeleteDirCallback deleteDir; |
135 static WriteFileCallback writeFile; | 156 static WriteFileCallback writeFile; |
136 static WriteStreamFileCallback writeStreamFile; | 157 static WriteStreamFileCallback writeStreamFile; |
137 static ReadFileCallback readFile; | 158 static ReadFileCallback readFile; |
138 static ListFilesCallback listFiles; | 159 static ListFilesCallback listFiles; |
| 160 static ServerInformationCallback serverInformation; |
| 161 static WebServerControlCallback webServerControl; |
139 } | 162 } |
140 | 163 |
141 class VMService extends MessageRouter { | 164 class VMService extends MessageRouter { |
142 static VMService _instance; | 165 static VMService _instance; |
143 | 166 |
144 /// Collection of currently connected clients. | 167 /// Collection of currently connected clients. |
145 final Set<Client> clients = new Set<Client>(); | 168 final Set<Client> clients = new Set<Client>(); |
146 | 169 |
147 /// Collection of currently running isolates. | 170 /// Collection of currently running isolates. |
148 RunningIsolates runningIsolates = new RunningIsolates(); | 171 RunningIsolates runningIsolates = new RunningIsolates(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID: | 210 case Constants.ISOLATE_SHUTDOWN_MESSAGE_ID: |
188 runningIsolates.isolateShutdown(portId, sp); | 211 runningIsolates.isolateShutdown(portId, sp); |
189 IsolateEmbedderData ied = isolateEmbedderData.remove(portId); | 212 IsolateEmbedderData ied = isolateEmbedderData.remove(portId); |
190 if (ied != null) { | 213 if (ied != null) { |
191 ied.cleanup(); | 214 ied.cleanup(); |
192 } | 215 } |
193 break; | 216 break; |
194 } | 217 } |
195 } | 218 } |
196 | 219 |
| 220 Future<Null> _serverMessageHandler(int code, SendPort sp, bool enable) async { |
| 221 switch (code) { |
| 222 case Constants.WEB_SERVER_CONTROL_MESSAGE_ID: |
| 223 if (VMServiceEmbedderHooks.webServerControl == null) { |
| 224 sp.send(null); |
| 225 return; |
| 226 } |
| 227 Uri uri = await VMServiceEmbedderHooks.webServerControl(enable); |
| 228 sp.send(uri); |
| 229 break; |
| 230 case Constants.SERVER_INFO_MESSAGE_ID: |
| 231 if (VMServiceEmbedderHooks.serverInformation == null) { |
| 232 sp.send(null); |
| 233 return; |
| 234 } |
| 235 Uri uri = await VMServiceEmbedderHooks.serverInformation(); |
| 236 sp.send(uri); |
| 237 break; |
| 238 } |
| 239 } |
| 240 |
197 Future _exit() async { | 241 Future _exit() async { |
198 // Stop the server. | 242 // Stop the server. |
199 if (VMServiceEmbedderHooks.serverStop != null) { | 243 if (VMServiceEmbedderHooks.serverStop != null) { |
200 await VMServiceEmbedderHooks.serverStop(); | 244 await VMServiceEmbedderHooks.serverStop(); |
201 } | 245 } |
202 | 246 |
203 // Close receive ports. | 247 // Close receive ports. |
204 isolateLifecyclePort.close(); | 248 isolateControlPort.close(); |
205 scriptLoadPort.close(); | 249 scriptLoadPort.close(); |
206 | 250 |
207 // Create a copy of the set as a list because client.disconnect() will | 251 // Create a copy of the set as a list because client.disconnect() will |
208 // alter the connected clients set. | 252 // alter the connected clients set. |
209 var clientsList = clients.toList(); | 253 var clientsList = clients.toList(); |
210 for (var client in clientsList) { | 254 for (var client in clientsList) { |
211 client.disconnect(); | 255 client.disconnect(); |
212 } | 256 } |
213 devfs.cleanup(); | 257 devfs.cleanup(); |
214 if (VMServiceEmbedderHooks.cleanup != null) { | 258 if (VMServiceEmbedderHooks.cleanup != null) { |
(...skipping 11 matching lines...) Expand all Loading... |
226 assert(message[1] is String || message[1] is Uint8List); | 270 assert(message[1] is String || message[1] is Uint8List); |
227 _eventMessageHandler(message); | 271 _eventMessageHandler(message); |
228 return; | 272 return; |
229 } | 273 } |
230 if (message.length == 1) { | 274 if (message.length == 1) { |
231 // This is a control message directing the vm service to exit. | 275 // This is a control message directing the vm service to exit. |
232 assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID); | 276 assert(message[0] == Constants.SERVICE_EXIT_MESSAGE_ID); |
233 _exit(); | 277 _exit(); |
234 return; | 278 return; |
235 } | 279 } |
| 280 if (message.length == 3) { |
| 281 // This is a message interacting with the web server. |
| 282 assert((message[0] == Constants.WEB_SERVER_CONTROL_MESSAGE_ID) || |
| 283 (message[0] == Constants.SERVER_INFO_MESSAGE_ID)); |
| 284 _serverMessageHandler(message[0], message[1], message[2]); |
| 285 return; |
| 286 } |
236 if (message.length == 4) { | 287 if (message.length == 4) { |
237 // This is a message informing us of the birth or death of an | 288 // This is a message informing us of the birth or death of an |
238 // isolate. | 289 // isolate. |
239 _controlMessageHandler(message[0], message[1], message[2], message[3]); | 290 _controlMessageHandler(message[0], message[1], message[2], message[3]); |
240 return; | 291 return; |
241 } | 292 } |
242 } | 293 } |
243 print('Internal vm-service error: ignoring illegal message: $message'); | 294 print('Internal vm-service error: ignoring illegal message: $message'); |
244 } | 295 } |
245 | 296 |
246 VMService._internal() | 297 VMService._internal() |
247 : eventPort = isolateLifecyclePort { | 298 : eventPort = isolateControlPort { |
248 eventPort.handler = messageHandler; | 299 eventPort.handler = messageHandler; |
249 } | 300 } |
250 | 301 |
251 factory VMService() { | 302 factory VMService() { |
252 if (VMService._instance == null) { | 303 if (VMService._instance == null) { |
253 VMService._instance = new VMService._internal(); | 304 VMService._instance = new VMService._internal(); |
254 _onStart(); | 305 _onStart(); |
255 } | 306 } |
256 return _instance; | 307 return _instance; |
257 } | 308 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 return devfs.handleMessage(message); | 469 return devfs.handleMessage(message); |
419 } | 470 } |
420 if (message.params['isolateId'] != null) { | 471 if (message.params['isolateId'] != null) { |
421 return runningIsolates.route(message); | 472 return runningIsolates.route(message); |
422 } | 473 } |
423 return message.sendToVM(); | 474 return message.sendToVM(); |
424 } | 475 } |
425 } | 476 } |
426 | 477 |
427 RawReceivePort boot() { | 478 RawReceivePort boot() { |
428 // Return the port we expect isolate startup and shutdown messages on. | 479 // Return the port we expect isolate control messages on. |
429 return isolateLifecyclePort; | 480 return isolateControlPort; |
430 } | 481 } |
431 | 482 |
432 void _registerIsolate(int port_id, SendPort sp, String name) { | 483 void _registerIsolate(int port_id, SendPort sp, String name) { |
433 var service = new VMService(); | 484 var service = new VMService(); |
434 service.runningIsolates.isolateStartup(port_id, sp, name); | 485 service.runningIsolates.isolateStartup(port_id, sp, name); |
435 } | 486 } |
436 | 487 |
437 /// Notify the VM that the service is running. | 488 /// Notify the VM that the service is running. |
438 external void _onStart(); | 489 external void _onStart(); |
439 | 490 |
440 /// Notify the VM that the service is no longer running. | 491 /// Notify the VM that the service is no longer running. |
441 external void _onExit(); | 492 external void _onExit(); |
442 | 493 |
443 /// Notify the VM that the server's address has changed. | 494 /// Notify the VM that the server's address has changed. |
444 external void onServerAddressChange(String address); | 495 external void onServerAddressChange(String address); |
445 | 496 |
446 /// Subscribe to a service stream. | 497 /// Subscribe to a service stream. |
447 external bool _vmListenStream(String streamId); | 498 external bool _vmListenStream(String streamId); |
448 | 499 |
449 /// Cancel a subscription to a service stream. | 500 /// Cancel a subscription to a service stream. |
450 external void _vmCancelStream(String streamId); | 501 external void _vmCancelStream(String streamId); |
451 | 502 |
452 /// Get the bytes to the tar archive. | 503 /// Get the bytes to the tar archive. |
453 external Uint8List _requestAssets(); | 504 external Uint8List _requestAssets(); |
454 | 505 |
455 /// Notify the vm service that an isolate has been spawned via rpc. | 506 /// Notify the vm service that an isolate has been spawned via rpc. |
456 external void _spawnUriNotify(obj, String token); | 507 external void _spawnUriNotify(obj, String token); |
OLD | NEW |