Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / v8 / src / debug-agent.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
28 #ifdef ENABLE_DEBUGGER_SUPPORT
29
30 #include "v8.h"
31 #include "debug.h"
32 #include "debug-agent.h"
33 #include "platform/socket.h"
34
35 namespace v8 {
36 namespace internal {
37
38 // Public V8 debugger API message handler function. This function just delegates
39 // to the debugger agent through it's data parameter.
40 void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
41   Isolate* isolate = reinterpret_cast<Isolate*>(message.GetIsolate());
42   DebuggerAgent* agent = isolate->debugger_agent_instance();
43   ASSERT(agent != NULL);
44   agent->DebuggerMessage(message);
45 }
46
47
48 DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port)
49   : Thread(name),
50     isolate_(isolate),
51     name_(StrDup(name)),
52     port_(port),
53     server_(new Socket),
54     terminate_(false),
55     session_(NULL),
56     terminate_now_(0),
57     listening_(0) {
58   ASSERT(isolate_->debugger_agent_instance() == NULL);
59   isolate_->set_debugger_agent_instance(this);
60 }
61
62
63 DebuggerAgent::~DebuggerAgent() {
64   isolate_->set_debugger_agent_instance(NULL);
65   delete server_;
66 }
67
68
69 // Debugger agent main thread.
70 void DebuggerAgent::Run() {
71   // Allow this socket to reuse port even if still in TIME_WAIT.
72   server_->SetReuseAddress(true);
73
74   // First bind the socket to the requested port.
75   bool bound = false;
76   while (!bound && !terminate_) {
77     bound = server_->Bind(port_);
78
79     // If an error occurred wait a bit before retrying. The most common error
80     // would be that the port is already in use so this avoids a busy loop and
81     // make the agent take over the port when it becomes free.
82     if (!bound) {
83       const TimeDelta kTimeout = TimeDelta::FromSeconds(1);
84       PrintF("Failed to open socket on port %d, "
85           "waiting %d ms before retrying\n", port_,
86           static_cast<int>(kTimeout.InMilliseconds()));
87       if (!terminate_now_.WaitFor(kTimeout)) {
88         if (terminate_) return;
89       }
90     }
91   }
92
93   // Accept connections on the bound port.
94   while (!terminate_) {
95     bool ok = server_->Listen(1);
96     listening_.Signal();
97     if (ok) {
98       // Accept the new connection.
99       Socket* client = server_->Accept();
100       ok = client != NULL;
101       if (ok) {
102         // Create and start a new session.
103         CreateSession(client);
104       }
105     }
106   }
107 }
108
109
110 void DebuggerAgent::Shutdown() {
111   // Set the termination flag.
112   terminate_ = true;
113
114   // Signal termination and make the server exit either its listen call or its
115   // binding loop. This makes sure that no new sessions can be established.
116   terminate_now_.Signal();
117   server_->Shutdown();
118   Join();
119
120   // Close existing session if any.
121   CloseSession();
122 }
123
124
125 void DebuggerAgent::WaitUntilListening() {
126   listening_.Wait();
127 }
128
129 static const char* kCreateSessionMessage =
130     "Remote debugging session already active\r\n";
131
132 void DebuggerAgent::CreateSession(Socket* client) {
133   LockGuard<RecursiveMutex> session_access_guard(&session_access_);
134
135   // If another session is already established terminate this one.
136   if (session_ != NULL) {
137     int len = StrLength(kCreateSessionMessage);
138     int res = client->Send(kCreateSessionMessage, len);
139     delete client;
140     USE(res);
141     return;
142   }
143
144   // Create a new session and hook up the debug message handler.
145   session_ = new DebuggerAgentSession(this, client);
146   isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler);
147   session_->Start();
148 }
149
150
151 void DebuggerAgent::CloseSession() {
152   LockGuard<RecursiveMutex> session_access_guard(&session_access_);
153
154   // Terminate the session.
155   if (session_ != NULL) {
156     session_->Shutdown();
157     session_->Join();
158     delete session_;
159     session_ = NULL;
160   }
161 }
162
163
164 void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
165   LockGuard<RecursiveMutex> session_access_guard(&session_access_);
166
167   // Forward the message handling to the session.
168   if (session_ != NULL) {
169     v8::String::Value val(message.GetJSON());
170     session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
171                               val.length()));
172   }
173 }
174
175
176 DebuggerAgentSession::~DebuggerAgentSession() {
177   delete client_;
178 }
179
180
181 void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
182   // Don't do anything during termination.
183   if (terminate_) {
184     return;
185   }
186
187   // Terminate the session.
188   LockGuard<RecursiveMutex> session_access_guard(&session_access_);
189   ASSERT(session == session_);
190   if (session == session_) {
191     session_->Shutdown();
192     delete session_;
193     session_ = NULL;
194   }
195 }
196
197
198 void DebuggerAgentSession::Run() {
199   // Send the hello message.
200   bool ok = DebuggerAgentUtil::SendConnectMessage(client_, agent_->name_.get());
201   if (!ok) return;
202
203   while (true) {
204     // Read data from the debugger front end.
205     SmartArrayPointer<char> message =
206         DebuggerAgentUtil::ReceiveMessage(client_);
207
208     const char* msg = message.get();
209     bool is_closing_session = (msg == NULL);
210
211     if (msg == NULL) {
212       // If we lost the connection, then simulate a disconnect msg:
213       msg = "{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}";
214
215     } else {
216       // Check if we're getting a disconnect request:
217       const char* disconnectRequestStr =
218           "\"type\":\"request\",\"command\":\"disconnect\"}";
219       const char* result = strstr(msg, disconnectRequestStr);
220       if (result != NULL) {
221         is_closing_session = true;
222       }
223     }
224
225     // Convert UTF-8 to UTF-16.
226     unibrow::Utf8Decoder<128> decoder(msg, StrLength(msg));
227     int utf16_length = decoder.Utf16Length();
228     ScopedVector<uint16_t> temp(utf16_length + 1);
229     decoder.WriteUtf16(temp.start(), utf16_length);
230
231     // Send the request received to the debugger.
232     v8::Debug::SendCommand(temp.start(),
233                            utf16_length,
234                            NULL,
235                            reinterpret_cast<v8::Isolate*>(agent_->isolate()));
236
237     if (is_closing_session) {
238       // Session is closed.
239       agent_->OnSessionClosed(this);
240       return;
241     }
242   }
243 }
244
245
246 void DebuggerAgentSession::DebuggerMessage(Vector<uint16_t> message) {
247   DebuggerAgentUtil::SendMessage(client_, message);
248 }
249
250
251 void DebuggerAgentSession::Shutdown() {
252   // Shutdown the socket to end the blocking receive.
253   client_->Shutdown();
254 }
255
256
257 const char* const DebuggerAgentUtil::kContentLength = "Content-Length";
258
259
260 SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) {
261   int received;
262
263   // Read header.
264   int content_length = 0;
265   while (true) {
266     const int kHeaderBufferSize = 80;
267     char header_buffer[kHeaderBufferSize];
268     int header_buffer_position = 0;
269     char c = '\0';  // One character receive buffer.
270     char prev_c = '\0';  // Previous character.
271
272     // Read until CRLF.
273     while (!(c == '\n' && prev_c == '\r')) {
274       prev_c = c;
275       received = conn->Receive(&c, 1);
276       if (received == 0) {
277         PrintF("Error %d\n", Socket::GetLastError());
278         return SmartArrayPointer<char>();
279       }
280
281       // Add character to header buffer.
282       if (header_buffer_position < kHeaderBufferSize) {
283         header_buffer[header_buffer_position++] = c;
284       }
285     }
286
287     // Check for end of header (empty header line).
288     if (header_buffer_position == 2) {  // Receive buffer contains CRLF.
289       break;
290     }
291
292     // Terminate header.
293     ASSERT(header_buffer_position > 1);  // At least CRLF is received.
294     ASSERT(header_buffer_position <= kHeaderBufferSize);
295     header_buffer[header_buffer_position - 2] = '\0';
296
297     // Split header.
298     char* key = header_buffer;
299     char* value = NULL;
300     for (int i = 0; header_buffer[i] != '\0'; i++) {
301       if (header_buffer[i] == ':') {
302         header_buffer[i] = '\0';
303         value = header_buffer + i + 1;
304         while (*value == ' ') {
305           value++;
306         }
307         break;
308       }
309     }
310
311     // Check that key is Content-Length.
312     if (strcmp(key, kContentLength) == 0) {
313       // Get the content length value if present and within a sensible range.
314       if (value == NULL || strlen(value) > 7) {
315         return SmartArrayPointer<char>();
316       }
317       for (int i = 0; value[i] != '\0'; i++) {
318         // Bail out if illegal data.
319         if (value[i] < '0' || value[i] > '9') {
320           return SmartArrayPointer<char>();
321         }
322         content_length = 10 * content_length + (value[i] - '0');
323       }
324     } else {
325       // For now just print all other headers than Content-Length.
326       PrintF("%s: %s\n", key, value != NULL ? value : "(no value)");
327     }
328   }
329
330   // Return now if no body.
331   if (content_length == 0) {
332     return SmartArrayPointer<char>();
333   }
334
335   // Read body.
336   char* buffer = NewArray<char>(content_length + 1);
337   received = ReceiveAll(conn, buffer, content_length);
338   if (received < content_length) {
339     PrintF("Error %d\n", Socket::GetLastError());
340     return SmartArrayPointer<char>();
341   }
342   buffer[content_length] = '\0';
343
344   return SmartArrayPointer<char>(buffer);
345 }
346
347
348 bool DebuggerAgentUtil::SendConnectMessage(Socket* conn,
349                                            const char* embedding_host) {
350   static const int kBufferSize = 80;
351   char buffer[kBufferSize];  // Sending buffer.
352   bool ok;
353   int len;
354
355   // Send the header.
356   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
357                      "Type: connect\r\n");
358   ok = conn->Send(buffer, len);
359   if (!ok) return false;
360
361   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
362                      "V8-Version: %s\r\n", v8::V8::GetVersion());
363   ok = conn->Send(buffer, len);
364   if (!ok) return false;
365
366   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
367                      "Protocol-Version: 1\r\n");
368   ok = conn->Send(buffer, len);
369   if (!ok) return false;
370
371   if (embedding_host != NULL) {
372     len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
373                        "Embedding-Host: %s\r\n", embedding_host);
374     ok = conn->Send(buffer, len);
375     if (!ok) return false;
376   }
377
378   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
379                      "%s: 0\r\n", kContentLength);
380   ok = conn->Send(buffer, len);
381   if (!ok) return false;
382
383   // Terminate header with empty line.
384   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
385   ok = conn->Send(buffer, len);
386   if (!ok) return false;
387
388   // No body for connect message.
389
390   return true;
391 }
392
393
394 bool DebuggerAgentUtil::SendMessage(Socket* conn,
395                                     const Vector<uint16_t> message) {
396   static const int kBufferSize = 80;
397   char buffer[kBufferSize];  // Sending buffer both for header and body.
398
399   // Calculate the message size in UTF-8 encoding.
400   int utf8_len = 0;
401   int previous = unibrow::Utf16::kNoPreviousCharacter;
402   for (int i = 0; i < message.length(); i++) {
403     uint16_t character = message[i];
404     utf8_len += unibrow::Utf8::Length(character, previous);
405     previous = character;
406   }
407
408   // Send the header.
409   int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
410                          "%s: %d\r\n", kContentLength, utf8_len);
411   if (conn->Send(buffer, len) < len) {
412     return false;
413   }
414
415   // Terminate header with empty line.
416   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
417   if (conn->Send(buffer, len) < len) {
418     return false;
419   }
420
421   // Send message body as UTF-8.
422   int buffer_position = 0;  // Current buffer position.
423   previous = unibrow::Utf16::kNoPreviousCharacter;
424   for (int i = 0; i < message.length(); i++) {
425     // Write next UTF-8 encoded character to buffer.
426     uint16_t character = message[i];
427     buffer_position +=
428         unibrow::Utf8::Encode(buffer + buffer_position, character, previous);
429     ASSERT(buffer_position <= kBufferSize);
430
431     // Send buffer if full or last character is encoded.
432     if (kBufferSize - buffer_position <
433           unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit ||
434         i == message.length() - 1) {
435       if (unibrow::Utf16::IsLeadSurrogate(character)) {
436         const int kEncodedSurrogateLength =
437             unibrow::Utf16::kUtf8BytesToCodeASurrogate;
438         ASSERT(buffer_position >= kEncodedSurrogateLength);
439         len = buffer_position - kEncodedSurrogateLength;
440         if (conn->Send(buffer, len) < len) {
441           return false;
442         }
443         for (int i = 0; i < kEncodedSurrogateLength; i++) {
444           buffer[i] = buffer[buffer_position + i];
445         }
446         buffer_position = kEncodedSurrogateLength;
447       } else {
448         len = buffer_position;
449         if (conn->Send(buffer, len) < len) {
450           return false;
451         }
452         buffer_position = 0;
453       }
454     }
455     previous = character;
456   }
457
458   return true;
459 }
460
461
462 bool DebuggerAgentUtil::SendMessage(Socket* conn,
463                                     const v8::Handle<v8::String> request) {
464   static const int kBufferSize = 80;
465   char buffer[kBufferSize];  // Sending buffer both for header and body.
466
467   // Convert the request to UTF-8 encoding.
468   v8::String::Utf8Value utf8_request(request);
469
470   // Send the header.
471   int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
472                          "Content-Length: %d\r\n", utf8_request.length());
473   if (conn->Send(buffer, len) < len) {
474     return false;
475   }
476
477   // Terminate header with empty line.
478   len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
479   if (conn->Send(buffer, len) < len) {
480     return false;
481   }
482
483   // Send message body as UTF-8.
484   len = utf8_request.length();
485   if (conn->Send(*utf8_request, len) < len) {
486     return false;
487   }
488
489   return true;
490 }
491
492
493 // Receive the full buffer before returning unless an error occours.
494 int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) {
495   int total_received = 0;
496   while (total_received < len) {
497     int received = conn->Receive(data + total_received, len - total_received);
498     if (received == 0) {
499       return total_received;
500     }
501     total_received += received;
502   }
503   return total_received;
504 }
505
506 } }  // namespace v8::internal
507
508 #endif  // ENABLE_DEBUGGER_SUPPORT