1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
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.
4
5#include "bin/vmservice_impl.h"
6
7#include "include/dart_api.h"
8
9#include "bin/builtin.h"
10#include "bin/dartutils.h"
11#include "bin/isolate_data.h"
12#include "bin/platform.h"
13#include "bin/thread.h"
14#include "bin/utils.h"
15#include "platform/text_buffer.h"
16#include "platform/utils.h"
17
18namespace dart {
19namespace bin {
20
21#define RETURN_ERROR_HANDLE(handle) \
22 if (Dart_IsError(handle)) { \
23 return handle; \
24 }
25
26#define SHUTDOWN_ON_ERROR(handle) \
27 if (Dart_IsError(handle)) { \
28 error_msg_ = Utils::StrDup(Dart_GetError(handle)); \
29 Dart_ExitScope(); \
30 Dart_ShutdownIsolate(); \
31 return false; \
32 }
33
34static const char* const kVMServiceIOLibraryUri = "dart:vmservice_io";
35
36void NotifyServerState(Dart_NativeArguments args) {
37 Dart_EnterScope();
38 const char* uri_chars;
39 Dart_Handle uri_arg = Dart_GetNativeArgument(args, 0);
40 if (Dart_IsError(uri_arg)) {
41 VmService::SetServerAddress("");
42 Dart_ExitScope();
43 return;
44 }
45 Dart_Handle result = Dart_StringToCString(uri_arg, &uri_chars);
46 if (Dart_IsError(result)) {
47 VmService::SetServerAddress("");
48 Dart_ExitScope();
49 return;
50 }
51 VmService::SetServerAddress(uri_chars);
52 Dart_ExitScope();
53}
54
55static void Shutdown(Dart_NativeArguments args) {
56 // NO-OP.
57}
58
59struct VmServiceIONativeEntry {
60 const char* name;
61 int num_arguments;
62 Dart_NativeFunction function;
63};
64
65static VmServiceIONativeEntry _VmServiceIONativeEntries[] = {
66 {"VMServiceIO_NotifyServerState", 1, NotifyServerState},
67 {"VMServiceIO_Shutdown", 0, Shutdown},
68};
69
70static Dart_NativeFunction VmServiceIONativeResolver(Dart_Handle name,
71 int num_arguments,
72 bool* auto_setup_scope) {
73 const char* function_name = NULL;
74 Dart_Handle result = Dart_StringToCString(name, &function_name);
75 ASSERT(!Dart_IsError(result));
76 ASSERT(function_name != NULL);
77 *auto_setup_scope = true;
78 intptr_t n =
79 sizeof(_VmServiceIONativeEntries) / sizeof(_VmServiceIONativeEntries[0]);
80 for (intptr_t i = 0; i < n; i++) {
81 VmServiceIONativeEntry entry = _VmServiceIONativeEntries[i];
82 if ((strcmp(function_name, entry.name) == 0) &&
83 (num_arguments == entry.num_arguments)) {
84 return entry.function;
85 }
86 }
87 return NULL;
88}
89
90const uint8_t* VmServiceIONativeSymbol(Dart_NativeFunction nf) {
91 intptr_t n =
92 sizeof(_VmServiceIONativeEntries) / sizeof(_VmServiceIONativeEntries[0]);
93 for (intptr_t i = 0; i < n; i++) {
94 VmServiceIONativeEntry entry = _VmServiceIONativeEntries[i];
95 if (reinterpret_cast<Dart_NativeFunction>(entry.function) == nf) {
96 return reinterpret_cast<const uint8_t*>(entry.name);
97 }
98 }
99 return NULL;
100}
101
102const char* VmService::error_msg_ = NULL;
103char VmService::server_uri_[kServerUriStringBufferSize];
104
105void VmService::SetNativeResolver() {
106 Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
107 Dart_Handle library = Dart_LookupLibrary(url);
108 if (!Dart_IsError(library)) {
109 Dart_SetNativeResolver(library, VmServiceIONativeResolver,
110 VmServiceIONativeSymbol);
111 }
112}
113
114bool VmService::Setup(const char* server_ip,
115 intptr_t server_port,
116 bool dev_mode_server,
117 bool auth_codes_disabled,
118 const char* write_service_info_filename,
119 bool trace_loading,
120 bool deterministic,
121 bool enable_service_port_fallback) {
122 Dart_Isolate isolate = Dart_CurrentIsolate();
123 ASSERT(isolate != NULL);
124 SetServerAddress("");
125
126 Dart_Handle result;
127
128 // Prepare builtin and its dependent libraries for use to resolve URIs.
129 // Set up various closures, e.g: printing, timers etc.
130 // Set up 'package root' for URI resolution.
131 result = DartUtils::PrepareForScriptLoading(/*is_service_isolate=*/true,
132 trace_loading);
133 SHUTDOWN_ON_ERROR(result);
134
135 Dart_Handle url = DartUtils::NewString(kVMServiceIOLibraryUri);
136 Dart_Handle library = Dart_LookupLibrary(url);
137 SHUTDOWN_ON_ERROR(library);
138 result = Dart_SetRootLibrary(library);
139 SHUTDOWN_ON_ERROR(library);
140 result = Dart_SetNativeResolver(library, VmServiceIONativeResolver,
141 VmServiceIONativeSymbol);
142 SHUTDOWN_ON_ERROR(result);
143
144 // Make runnable.
145 Dart_ExitScope();
146 Dart_ExitIsolate();
147 error_msg_ = Dart_IsolateMakeRunnable(isolate);
148 if (error_msg_ != NULL) {
149 Dart_EnterIsolate(isolate);
150 Dart_ShutdownIsolate();
151 return false;
152 }
153 Dart_EnterIsolate(isolate);
154 Dart_EnterScope();
155
156 library = Dart_RootLibrary();
157 SHUTDOWN_ON_ERROR(library);
158
159 // Set HTTP server state.
160 result = DartUtils::SetStringField(library, "_ip", server_ip);
161 SHUTDOWN_ON_ERROR(result);
162 // If we have a port specified, start the server immediately.
163 bool auto_start = server_port >= 0;
164 if (server_port < 0) {
165 // Adjust server_port to port 0 which will result in the first available
166 // port when the HTTP server is started.
167 server_port = 0;
168 }
169 result = DartUtils::SetIntegerField(library, "_port", server_port);
170 SHUTDOWN_ON_ERROR(result);
171 result = Dart_SetField(library, DartUtils::NewString("_autoStart"),
172 Dart_NewBoolean(auto_start));
173 SHUTDOWN_ON_ERROR(result);
174 result = Dart_SetField(library, DartUtils::NewString("_originCheckDisabled"),
175 Dart_NewBoolean(dev_mode_server));
176 SHUTDOWN_ON_ERROR(result);
177
178 result = Dart_SetField(library, DartUtils::NewString("_authCodesDisabled"),
179 Dart_NewBoolean(auth_codes_disabled));
180 SHUTDOWN_ON_ERROR(result);
181
182 result =
183 Dart_SetField(library, DartUtils::NewString("_enableServicePortFallback"),
184 Dart_NewBoolean(enable_service_port_fallback));
185 SHUTDOWN_ON_ERROR(result);
186
187 if (write_service_info_filename != nullptr) {
188 result = DartUtils::SetStringField(library, "_serviceInfoFilename",
189 write_service_info_filename);
190 SHUTDOWN_ON_ERROR(result);
191 }
192// Are we running on Windows?
193#if defined(HOST_OS_WINDOWS)
194 Dart_Handle is_windows = Dart_True();
195#else
196 Dart_Handle is_windows = Dart_False();
197#endif
198 result =
199 Dart_SetField(library, DartUtils::NewString("_isWindows"), is_windows);
200 SHUTDOWN_ON_ERROR(result);
201
202// Are we running on Fuchsia?
203#if defined(HOST_OS_FUCHSIA)
204 Dart_Handle is_fuchsia = Dart_True();
205#else
206 Dart_Handle is_fuchsia = Dart_False();
207#endif
208 result =
209 Dart_SetField(library, DartUtils::NewString("_isFuchsia"), is_fuchsia);
210 SHUTDOWN_ON_ERROR(result);
211
212 // Get _getWatchSignalInternal from dart:io.
213 Dart_Handle dart_io_str = Dart_NewStringFromCString(DartUtils::kIOLibURL);
214 SHUTDOWN_ON_ERROR(dart_io_str);
215 Dart_Handle io_lib = Dart_LookupLibrary(dart_io_str);
216 SHUTDOWN_ON_ERROR(io_lib);
217 Dart_Handle function_name =
218 Dart_NewStringFromCString("_getWatchSignalInternal");
219 SHUTDOWN_ON_ERROR(function_name);
220 Dart_Handle signal_watch = Dart_Invoke(io_lib, function_name, 0, NULL);
221 SHUTDOWN_ON_ERROR(signal_watch);
222 Dart_Handle field_name = Dart_NewStringFromCString("_signalWatch");
223 SHUTDOWN_ON_ERROR(field_name);
224 result = Dart_SetField(library, field_name, signal_watch);
225 SHUTDOWN_ON_ERROR(field_name);
226 return true;
227}
228
229const char* VmService::GetErrorMessage() {
230 return (error_msg_ == NULL) ? "No error." : error_msg_;
231}
232
233void VmService::SetServerAddress(const char* server_uri) {
234 if (server_uri == NULL) {
235 server_uri = "";
236 }
237 const intptr_t server_uri_len = strlen(server_uri);
238 if (server_uri_len >= (kServerUriStringBufferSize - 1)) {
239 FATAL1("vm-service: Server URI exceeded length: %s\n", server_uri);
240 }
241 strncpy(server_uri_, server_uri, kServerUriStringBufferSize);
242 server_uri_[kServerUriStringBufferSize - 1] = '\0';
243}
244
245} // namespace bin
246} // namespace dart
247