OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
| 28 #ifdef ENABLE_DEBUGGER_SUPPORT |
28 | 29 |
29 #include "v8.h" | 30 #include "v8.h" |
30 #include "debug.h" | 31 #include "debug.h" |
31 #include "debug-agent.h" | 32 #include "debug-agent.h" |
32 | 33 #include "platform/socket.h" |
33 #ifdef ENABLE_DEBUGGER_SUPPORT | |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 // Public V8 debugger API message handler function. This function just delegates | 38 // Public V8 debugger API message handler function. This function just delegates |
39 // to the debugger agent through it's data parameter. | 39 // to the debugger agent through it's data parameter. |
40 void DebuggerAgentMessageHandler(const v8::Debug::Message& message) { | 40 void DebuggerAgentMessageHandler(const v8::Debug::Message& message) { |
41 DebuggerAgent* agent = Isolate::Current()->debugger_agent_instance(); | 41 DebuggerAgent* agent = Isolate::Current()->debugger_agent_instance(); |
42 ASSERT(agent != NULL); | 42 ASSERT(agent != NULL); |
43 agent->DebuggerMessage(message); | 43 agent->DebuggerMessage(message); |
44 } | 44 } |
45 | 45 |
46 | 46 |
| 47 DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port) |
| 48 : Thread(name), |
| 49 isolate_(isolate), |
| 50 name_(StrDup(name)), |
| 51 port_(port), |
| 52 server_(new Socket), |
| 53 terminate_(false), |
| 54 session_(NULL), |
| 55 terminate_now_(0), |
| 56 listening_(0) { |
| 57 ASSERT(isolate_->debugger_agent_instance() == NULL); |
| 58 isolate_->set_debugger_agent_instance(this); |
| 59 } |
| 60 |
| 61 |
| 62 DebuggerAgent::~DebuggerAgent() { |
| 63 isolate_->set_debugger_agent_instance(NULL); |
| 64 delete server_; |
| 65 } |
| 66 |
| 67 |
47 // Debugger agent main thread. | 68 // Debugger agent main thread. |
48 void DebuggerAgent::Run() { | 69 void DebuggerAgent::Run() { |
49 // Allow this socket to reuse port even if still in TIME_WAIT. | 70 // Allow this socket to reuse port even if still in TIME_WAIT. |
50 server_->SetReuseAddress(true); | 71 server_->SetReuseAddress(true); |
51 | 72 |
52 // First bind the socket to the requested port. | 73 // First bind the socket to the requested port. |
53 bool bound = false; | 74 bool bound = false; |
54 while (!bound && !terminate_) { | 75 while (!bound && !terminate_) { |
55 bound = server_->Bind(port_); | 76 bound = server_->Bind(port_); |
56 | 77 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 } | 126 } |
106 | 127 |
107 static const char* kCreateSessionMessage = | 128 static const char* kCreateSessionMessage = |
108 "Remote debugging session already active\r\n"; | 129 "Remote debugging session already active\r\n"; |
109 | 130 |
110 void DebuggerAgent::CreateSession(Socket* client) { | 131 void DebuggerAgent::CreateSession(Socket* client) { |
111 LockGuard<RecursiveMutex> session_access_guard(&session_access_); | 132 LockGuard<RecursiveMutex> session_access_guard(&session_access_); |
112 | 133 |
113 // If another session is already established terminate this one. | 134 // If another session is already established terminate this one. |
114 if (session_ != NULL) { | 135 if (session_ != NULL) { |
115 client->Send(kCreateSessionMessage, StrLength(kCreateSessionMessage)); | 136 int len = StrLength(kCreateSessionMessage); |
| 137 int res = client->Send(kCreateSessionMessage, len); |
116 delete client; | 138 delete client; |
| 139 USE(res); |
117 return; | 140 return; |
118 } | 141 } |
119 | 142 |
120 // Create a new session and hook up the debug message handler. | 143 // Create a new session and hook up the debug message handler. |
121 session_ = new DebuggerAgentSession(this, client); | 144 session_ = new DebuggerAgentSession(this, client); |
122 isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler); | 145 isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler); |
123 session_->Start(); | 146 session_->Start(); |
124 } | 147 } |
125 | 148 |
126 | 149 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 | 244 |
222 void DebuggerAgentSession::Shutdown() { | 245 void DebuggerAgentSession::Shutdown() { |
223 // Shutdown the socket to end the blocking receive. | 246 // Shutdown the socket to end the blocking receive. |
224 client_->Shutdown(); | 247 client_->Shutdown(); |
225 } | 248 } |
226 | 249 |
227 | 250 |
228 const char* const DebuggerAgentUtil::kContentLength = "Content-Length"; | 251 const char* const DebuggerAgentUtil::kContentLength = "Content-Length"; |
229 | 252 |
230 | 253 |
231 SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) { | 254 SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) { |
232 int received; | 255 int received; |
233 | 256 |
234 // Read header. | 257 // Read header. |
235 int content_length = 0; | 258 int content_length = 0; |
236 while (true) { | 259 while (true) { |
237 const int kHeaderBufferSize = 80; | 260 const int kHeaderBufferSize = 80; |
238 char header_buffer[kHeaderBufferSize]; | 261 char header_buffer[kHeaderBufferSize]; |
239 int header_buffer_position = 0; | 262 int header_buffer_position = 0; |
240 char c = '\0'; // One character receive buffer. | 263 char c = '\0'; // One character receive buffer. |
241 char prev_c = '\0'; // Previous character. | 264 char prev_c = '\0'; // Previous character. |
242 | 265 |
243 // Read until CRLF. | 266 // Read until CRLF. |
244 while (!(c == '\n' && prev_c == '\r')) { | 267 while (!(c == '\n' && prev_c == '\r')) { |
245 prev_c = c; | 268 prev_c = c; |
246 received = conn->Receive(&c, 1); | 269 received = conn->Receive(&c, 1); |
247 if (received == 0) { | 270 if (received == 0) { |
248 PrintF("Error %d\n", Socket::LastError()); | 271 PrintF("Error %d\n", Socket::GetLastError()); |
249 return SmartArrayPointer<char>(); | 272 return SmartArrayPointer<char>(); |
250 } | 273 } |
251 | 274 |
252 // Add character to header buffer. | 275 // Add character to header buffer. |
253 if (header_buffer_position < kHeaderBufferSize) { | 276 if (header_buffer_position < kHeaderBufferSize) { |
254 header_buffer[header_buffer_position++] = c; | 277 header_buffer[header_buffer_position++] = c; |
255 } | 278 } |
256 } | 279 } |
257 | 280 |
258 // Check for end of header (empty header line). | 281 // Check for end of header (empty header line). |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 | 323 |
301 // Return now if no body. | 324 // Return now if no body. |
302 if (content_length == 0) { | 325 if (content_length == 0) { |
303 return SmartArrayPointer<char>(); | 326 return SmartArrayPointer<char>(); |
304 } | 327 } |
305 | 328 |
306 // Read body. | 329 // Read body. |
307 char* buffer = NewArray<char>(content_length + 1); | 330 char* buffer = NewArray<char>(content_length + 1); |
308 received = ReceiveAll(conn, buffer, content_length); | 331 received = ReceiveAll(conn, buffer, content_length); |
309 if (received < content_length) { | 332 if (received < content_length) { |
310 PrintF("Error %d\n", Socket::LastError()); | 333 PrintF("Error %d\n", Socket::GetLastError()); |
311 return SmartArrayPointer<char>(); | 334 return SmartArrayPointer<char>(); |
312 } | 335 } |
313 buffer[content_length] = '\0'; | 336 buffer[content_length] = '\0'; |
314 | 337 |
315 return SmartArrayPointer<char>(buffer); | 338 return SmartArrayPointer<char>(buffer); |
316 } | 339 } |
317 | 340 |
318 | 341 |
319 bool DebuggerAgentUtil::SendConnectMessage(const Socket* conn, | 342 bool DebuggerAgentUtil::SendConnectMessage(Socket* conn, |
320 const char* embedding_host) { | 343 const char* embedding_host) { |
321 static const int kBufferSize = 80; | 344 static const int kBufferSize = 80; |
322 char buffer[kBufferSize]; // Sending buffer. | 345 char buffer[kBufferSize]; // Sending buffer. |
323 bool ok; | 346 bool ok; |
324 int len; | 347 int len; |
325 | 348 |
326 // Send the header. | 349 // Send the header. |
327 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), | 350 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), |
328 "Type: connect\r\n"); | 351 "Type: connect\r\n"); |
329 ok = conn->Send(buffer, len); | 352 ok = conn->Send(buffer, len); |
(...skipping 25 matching lines...) Expand all Loading... |
355 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n"); | 378 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n"); |
356 ok = conn->Send(buffer, len); | 379 ok = conn->Send(buffer, len); |
357 if (!ok) return false; | 380 if (!ok) return false; |
358 | 381 |
359 // No body for connect message. | 382 // No body for connect message. |
360 | 383 |
361 return true; | 384 return true; |
362 } | 385 } |
363 | 386 |
364 | 387 |
365 bool DebuggerAgentUtil::SendMessage(const Socket* conn, | 388 bool DebuggerAgentUtil::SendMessage(Socket* conn, |
366 const Vector<uint16_t> message) { | 389 const Vector<uint16_t> message) { |
367 static const int kBufferSize = 80; | 390 static const int kBufferSize = 80; |
368 char buffer[kBufferSize]; // Sending buffer both for header and body. | 391 char buffer[kBufferSize]; // Sending buffer both for header and body. |
369 | 392 |
370 // Calculate the message size in UTF-8 encoding. | 393 // Calculate the message size in UTF-8 encoding. |
371 int utf8_len = 0; | 394 int utf8_len = 0; |
372 int previous = unibrow::Utf16::kNoPreviousCharacter; | 395 int previous = unibrow::Utf16::kNoPreviousCharacter; |
373 for (int i = 0; i < message.length(); i++) { | 396 for (int i = 0; i < message.length(); i++) { |
374 uint16_t character = message[i]; | 397 uint16_t character = message[i]; |
375 utf8_len += unibrow::Utf8::Length(character, previous); | 398 utf8_len += unibrow::Utf8::Length(character, previous); |
376 previous = character; | 399 previous = character; |
377 } | 400 } |
378 | 401 |
379 // Send the header. | 402 // Send the header. |
380 int len; | 403 int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), |
381 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), | 404 "%s: %d\r\n", kContentLength, utf8_len); |
382 "%s: %d\r\n", kContentLength, utf8_len); | 405 if (conn->Send(buffer, len) < len) { |
383 conn->Send(buffer, len); | 406 return false; |
| 407 } |
384 | 408 |
385 // Terminate header with empty line. | 409 // Terminate header with empty line. |
386 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n"); | 410 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n"); |
387 conn->Send(buffer, len); | 411 if (conn->Send(buffer, len) < len) { |
| 412 return false; |
| 413 } |
388 | 414 |
389 // Send message body as UTF-8. | 415 // Send message body as UTF-8. |
390 int buffer_position = 0; // Current buffer position. | 416 int buffer_position = 0; // Current buffer position. |
391 previous = unibrow::Utf16::kNoPreviousCharacter; | 417 previous = unibrow::Utf16::kNoPreviousCharacter; |
392 for (int i = 0; i < message.length(); i++) { | 418 for (int i = 0; i < message.length(); i++) { |
393 // Write next UTF-8 encoded character to buffer. | 419 // Write next UTF-8 encoded character to buffer. |
394 uint16_t character = message[i]; | 420 uint16_t character = message[i]; |
395 buffer_position += | 421 buffer_position += |
396 unibrow::Utf8::Encode(buffer + buffer_position, character, previous); | 422 unibrow::Utf8::Encode(buffer + buffer_position, character, previous); |
397 ASSERT(buffer_position <= kBufferSize); | 423 ASSERT(buffer_position <= kBufferSize); |
398 | 424 |
399 // Send buffer if full or last character is encoded. | 425 // Send buffer if full or last character is encoded. |
400 if (kBufferSize - buffer_position < | 426 if (kBufferSize - buffer_position < |
401 unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit || | 427 unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit || |
402 i == message.length() - 1) { | 428 i == message.length() - 1) { |
403 if (unibrow::Utf16::IsLeadSurrogate(character)) { | 429 if (unibrow::Utf16::IsLeadSurrogate(character)) { |
404 const int kEncodedSurrogateLength = | 430 const int kEncodedSurrogateLength = |
405 unibrow::Utf16::kUtf8BytesToCodeASurrogate; | 431 unibrow::Utf16::kUtf8BytesToCodeASurrogate; |
406 ASSERT(buffer_position >= kEncodedSurrogateLength); | 432 ASSERT(buffer_position >= kEncodedSurrogateLength); |
407 conn->Send(buffer, buffer_position - kEncodedSurrogateLength); | 433 len = buffer_position - kEncodedSurrogateLength; |
| 434 if (conn->Send(buffer, len) < len) { |
| 435 return false; |
| 436 } |
408 for (int i = 0; i < kEncodedSurrogateLength; i++) { | 437 for (int i = 0; i < kEncodedSurrogateLength; i++) { |
409 buffer[i] = buffer[buffer_position + i]; | 438 buffer[i] = buffer[buffer_position + i]; |
410 } | 439 } |
411 buffer_position = kEncodedSurrogateLength; | 440 buffer_position = kEncodedSurrogateLength; |
412 } else { | 441 } else { |
413 conn->Send(buffer, buffer_position); | 442 len = buffer_position; |
| 443 if (conn->Send(buffer, len) < len) { |
| 444 return false; |
| 445 } |
414 buffer_position = 0; | 446 buffer_position = 0; |
415 } | 447 } |
416 } | 448 } |
417 previous = character; | 449 previous = character; |
418 } | 450 } |
419 | 451 |
420 return true; | 452 return true; |
421 } | 453 } |
422 | 454 |
423 | 455 |
424 bool DebuggerAgentUtil::SendMessage(const Socket* conn, | 456 bool DebuggerAgentUtil::SendMessage(Socket* conn, |
425 const v8::Handle<v8::String> request) { | 457 const v8::Handle<v8::String> request) { |
426 static const int kBufferSize = 80; | 458 static const int kBufferSize = 80; |
427 char buffer[kBufferSize]; // Sending buffer both for header and body. | 459 char buffer[kBufferSize]; // Sending buffer both for header and body. |
428 | 460 |
429 // Convert the request to UTF-8 encoding. | 461 // Convert the request to UTF-8 encoding. |
430 v8::String::Utf8Value utf8_request(request); | 462 v8::String::Utf8Value utf8_request(request); |
431 | 463 |
432 // Send the header. | 464 // Send the header. |
433 int len; | 465 int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), |
434 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), | 466 "Content-Length: %d\r\n", utf8_request.length()); |
435 "Content-Length: %d\r\n", utf8_request.length()); | 467 if (conn->Send(buffer, len) < len) { |
436 conn->Send(buffer, len); | 468 return false; |
| 469 } |
437 | 470 |
438 // Terminate header with empty line. | 471 // Terminate header with empty line. |
439 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n"); | 472 len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n"); |
440 conn->Send(buffer, len); | 473 if (conn->Send(buffer, len) < len) { |
| 474 return false; |
| 475 } |
441 | 476 |
442 // Send message body as UTF-8. | 477 // Send message body as UTF-8. |
443 conn->Send(*utf8_request, utf8_request.length()); | 478 len = utf8_request.length(); |
| 479 if (conn->Send(*utf8_request, len) < len) { |
| 480 return false; |
| 481 } |
444 | 482 |
445 return true; | 483 return true; |
446 } | 484 } |
447 | 485 |
448 | 486 |
449 // Receive the full buffer before returning unless an error occours. | 487 // Receive the full buffer before returning unless an error occours. |
450 int DebuggerAgentUtil::ReceiveAll(const Socket* conn, char* data, int len) { | 488 int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) { |
451 int total_received = 0; | 489 int total_received = 0; |
452 while (total_received < len) { | 490 while (total_received < len) { |
453 int received = conn->Receive(data + total_received, len - total_received); | 491 int received = conn->Receive(data + total_received, len - total_received); |
454 if (received == 0) { | 492 if (received == 0) { |
455 return total_received; | 493 return total_received; |
456 } | 494 } |
457 total_received += received; | 495 total_received += received; |
458 } | 496 } |
459 return total_received; | 497 return total_received; |
460 } | 498 } |
461 | 499 |
462 } } // namespace v8::internal | 500 } } // namespace v8::internal |
463 | 501 |
464 #endif // ENABLE_DEBUGGER_SUPPORT | 502 #endif // ENABLE_DEBUGGER_SUPPORT |
OLD | NEW |