| 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 |