OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/dbg_connection.h" | 5 #include "bin/dbg_connection.h" |
6 #include "bin/dbg_message.h" | 6 #include "bin/dbg_message.h" |
7 #include "bin/dartutils.h" | 7 #include "bin/dartutils.h" |
8 #include "bin/log.h" | 8 #include "bin/log.h" |
9 #include "bin/socket.h" | 9 #include "bin/socket.h" |
10 #include "bin/thread.h" | 10 #include "bin/thread.h" |
11 #include "bin/utils.h" | 11 #include "bin/utils.h" |
12 | 12 |
13 #include "platform/globals.h" | 13 #include "platform/globals.h" |
14 #include "platform/json.h" | 14 #include "platform/json.h" |
15 #include "platform/thread.h" | 15 #include "platform/thread.h" |
16 #include "platform/utils.h" | 16 #include "platform/utils.h" |
17 | 17 |
18 #include "include/dart_api.h" | 18 #include "include/dart_api.h" |
19 | 19 |
20 | 20 |
21 namespace dart { | 21 namespace dart { |
22 namespace bin { | 22 namespace bin { |
23 | 23 |
24 extern bool trace_debug_protocol; | 24 extern bool trace_debug_protocol; |
25 | 25 |
26 int DebuggerConnectionHandler::listener_fd_ = -1; | 26 intptr_t DebuggerConnectionHandler::listener_fd_ = -1; |
27 dart::Monitor* DebuggerConnectionHandler::handler_lock_ = new dart::Monitor(); | 27 dart::Monitor* DebuggerConnectionHandler::handler_lock_ = new dart::Monitor(); |
28 | 28 |
29 // TODO(asiva): Remove this once we have support for multiple debugger | 29 // TODO(asiva): Remove this once we have support for multiple debugger |
30 // connections. For now we just store the single debugger connection | 30 // connections. For now we just store the single debugger connection |
31 // handler in a static variable. | 31 // handler in a static variable. |
32 static DebuggerConnectionHandler* singleton_handler = NULL; | 32 static DebuggerConnectionHandler* singleton_handler = NULL; |
33 | 33 |
34 // The maximum message length to print when --trace_debug_protocol is | 34 // The maximum message length to print when --trace_debug_protocol is |
35 // specified. | 35 // specified. |
36 static const int kMaxPrintMessageLen = 1024; | 36 static const int kMaxPrintMessageLen = 1024; |
37 | 37 |
38 class MessageBuffer { | 38 class MessageBuffer { |
39 public: | 39 public: |
40 explicit MessageBuffer(int fd); | 40 explicit MessageBuffer(intptr_t fd); |
41 ~MessageBuffer(); | 41 ~MessageBuffer(); |
42 void ReadData(); | 42 void ReadData(); |
43 bool IsValidMessage() const; | 43 bool IsValidMessage() const; |
44 void PopMessage(); | 44 void PopMessage(); |
45 int MessageId() const; | 45 int MessageId() const; |
46 char* buf() const { return buf_; } | 46 char* buf() const { return buf_; } |
47 bool Alive() const { return connection_is_alive_; } | 47 bool Alive() const { return connection_is_alive_; } |
48 | 48 |
49 private: | 49 private: |
50 static const int kInitialBufferSize = 256; | 50 static const int kInitialBufferSize = 256; |
51 char* buf_; | 51 char* buf_; |
52 int buf_length_; | 52 int buf_length_; |
53 int fd_; | 53 intptr_t fd_; |
54 int data_length_; | 54 int data_length_; |
55 bool connection_is_alive_; | 55 bool connection_is_alive_; |
56 | 56 |
57 DISALLOW_COPY_AND_ASSIGN(MessageBuffer); | 57 DISALLOW_COPY_AND_ASSIGN(MessageBuffer); |
58 }; | 58 }; |
59 | 59 |
60 | 60 |
61 MessageBuffer::MessageBuffer(int fd) | 61 MessageBuffer::MessageBuffer(intptr_t fd) |
62 : buf_(NULL), | 62 : buf_(NULL), |
63 buf_length_(0), | 63 buf_length_(0), |
64 fd_(fd), | 64 fd_(fd), |
65 data_length_(0), | 65 data_length_(0), |
66 connection_is_alive_(true) { | 66 connection_is_alive_(true) { |
67 buf_ = reinterpret_cast<char*>(malloc(kInitialBufferSize)); | 67 buf_ = reinterpret_cast<char*>(malloc(kInitialBufferSize)); |
68 if (buf_ == NULL) { | 68 if (buf_ == NULL) { |
69 FATAL("Failed to allocate message buffer\n"); | 69 FATAL("Failed to allocate message buffer\n"); |
70 } | 70 } |
71 buf_length_ = kInitialBufferSize; | 71 buf_length_ = kInitialBufferSize; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 } | 145 } |
146 } | 146 } |
147 | 147 |
148 | 148 |
149 static bool IsValidJSON(const char* msg) { | 149 static bool IsValidJSON(const char* msg) { |
150 dart::JSONReader r(msg); | 150 dart::JSONReader r(msg); |
151 return r.CheckMessage(); | 151 return r.CheckMessage(); |
152 } | 152 } |
153 | 153 |
154 | 154 |
155 DebuggerConnectionHandler::DebuggerConnectionHandler(int debug_fd) | 155 DebuggerConnectionHandler::DebuggerConnectionHandler(intptr_t debug_fd) |
156 : debug_fd_(debug_fd), msgbuf_(NULL) { | 156 : debug_fd_(debug_fd), msgbuf_(NULL) { |
157 msgbuf_ = new MessageBuffer(debug_fd_); | 157 msgbuf_ = new MessageBuffer(debug_fd_); |
158 } | 158 } |
159 | 159 |
160 | 160 |
161 DebuggerConnectionHandler::~DebuggerConnectionHandler() { | 161 DebuggerConnectionHandler::~DebuggerConnectionHandler() { |
162 CloseDbgConnection(); | 162 CloseDbgConnection(); |
163 DebuggerConnectionHandler::RemoveDebuggerConnection(debug_fd_); | 163 DebuggerConnectionHandler::RemoveDebuggerConnection(debug_fd_); |
164 } | 164 } |
165 | 165 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 return; | 201 return; |
202 } | 202 } |
203 | 203 |
204 if (trace_debug_protocol) { | 204 if (trace_debug_protocol) { |
205 dart::JSONReader r(msgbuf_->buf()); | 205 dart::JSONReader r(msgbuf_->buf()); |
206 const char* msg_end = r.EndOfObject(); | 206 const char* msg_end = r.EndOfObject(); |
207 if (msg_end != NULL) { | 207 if (msg_end != NULL) { |
208 intptr_t msg_len = msg_end - msgbuf_->buf(); | 208 intptr_t msg_len = msg_end - msgbuf_->buf(); |
209 int print_len = ((msg_len > kMaxPrintMessageLen) | 209 int print_len = ((msg_len > kMaxPrintMessageLen) |
210 ? kMaxPrintMessageLen : msg_len); | 210 ? kMaxPrintMessageLen : msg_len); |
211 Log::Print("[<<<] Receiving message from debug fd %d:\n%.*s%s\n", | 211 Log::Print("[<<<] Receiving message from debug fd %" Pd ":\n%.*s%s\n", |
212 debug_fd_, print_len, msgbuf_->buf(), | 212 debug_fd_, print_len, msgbuf_->buf(), |
213 ((msg_len > print_len) ? "..." : "")); | 213 ((msg_len > print_len) ? "..." : "")); |
214 } | 214 } |
215 } | 215 } |
216 | 216 |
217 // Parse out the command portion from the message. | 217 // Parse out the command portion from the message. |
218 dart::JSONReader r(msgbuf_->buf()); | 218 dart::JSONReader r(msgbuf_->buf()); |
219 bool found = r.Seek("command"); | 219 bool found = r.Seek("command"); |
220 if (r.Error()) { | 220 if (r.Error()) { |
221 FATAL("Illegal JSON message received"); | 221 FATAL("Illegal JSON message received"); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 | 266 |
267 // This is an unrecognized command, report error and move on to next. | 267 // This is an unrecognized command, report error and move on to next. |
268 Log::Print("unrecognized command received: '%s'\n", msgbuf_->buf()); | 268 Log::Print("unrecognized command received: '%s'\n", msgbuf_->buf()); |
269 HandleUnknownMsg(); | 269 HandleUnknownMsg(); |
270 msgbuf_->PopMessage(); | 270 msgbuf_->PopMessage(); |
271 } | 271 } |
272 } | 272 } |
273 } | 273 } |
274 | 274 |
275 | 275 |
276 void DebuggerConnectionHandler::SendError(int debug_fd, | 276 void DebuggerConnectionHandler::SendError(intptr_t debug_fd, |
277 int msg_id, | 277 int msg_id, |
278 const char* err_msg) { | 278 const char* err_msg) { |
279 dart::TextBuffer msg(64); | 279 dart::TextBuffer msg(64); |
280 msg.Printf("{\"id\": %d, \"error\": \"Error: ", msg_id); | 280 msg.Printf("{\"id\": %d, \"error\": \"Error: ", msg_id); |
281 msg.AddEscapedString(err_msg); | 281 msg.AddEscapedString(err_msg); |
282 msg.Printf("\"}"); | 282 msg.Printf("\"}"); |
283 SendMsg(debug_fd, &msg); | 283 SendMsg(debug_fd, &msg); |
284 } | 284 } |
285 | 285 |
286 | 286 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 // connections. | 345 // connections. |
346 return; | 346 return; |
347 } | 347 } |
348 while (!IsConnected()) { | 348 while (!IsConnected()) { |
349 dart::Monitor::WaitResult res = ml.Wait(); | 349 dart::Monitor::WaitResult res = ml.Wait(); |
350 ASSERT(res == dart::Monitor::kNotified); | 350 ASSERT(res == dart::Monitor::kNotified); |
351 } | 351 } |
352 } | 352 } |
353 | 353 |
354 | 354 |
355 void DebuggerConnectionHandler::SendMsg(int debug_fd, dart::TextBuffer* msg) { | 355 void DebuggerConnectionHandler::SendMsg(intptr_t debug_fd, |
| 356 dart::TextBuffer* msg) { |
356 ASSERT(handler_lock_ != NULL); | 357 ASSERT(handler_lock_ != NULL); |
357 MonitorLocker ml(handler_lock_); | 358 MonitorLocker ml(handler_lock_); |
358 SendMsgHelper(debug_fd, msg); | 359 SendMsgHelper(debug_fd, msg); |
359 } | 360 } |
360 | 361 |
361 | 362 |
362 void DebuggerConnectionHandler::BroadcastMsg(dart::TextBuffer* msg) { | 363 void DebuggerConnectionHandler::BroadcastMsg(dart::TextBuffer* msg) { |
363 ASSERT(handler_lock_ != NULL); | 364 ASSERT(handler_lock_ != NULL); |
364 MonitorLocker ml(handler_lock_); | 365 MonitorLocker ml(handler_lock_); |
365 if (!IsListening()) { | 366 if (!IsListening()) { |
366 // If we are only running the vm service, don't try to broadcast | 367 // If we are only running the vm service, don't try to broadcast |
367 // to debugger clients. | 368 // to debugger clients. |
368 return; | 369 return; |
369 } | 370 } |
370 // TODO(asiva): Once we support connection to multiple debuggers | 371 // TODO(asiva): Once we support connection to multiple debuggers |
371 // we need to send the message to all of them. | 372 // we need to send the message to all of them. |
372 ASSERT(singleton_handler != NULL); | 373 ASSERT(singleton_handler != NULL); |
373 SendMsgHelper(singleton_handler->debug_fd(), msg); | 374 SendMsgHelper(singleton_handler->debug_fd(), msg); |
374 } | 375 } |
375 | 376 |
376 | 377 |
377 void DebuggerConnectionHandler::SendMsgHelper(int debug_fd, | 378 void DebuggerConnectionHandler::SendMsgHelper(intptr_t debug_fd, |
378 dart::TextBuffer* msg) { | 379 dart::TextBuffer* msg) { |
379 ASSERT(debug_fd >= 0); | 380 ASSERT(debug_fd >= 0); |
380 ASSERT(IsValidJSON(msg->buf())); | 381 ASSERT(IsValidJSON(msg->buf())); |
381 | 382 |
382 if (trace_debug_protocol) { | 383 if (trace_debug_protocol) { |
383 int print_len = ((msg->length() > kMaxPrintMessageLen) | 384 int print_len = ((msg->length() > kMaxPrintMessageLen) |
384 ? kMaxPrintMessageLen : msg->length()); | 385 ? kMaxPrintMessageLen : msg->length()); |
385 Log::Print("[>>>] Sending message to debug fd %d:\n%.*s%s\n", | 386 Log::Print("[>>>] Sending message to debug fd %" Pd ":\n%.*s%s\n", |
386 debug_fd, print_len, msg->buf(), | 387 debug_fd, print_len, msg->buf(), |
387 ((msg->length() > print_len) ? "..." : "")); | 388 ((msg->length() > print_len) ? "..." : "")); |
388 } | 389 } |
389 | 390 |
390 // Sending messages in short pieces can be used to stress test the | 391 // Sending messages in short pieces can be used to stress test the |
391 // debugger front-end's message handling code. | 392 // debugger front-end's message handling code. |
392 const bool send_in_pieces = false; | 393 const bool send_in_pieces = false; |
393 if (send_in_pieces) { | 394 if (send_in_pieces) { |
394 intptr_t remaining = msg->length(); | 395 intptr_t remaining = msg->length(); |
395 intptr_t sent = 0; | 396 intptr_t sent = 0; |
(...skipping 18 matching lines...) Expand all Loading... |
414 return; | 415 return; |
415 } | 416 } |
416 intptr_t bytes_written = | 417 intptr_t bytes_written = |
417 DebuggerConnectionImpl::Send(debug_fd, msg->buf(), msg->length()); | 418 DebuggerConnectionImpl::Send(debug_fd, msg->buf(), msg->length()); |
418 ASSERT(msg->length() == bytes_written); | 419 ASSERT(msg->length() == bytes_written); |
419 // TODO(hausner): Error checking. Probably just shut down the debugger | 420 // TODO(hausner): Error checking. Probably just shut down the debugger |
420 // session if we there is an error while writing. | 421 // session if we there is an error while writing. |
421 } | 422 } |
422 | 423 |
423 | 424 |
424 void DebuggerConnectionHandler::AcceptDbgConnection(int debug_fd) { | 425 void DebuggerConnectionHandler::AcceptDbgConnection(intptr_t debug_fd) { |
425 Socket::SetNoDelay(debug_fd, true); | 426 Socket::SetNoDelay(debug_fd, true); |
426 AddNewDebuggerConnection(debug_fd); | 427 AddNewDebuggerConnection(debug_fd); |
427 { | 428 { |
428 ASSERT(handler_lock_ != NULL); | 429 ASSERT(handler_lock_ != NULL); |
429 MonitorLocker ml(handler_lock_); | 430 MonitorLocker ml(handler_lock_); |
430 ml.NotifyAll(); | 431 ml.NotifyAll(); |
431 } | 432 } |
432 // TODO(asiva): Once we implement support for multiple connections | 433 // TODO(asiva): Once we implement support for multiple connections |
433 // we should have a different callback for wakeups on fds which | 434 // we should have a different callback for wakeups on fds which |
434 // are not the listener_fd_. | 435 // are not the listener_fd_. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 int msg_id = msg_parser.MessageId(); | 467 int msg_id = msg_parser.MessageId(); |
467 ASSERT(msg_id >= 0); | 468 ASSERT(msg_id >= 0); |
468 dart::TextBuffer msg(64); | 469 dart::TextBuffer msg(64); |
469 msg.Printf("{ \"id\": %d, \"result\": { \"isolateIds\": [", msg_id); | 470 msg.Printf("{ \"id\": %d, \"result\": { \"isolateIds\": [", msg_id); |
470 DbgMsgQueueList::ListIsolateIds(&msg); | 471 DbgMsgQueueList::ListIsolateIds(&msg); |
471 msg.Printf("]}}"); | 472 msg.Printf("]}}"); |
472 in_msg->SendReply(&msg); | 473 in_msg->SendReply(&msg); |
473 } | 474 } |
474 | 475 |
475 | 476 |
476 void DebuggerConnectionHandler::AddNewDebuggerConnection(int debug_fd) { | 477 void DebuggerConnectionHandler::AddNewDebuggerConnection(intptr_t debug_fd) { |
477 // TODO(asiva): Support multiple debugger connections, for now we just | 478 // TODO(asiva): Support multiple debugger connections, for now we just |
478 // create one handler, store it in a static variable and use it. | 479 // create one handler, store it in a static variable and use it. |
479 ASSERT(singleton_handler == NULL); | 480 ASSERT(singleton_handler == NULL); |
480 singleton_handler = new DebuggerConnectionHandler(debug_fd); | 481 singleton_handler = new DebuggerConnectionHandler(debug_fd); |
481 } | 482 } |
482 | 483 |
483 | 484 |
484 void DebuggerConnectionHandler::RemoveDebuggerConnection(int debug_fd) { | 485 void DebuggerConnectionHandler::RemoveDebuggerConnection(intptr_t debug_fd) { |
485 // TODO(asiva): Support multiple debugger connections, for now we just | 486 // TODO(asiva): Support multiple debugger connections, for now we just |
486 // set the static handler back to NULL. | 487 // set the static handler back to NULL. |
487 ASSERT(singleton_handler != NULL); | 488 ASSERT(singleton_handler != NULL); |
488 singleton_handler = NULL; | 489 singleton_handler = NULL; |
489 } | 490 } |
490 | 491 |
491 | 492 |
492 DebuggerConnectionHandler* | 493 DebuggerConnectionHandler* |
493 DebuggerConnectionHandler::GetDebuggerConnectionHandler(int debug_fd) { | 494 DebuggerConnectionHandler::GetDebuggerConnectionHandler(intptr_t debug_fd) { |
494 // TODO(asiva): Support multiple debugger connections, for now we just | 495 // TODO(asiva): Support multiple debugger connections, for now we just |
495 // return the one static handler that was created. | 496 // return the one static handler that was created. |
496 ASSERT(singleton_handler != NULL); | 497 ASSERT(singleton_handler != NULL); |
497 return singleton_handler; | 498 return singleton_handler; |
498 } | 499 } |
499 | 500 |
500 | 501 |
501 bool DebuggerConnectionHandler::IsConnected() { | 502 bool DebuggerConnectionHandler::IsConnected() { |
502 // TODO(asiva): Support multiple debugger connections. | 503 // TODO(asiva): Support multiple debugger connections. |
503 // Return true if a connection has been established. | 504 // Return true if a connection has been established. |
504 return singleton_handler != NULL; | 505 return singleton_handler != NULL; |
505 } | 506 } |
506 | 507 |
507 } // namespace bin | 508 } // namespace bin |
508 } // namespace dart | 509 } // namespace dart |
OLD | NEW |