Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(900)

Side by Side Diff: runtime/bin/vmstats_impl.cc

Issue 12377099: Added support for "bin-ified" vmstats web app source files (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Final code review changes Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/vmstats/vmstats.html ('k') | runtime/bin/vmstats_sources.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 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 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 #include "bin/vmstats_impl.h" 5 #include "bin/vmstats_impl.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "bin/file.h" 9 #include "bin/file.h"
10 #include "bin/log.h" 10 #include "bin/log.h"
11 #include "bin/platform.h" 11 #include "bin/platform.h"
12 #include "bin/resources.h"
12 #include "bin/socket.h" 13 #include "bin/socket.h"
13 #include "bin/thread.h" 14 #include "bin/thread.h"
14 #include "bin/utils.h" 15 #include "bin/utils.h"
15 #include "include/dart_debugger_api.h" 16 #include "include/dart_debugger_api.h"
16 #include "platform/json.h" 17 #include "platform/json.h"
17 18
18 #define BUFSIZE 8192 19 #define BUFSIZE 8192
19 #define RETRY_PAUSE 100 // milliseconds 20 #define RETRY_PAUSE 100 // milliseconds
20 21
21 static const char* INDEX_HTML = "index.html"; 22 static const char* INDEX_HTML = "index.html";
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 return "image/png"; 126 return "image/png";
126 } 127 }
127 if (!strcmp(suffix, ".jpg") || !strcmp(suffix, ".jpeg")) { 128 if (!strcmp(suffix, ".jpg") || !strcmp(suffix, ".jpeg")) {
128 return "image/jpeg"; 129 return "image/jpeg";
129 } 130 }
130 } 131 }
131 return "text/plain"; 132 return "text/plain";
132 } 133 }
133 134
134 135
136 // Return a malloc'd string from a format string and arguments.
137 intptr_t alloc_printf(char** result, const char* format, ...) {
138 va_list args;
139 va_start(args, format);
140 intptr_t len = vsnprintf(NULL, 0, format, args) + 1;
141 *result = reinterpret_cast<char*>(malloc(len));
142 return vsnprintf(*result, len, format, args);
143 }
144
145
146 void writeResponse(intptr_t socket, const char* content_type,
147 const char* data, size_t length) {
148 char* header;
149 intptr_t len = alloc_printf(&header,
150 "HTTP/1.1 200 OK\nContent-Type: %s\nContent-Length: %"Pu"\n\n",
151 content_type, length);
152 Socket::Write(socket, header, len);
153 Socket::Write(socket, data, length);
154 Socket::Write(socket, "\n", 1);
155 free(header);
156 }
157
158
159 void writeErrorResponse(intptr_t socket, intptr_t error_num, const char* error,
160 const char* description) {
161 if (description != NULL) {
162 // Create body first, so its length is known when creating the header.
163 char* body;
164 intptr_t body_len = alloc_printf(&body,
165 "<html><head><title>%d %s</title></head>\n"
166 "<body>\n<h1>%s</h1>\n%s\n</body></html>\n",
167 error_num, error, error, description);
168 char* header;
169 intptr_t header_len = alloc_printf(&header,
170 "HTTP/1.1 %d %s\n"
171 "Content-Length: %d\n"
172 "Connection: close\n"
173 "Content-Type: text/html\n\n",
174 error_num, error, body_len);
175 Socket::Write(socket, header, header_len);
176 Socket::Write(socket, body, body_len);
177 free(header);
178 free(body);
179 } else {
180 char* response;
181 intptr_t len =
182 alloc_printf(&response, "HTTP/1.1 %d %s\n\n", error_num, error);
183 Socket::Write(socket, response, len);
184 free(response);
185 }
186 }
187
188
135 void VmStats::WebServer(uword bind_address) { 189 void VmStats::WebServer(uword bind_address) {
136 while (true) { 190 while (true) {
137 intptr_t socket = ServerSocket::Accept(bind_address); 191 intptr_t socket = ServerSocket::Accept(bind_address);
138 if (socket == ServerSocket::kTemporaryFailure) { 192 if (socket == ServerSocket::kTemporaryFailure) {
139 // Not a real failure, woke up but no connection available. 193 // Not a real failure, woke up but no connection available.
140 194
141 // Use MonitorLocker.Wait(), since it has finer granularity than sleep(). 195 // Use MonitorLocker.Wait(), since it has finer granularity than sleep().
142 dart::Monitor m; 196 dart::Monitor m;
143 MonitorLocker ml(&m); 197 MonitorLocker ml(&m);
144 ml.Wait(RETRY_PAUSE); 198 ml.Wait(RETRY_PAUSE);
(...skipping 15 matching lines...) Expand all
160 if (len <= 0) { 214 if (len <= 0) {
161 // Invalid HTTP request, ignore. 215 // Invalid HTTP request, ignore.
162 continue; 216 continue;
163 } 217 }
164 buffer[len] = '\0'; 218 buffer[len] = '\0';
165 219
166 // Verify it's a GET request. 220 // Verify it's a GET request.
167 // TODO(tball): support POST requests. 221 // TODO(tball): support POST requests.
168 if (strncmp("GET ", buffer, 4) != 0 && strncmp("get ", buffer, 4) != 0) { 222 if (strncmp("GET ", buffer, 4) != 0 && strncmp("get ", buffer, 4) != 0) {
169 Log::PrintErr("Unsupported HTTP request type"); 223 Log::PrintErr("Unsupported HTTP request type");
170 const char* response = "HTTP/1.1 403 Forbidden\n" 224 writeErrorResponse(socket, 403, "Forbidden",
171 "Content-Length: 120\n" 225 "Unsupported HTTP request type");
172 "Connection: close\n"
173 "Content-Type: text/html\n\n"
174 "<html><head>\n<title>403 Forbidden</title>\n</head>"
175 "<body>\n<h1>Forbidden</h1>\nUnsupported HTTP request type\n</body>"
176 "</html>\n";
177 Socket::Write(socket, response, strlen(response));
178 Socket::Close(socket); 226 Socket::Close(socket);
179 continue; 227 continue;
180 } 228 }
181 229
182 // Extract GET URL, and null-terminate URL in case request line has 230 // Extract GET URL, and null-terminate URL in case request line has
183 // HTTP version. 231 // HTTP version.
184 for (int i = 4; i < len; i++) { 232 for (int i = 4; i < len; i++) {
185 if (buffer[i] == ' ') { 233 if (buffer[i] == ' ') {
186 buffer[i] = '\0'; 234 buffer[i] = '\0';
187 } 235 }
188 } 236 }
189 char* url = &buffer[4]; 237 char* url = strdup(&buffer[4]);
190 238
191 Log::Print("vmstats: %s requested\n", url); 239 Log::Print("vmstats: %s requested\n", url);
192 char* content = NULL; 240 char* content = NULL;
193 241
194 // Check for VmStats-specific URLs. 242 // Check for VmStats-specific URLs.
195 if (strcmp(url, "/isolates") == 0) { 243 if (strcmp(url, "/isolates") == 0) {
196 content = instance_->IsolatesStatus(); 244 content = instance_->IsolatesStatus();
197 } else { 245 } else {
198 // Check plug-ins. 246 // Check plug-ins.
199 content = VmStatusService::GetVmStatus(url); 247 content = VmStatusService::GetVmStatus(url);
200 } 248 }
201 249
202 if (content != NULL) { 250 if (content != NULL) {
203 size_t content_len = strlen(content); 251 writeResponse(socket, "application/json", content, strlen(content));
204 len = snprintf(buffer, BUFSIZE,
205 "HTTP/1.1 200 OK\nContent-Type: application/json; charset=UTF-8\n"
206 "Content-Length: %"Pu"\n\n",
207 content_len);
208 Socket::Write(socket, buffer, strlen(buffer));
209 Socket::Write(socket, content, content_len);
210 Socket::Write(socket, "\n", 1);
211 Socket::Write(socket, buffer, strlen(buffer));
212 free(content); 252 free(content);
213 } else { 253 } else {
214 // No status content with this URL, return file or resource content. 254 // No status content with this URL, return file or resource content.
215 std::string path(instance_->root_directory_); 255 std::string path(instance_->root_directory_);
216 path.append(url); 256 path.append(url);
217 257
218 // Expand directory URLs. 258 // Expand directory URLs.
219 if (strcmp(url, "/") == 0) { 259 if (strcmp(url, "/") == 0) {
220 path.append(VMSTATS_HTML); 260 path.append(VMSTATS_HTML);
221 } else if (url[strlen(url) - 1] == '/') { 261 } else if (url[strlen(url) - 1] == '/') {
222 path.append(INDEX_HTML); 262 path.append(INDEX_HTML);
223 } 263 }
224 264
225 bool success = false; 265 bool success = false;
266 char* text_buffer = NULL;
267 const char* content_type = ContentType(path.c_str());
226 if (File::Exists(path.c_str())) { 268 if (File::Exists(path.c_str())) {
227 File* f = File::Open(path.c_str(), File::kRead); 269 File* f = File::Open(path.c_str(), File::kRead);
228 if (f != NULL) { 270 if (f != NULL) {
229 intptr_t len = f->Length(); 271 intptr_t len = f->Length();
230 char* text_buffer = reinterpret_cast<char*>(malloc(len)); 272 text_buffer = reinterpret_cast<char*>(malloc(len));
231 if (f->ReadFully(text_buffer, len)) { 273 if (f->ReadFully(text_buffer, len)) {
232 const char* content_type = ContentType(path.c_str()); 274 writeResponse(socket, content_type, text_buffer, len);
233 snprintf(buffer, BUFSIZE,
234 "HTTP/1.1 200 OK\nContent-Type: %s\n"
235 "Content-Length: %"Pu"\n\n",
236 content_type, len);
237 Socket::Write(socket, buffer, strlen(buffer));
238 Socket::Write(socket, text_buffer, len);
239 Socket::Write(socket, "\n", 1);
240 success = true; 275 success = true;
241 } 276 }
242 free(text_buffer); 277 free(text_buffer);
243 delete f; 278 delete f;
244 } 279 }
245 } else { 280 } else {
246 // TODO(tball): look up linked in resource. 281 const char* resource;
282 intptr_t len = Resources::ResourceLookup(path.c_str(), &resource);
283 if (len != Resources::kNoSuchInstance) {
284 ASSERT(len >= 0);
285 writeResponse(socket, content_type, resource, len);
286 success = true;
287 }
247 } 288 }
248 if (!success) { 289 if (!success) {
249 const char* response = "HTTP/1.1 404 Not Found\n\n"; 290 char* description;
250 Socket::Write(socket, response, strlen(response)); 291 alloc_printf(
292 &description, "URL <a href=\"%s\">%s</a> not found.", url, url);
293 writeErrorResponse(socket, 404, "Not Found", description);
294 free(description);
251 } 295 }
252 } 296 }
253 Socket::Close(socket); 297 Socket::Close(socket);
298 free(url);
254 } 299 }
255 300
256 Shutdown(); 301 Shutdown();
257 } 302 }
258 303
259 304
260 char* VmStats::IsolatesStatus() { 305 char* VmStats::IsolatesStatus() {
261 std::ostringstream stream; 306 std::ostringstream stream;
262 stream << '{' << std::endl; 307 stream << '{' << std::endl;
263 stream << "\"isolates\": [" << std::endl; 308 stream << "\"isolates\": [" << std::endl;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 VmStatusPlugin* plugin = instance_->registered_plugin_list_; 368 VmStatusPlugin* plugin = instance_->registered_plugin_list_;
324 while (plugin != NULL) { 369 while (plugin != NULL) {
325 char* result = (plugin->callback())(request); 370 char* result = (plugin->callback())(request);
326 if (result != NULL) { 371 if (result != NULL) {
327 return result; 372 return result;
328 } 373 }
329 plugin = plugin->next(); 374 plugin = plugin->next();
330 } 375 }
331 return NULL; 376 return NULL;
332 } 377 }
OLDNEW
« no previous file with comments | « runtime/bin/vmstats/vmstats.html ('k') | runtime/bin/vmstats_sources.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698