Skip to content

Commit 63e4f69

Browse files
committed
Provide an API to dart:developer to control the web server hosting the Service Protocol
- [x] Add `ServiceProtocolnfo` class to dart:developer. - [x] Add `Service` class to dart:developer. - [x] Add `Service.getInfo` static method to dart:developer. - [x] Add `Service.controlWebServer` static method to dart:developer. API: ```dart /// Information about the service protocol. class ServiceProtocolInfo { /// The major version of the protocol. final int majorVersion; /// The minor version of the protocol. final int minorVersion; /// The Uri to access the service. If the web server is not running, this /// will be null. final Uri serverUri; } /// Access information about the service protocol and control the web server. class Service { /// Get information about the service protocol. static Future<ServiceProtocolInfo> getInfo(); /// Control the web server that the service protocol is accessed through. static Future<ServiceProtocolInfo> controlWebServer({bool enable: false}); } ``` ... and add a randomly generated authentication token path prefix that must be passed in to access the service protocol. Old base url: Observatory listening on http://127.0.0.1:54804/ New base url: Observatory listening on http://127.0.0.1:54804/<token>/ For example: Observatory listening on http://127.0.0.1:54804/PTwjm8Ii8qg=/ Many tools will need to be updated. Fixes #23320 BUG= [email protected], [email protected] Review URL: https://codereview.chromium.org/2438613002 .
1 parent b1dfa2a commit 63e4f69

25 files changed

+495
-179
lines changed

CHANGELOG.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
## 1.21.0
2-
### Core library changes
3-
4-
* `dart:core`: `Set.difference` now takes a `Set<Object>` as argument.
52

63
### Language
74

85
* Allow `=` as well as `:` as separator for named parameter default values.
96

7+
### Core library changes
8+
9+
* `dart:core`: `Set.difference` now takes a `Set<Object>` as argument.
10+
11+
* `dart:developer`:
12+
* The service protocol http server can now be controlled from Dart code.
13+
1014
## 1.20.1 - 2016-10-13
1115

1216
Patch release, resolves one issue:

runtime/bin/vmservice/server.dart

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,23 @@ class Server {
126126
final bool _originCheckDisabled;
127127
HttpServer _server;
128128
bool get running => _server != null;
129-
bool _displayMessages = false;
130129

131-
Server(this._service, this._ip, this._port, this._originCheckDisabled) {
132-
_displayMessages = (_ip != '127.0.0.1' || _port != 8181);
130+
/// Returns the server address including the auth token.
131+
Uri get serverAddress {
132+
if (!running) {
133+
return null;
134+
}
135+
var ip = _server.address.address;
136+
var port = _server.port;
137+
if (useAuthToken) {
138+
return Uri.parse('http://$ip:$port/$serviceAuthToken/');
139+
} else {
140+
return Uri.parse('http://$ip:$port/');
141+
}
133142
}
134143

144+
Server(this._service, this._ip, this._port, this._originCheckDisabled);
145+
135146
bool _isAllowedOrigin(String origin) {
136147
Uri uri;
137148
try {
@@ -179,6 +190,28 @@ class Server {
179190
return false;
180191
}
181192

193+
/// Checks the [requestUri] for the service auth token and returns the path.
194+
/// If the service auth token check fails, returns null.
195+
String _checkAuthTokenAndGetPath(Uri requestUri) {
196+
if (!useAuthToken) {
197+
return requestUri.path == '/' ? ROOT_REDIRECT_PATH : requestUri.path;
198+
}
199+
final List<String> requestPathSegments = requestUri.pathSegments;
200+
if (requestPathSegments.length < 2) {
201+
// Malformed.
202+
return null;
203+
}
204+
// Check that we were given the auth token.
205+
final String authToken = requestPathSegments[0];
206+
if (authToken != serviceAuthToken) {
207+
// Malformed.
208+
return null;
209+
}
210+
// Construct the actual request path by chopping off the auth token.
211+
return (requestPathSegments[1] == '') ?
212+
ROOT_REDIRECT_PATH : '/${requestPathSegments.sublist(1).join('/')}';
213+
}
214+
182215
Future _requestHandler(HttpRequest request) async {
183216
if (!_originCheck(request)) {
184217
// This is a cross origin attempt to connect
@@ -231,8 +264,12 @@ class Server {
231264
return;
232265
}
233266

234-
final String path =
235-
request.uri.path == '/' ? ROOT_REDIRECT_PATH : request.uri.path;
267+
final String path = _checkAuthTokenAndGetPath(request.uri);
268+
if (path == null) {
269+
// Malformed.
270+
request.response.close();
271+
return;
272+
}
236273

237274
if (path == WEBSOCKET_PATH) {
238275
WebSocketTransformer.upgrade(request).then(
@@ -274,18 +311,14 @@ class Server {
274311
return HttpServer.bind(address, _port).then((s) {
275312
_server = s;
276313
_server.listen(_requestHandler, cancelOnError: true);
277-
var ip = _server.address.address;
278-
var port = _server.port;
279-
if (_displayMessages) {
280-
print('Observatory listening on http://$ip:$port');
281-
}
314+
print('Observatory listening on $serverAddress');
282315
// Server is up and running.
283-
_notifyServerState(ip, _server.port);
284-
onServerAddressChange('http://$ip:$port');
316+
_notifyServerState(serverAddress.toString());
317+
onServerAddressChange('$serverAddress');
285318
return this;
286319
}).catchError((e, st) {
287320
print('Could not start Observatory HTTP server:\n$e\n$st\n');
288-
_notifyServerState("", 0);
321+
_notifyServerState("");
289322
onServerAddressChange(null);
290323
return this;
291324
});
@@ -304,30 +337,24 @@ class Server {
304337
return new Future.value(this);
305338
}
306339

307-
// Force displaying of status messages if we are forcibly shutdown.
308-
_displayMessages = _displayMessages || forced;
309-
310340
// Shutdown HTTP server and subscription.
311-
var ip = _server.address.address.toString();
312-
var port = _server.port.toString();
341+
String oldServerAddress = serverAddress;
313342
return cleanup(forced).then((_) {
314-
if (_displayMessages) {
315-
print('Observatory no longer listening on http://$ip:$port');
316-
}
343+
print('Observatory no longer listening on $oldServerAddress');
317344
_server = null;
318-
_notifyServerState("", 0);
345+
_notifyServerState("");
319346
onServerAddressChange(null);
320347
return this;
321348
}).catchError((e, st) {
322349
_server = null;
323350
print('Could not shutdown Observatory HTTP server:\n$e\n$st\n');
324-
_notifyServerState("", 0);
351+
_notifyServerState("");
325352
onServerAddressChange(null);
326353
return this;
327354
});
328355
}
329356

330357
}
331358

332-
void _notifyServerState(String ip, int port)
359+
void _notifyServerState(String uri)
333360
native "VMServiceIO_NotifyServerState";

runtime/bin/vmservice/vmservice_io.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,27 @@ Future<List<Map<String,String>>> listFilesCallback(Uri dirPath) async {
162162
return result;
163163
}
164164

165+
Future<Uri> serverInformationCallback() async {
166+
_lazyServerBoot();
167+
return server.serverAddress;
168+
}
169+
170+
Future<Uri> webServerControlCallback(bool enable) async {
171+
_lazyServerBoot();
172+
if (server.running == enable) {
173+
// No change.
174+
return server.serverAddress;
175+
}
176+
177+
if (enable) {
178+
await server.startup();
179+
return server.serverAddress;
180+
} else {
181+
await server.shutdown(true);
182+
return server.serverAddress;
183+
}
184+
}
185+
165186
_clearFuture(_) {
166187
serverFuture = null;
167188
}
@@ -204,6 +225,8 @@ main() {
204225
VMServiceEmbedderHooks.writeStreamFile = writeStreamFileCallback;
205226
VMServiceEmbedderHooks.readFile = readFileCallback;
206227
VMServiceEmbedderHooks.listFiles = listFilesCallback;
228+
VMServiceEmbedderHooks.serverInformation = serverInformationCallback;
229+
VMServiceEmbedderHooks.webServerControl = webServerControlCallback;
207230
// Always instantiate the vmservice object so that the exit message
208231
// can be delivered and waiting loaders can be cancelled.
209232
var service = new VMService();

runtime/bin/vmservice_dartium.cc

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,8 @@ Dart_Isolate VmServiceServer::CreateIsolate(const uint8_t* snapshot_buffer) {
7777
}
7878

7979

80-
const char* VmServiceServer::GetServerIP() {
81-
return VmService::GetServerIP();
82-
}
83-
84-
85-
intptr_t VmServiceServer::GetServerPort() {
86-
return VmService::GetServerPort();
80+
const char* VmServiceServer::GetServerAddress() {
81+
return VmService::GetServerAddress();
8782
}
8883

8984

runtime/bin/vmservice_dartium.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ class VmServiceServer {
1818
static void Bootstrap();
1919
static Dart_Isolate CreateIsolate(const uint8_t* snapshot_buffer);
2020

21-
static const char* GetServerIP();
22-
static intptr_t GetServerPort();
21+
static const char* GetServerAddress();
2322

2423
static void DecompressAssets(const uint8_t* input, unsigned int input_len,
2524
uint8_t** output, unsigned int* output_length);

runtime/bin/vmservice_impl.cc

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -91,27 +91,20 @@ class Resources {
9191

9292
void NotifyServerState(Dart_NativeArguments args) {
9393
Dart_EnterScope();
94-
const char* ip_chars;
95-
Dart_Handle ip_arg = Dart_GetNativeArgument(args, 0);
96-
if (Dart_IsError(ip_arg)) {
97-
VmService::SetServerIPAndPort("", 0);
94+
const char* uri_chars;
95+
Dart_Handle uri_arg = Dart_GetNativeArgument(args, 0);
96+
if (Dart_IsError(uri_arg)) {
97+
VmService::SetServerAddress("");
9898
Dart_ExitScope();
9999
return;
100100
}
101-
Dart_Handle result = Dart_StringToCString(ip_arg, &ip_chars);
101+
Dart_Handle result = Dart_StringToCString(uri_arg, &uri_chars);
102102
if (Dart_IsError(result)) {
103-
VmService::SetServerIPAndPort("", 0);
103+
VmService::SetServerAddress("");
104104
Dart_ExitScope();
105105
return;
106106
}
107-
Dart_Handle port_arg = Dart_GetNativeArgument(args, 1);
108-
if (Dart_IsError(port_arg)) {
109-
VmService::SetServerIPAndPort("", 0);
110-
Dart_ExitScope();
111-
return;
112-
}
113-
int64_t port = DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535);
114-
VmService::SetServerIPAndPort(ip_chars, port);
107+
VmService::SetServerAddress(uri_chars);
115108
Dart_ExitScope();
116109
}
117110

@@ -129,7 +122,7 @@ struct VmServiceIONativeEntry {
129122

130123

131124
static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
132-
{"VMServiceIO_NotifyServerState", 2, NotifyServerState},
125+
{"VMServiceIO_NotifyServerState", 1, NotifyServerState},
133126
{"VMServiceIO_Shutdown", 0, Shutdown },
134127
};
135128

@@ -156,8 +149,7 @@ static Dart_NativeFunction VmServiceIONativeResolver(Dart_Handle name,
156149

157150

158151
const char* VmService::error_msg_ = NULL;
159-
char VmService::server_ip_[kServerIpStringBufferSize];
160-
intptr_t VmService::server_port_ = 0;
152+
char VmService::server_uri_[kServerUriStringBufferSize];
161153

162154

163155
bool VmService::LoadForGenPrecompiled() {
@@ -180,7 +172,7 @@ bool VmService::Setup(const char* server_ip,
180172
bool dev_mode_server) {
181173
Dart_Isolate isolate = Dart_CurrentIsolate();
182174
ASSERT(isolate != NULL);
183-
SetServerIPAndPort("", 0);
175+
SetServerAddress("");
184176

185177
Dart_Handle result;
186178

@@ -290,13 +282,16 @@ const char* VmService::GetErrorMessage() {
290282
}
291283

292284

293-
void VmService::SetServerIPAndPort(const char* ip, intptr_t port) {
294-
if (ip == NULL) {
295-
ip = "";
285+
void VmService::SetServerAddress(const char* server_uri) {
286+
if (server_uri == NULL) {
287+
server_uri = "";
288+
}
289+
const intptr_t server_uri_len = strlen(server_uri);
290+
if (server_uri_len >= (kServerUriStringBufferSize - 1)) {
291+
FATAL1("vm-service: Server URI exceeded length: %s\n", server_uri);
296292
}
297-
strncpy(server_ip_, ip, kServerIpStringBufferSize);
298-
server_ip_[kServerIpStringBufferSize - 1] = '\0';
299-
server_port_ = port;
293+
strncpy(server_uri_, server_uri, kServerUriStringBufferSize);
294+
server_uri_[kServerUriStringBufferSize - 1] = '\0';
300295
}
301296

302297

runtime/bin/vmservice_impl.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,16 @@ class VmService {
2424
// Error message if startup failed.
2525
static const char* GetErrorMessage();
2626

27-
// HTTP server's IP.
28-
static const char* GetServerIP() {
29-
return &server_ip_[0];
30-
}
31-
32-
// HTTP server's port.
33-
static intptr_t GetServerPort() {
34-
return server_port_;
27+
// HTTP Server's address.
28+
static const char* GetServerAddress() {
29+
return &server_uri_[0];
3530
}
3631

3732
private:
38-
static const intptr_t kServerIpStringBufferSize = 256;
33+
static const intptr_t kServerUriStringBufferSize = 1024;
3934
friend void NotifyServerState(Dart_NativeArguments args);
4035

41-
static void SetServerIPAndPort(const char* ip, intptr_t port);
36+
static void SetServerAddress(const char* server_uri_);
4237
static Dart_Handle GetSource(const char* name);
4338
static Dart_Handle LoadScript(const char* name);
4439
static Dart_Handle LoadLibrary(const char* name);
@@ -49,8 +44,7 @@ class VmService {
4944
Dart_Handle url);
5045

5146
static const char* error_msg_;
52-
static char server_ip_[kServerIpStringBufferSize];
53-
static intptr_t server_port_;
47+
static char server_uri_[kServerUriStringBufferSize];
5448

5549
DISALLOW_ALLOCATION();
5650
DISALLOW_IMPLICIT_CONSTRUCTORS(VmService);

0 commit comments

Comments
 (0)