| 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/socket.h" | 8 #include "bin/socket.h" |
| 9 #include "bin/thread.h" | 9 #include "bin/thread.h" |
| 10 #include "bin/utils.h" | 10 #include "bin/utils.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 } | 160 } |
| 161 | 161 |
| 162 | 162 |
| 163 void DebuggerConnectionHandler::HandleUnknownMsg() { | 163 void DebuggerConnectionHandler::HandleUnknownMsg() { |
| 164 int msg_id = msgbuf_->MessageId(); | 164 int msg_id = msgbuf_->MessageId(); |
| 165 ASSERT(msg_id >= 0); | 165 ASSERT(msg_id >= 0); |
| 166 SendError(debug_fd_, msg_id, "unknown debugger command"); | 166 SendError(debug_fd_, msg_id, "unknown debugger command"); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| 170 typedef void (*CommandHandler)(DebuggerConnectionHandler* handler); | 170 typedef void (*CommandHandler)(DbgMessage* msg); |
| 171 | 171 |
| 172 struct JSONDebuggerCommand { | 172 struct JSONDebuggerCommand { |
| 173 const char* cmd_string; | 173 const char* cmd_string; |
| 174 CommandHandler handler_function; | 174 CommandHandler handler_function; |
| 175 }; | 175 }; |
| 176 | 176 |
| 177 | 177 |
| 178 void DebuggerConnectionHandler::HandleMessages() { | 178 void DebuggerConnectionHandler::HandleMessages() { |
| 179 static JSONDebuggerCommand generic_debugger_commands[] = { | 179 static JSONDebuggerCommand generic_debugger_commands[] = { |
| 180 { "interrupt", HandleInterruptCmd }, | 180 { "interrupt", HandleInterruptCmd }, |
| 181 { "isolates", HandleIsolatesListCmd }, | 181 { "isolates", HandleIsolatesListCmd }, |
| 182 { "quit", HandleQuitCmd }, | |
| 183 { NULL, NULL } | 182 { NULL, NULL } |
| 184 }; | 183 }; |
| 185 | 184 |
| 186 for (;;) { | 185 for (;;) { |
| 187 // Read a message. | 186 // Read a message. |
| 188 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) { | 187 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) { |
| 189 msgbuf_->ReadData(); | 188 msgbuf_->ReadData(); |
| 190 } | 189 } |
| 191 if (!msgbuf_->Alive()) { | 190 if (!msgbuf_->Alive()) { |
| 192 return; | 191 return; |
| 193 } | 192 } |
| 194 | 193 |
| 195 // Parse out the command portion from the message. | 194 // Parse out the command portion from the message. |
| 196 dart::JSONReader r(msgbuf_->buf()); | 195 dart::JSONReader r(msgbuf_->buf()); |
| 197 bool found = r.Seek("command"); | 196 bool found = r.Seek("command"); |
| 198 if (r.Error()) { | 197 if (r.Error()) { |
| 199 FATAL("Illegal JSON message received"); | 198 FATAL("Illegal JSON message received"); |
| 200 } | 199 } |
| 201 if (!found) { | 200 if (!found) { |
| 202 printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf()); | 201 printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf()); |
| 203 msgbuf_->PopMessage(); | 202 msgbuf_->PopMessage(); |
| 204 } | 203 } |
| 205 | 204 |
| 206 // Check if this is a generic command (not isolate specific). | 205 // Check if this is a generic command (not isolate specific). |
| 207 int i = 0; | 206 int i = 0; |
| 208 bool is_handled = false; | 207 bool is_handled = false; |
| 209 while (generic_debugger_commands[i].cmd_string != NULL) { | 208 while (generic_debugger_commands[i].cmd_string != NULL) { |
| 210 if (r.IsStringLiteral(generic_debugger_commands[i].cmd_string)) { | 209 if (r.IsStringLiteral(generic_debugger_commands[i].cmd_string)) { |
| 211 (*generic_debugger_commands[i].handler_function)(this); | 210 DbgMessage* msg = new DbgMessage(i, |
| 211 msgbuf_->buf(), |
| 212 r.EndOfObject(), |
| 213 debug_fd_); |
| 214 (*generic_debugger_commands[i].handler_function)(msg); |
| 212 is_handled = true; | 215 is_handled = true; |
| 213 msgbuf_->PopMessage(); | 216 msgbuf_->PopMessage(); |
| 217 delete msg; |
| 214 break; | 218 break; |
| 215 } | 219 } |
| 216 i++; | 220 i++; |
| 217 } | 221 } |
| 218 if (!is_handled) { | 222 if (!is_handled) { |
| 219 // Check if this is an isolate specific command. | 223 // Check if this is an isolate specific command. |
| 220 int32_t cmd_idx = DbgMessageQueue::LookupIsolateCommand(r.ValueChars(), | 224 int32_t cmd_idx = DbgMsgQueueList::LookupIsolateCommand(r.ValueChars(), |
| 221 r.ValueLen()); | 225 r.ValueLen()); |
| 222 if (cmd_idx != DbgMessageQueue::kInvalidCommand) { | 226 if (cmd_idx != DbgMsgQueueList::kInvalidCommand) { |
| 223 // Get debug message queue corresponding to isolate. | 227 // Get debug message queue corresponding to isolate. |
| 224 // TODO(asiva): Need to read the isolate id, map it to the appropriate | 228 // TODO(asiva): Once we have support for including the isolate id |
| 225 // isolate and pass it down to GetIsolateMessageQueue to get the | 229 // in the debug wire protocol we need to read the isolate id and |
| 226 // appropriate debug message queue. | 230 // pass it down to GetIsolateMsgQueue to get the appropriate debug |
| 227 DbgMessageQueue* queue = DbgMessageQueue::GetIsolateMessageQueue(NULL); | 231 // message queue. |
| 232 DbgMsgQueue* queue = |
| 233 DbgMsgQueueList::GetIsolateMsgQueue(ILLEGAL_ISOLATE_ID); |
| 228 ASSERT(queue != NULL); | 234 ASSERT(queue != NULL); |
| 229 queue->AddMessage(cmd_idx, msgbuf_->buf(), r.EndOfObject(), debug_fd_); | 235 queue->AddMessage(cmd_idx, msgbuf_->buf(), r.EndOfObject(), debug_fd_); |
| 230 msgbuf_->PopMessage(); | 236 msgbuf_->PopMessage(); |
| 231 continue; | 237 continue; |
| 232 } | 238 } |
| 233 | 239 |
| 234 // This is an unrecognized command, report error and move on to next. | 240 // This is an unrecognized command, report error and move on to next. |
| 235 printf("unrecognized command received: '%s'\n", msgbuf_->buf()); | 241 printf("unrecognized command received: '%s'\n", msgbuf_->buf()); |
| 236 HandleUnknownMsg(); | 242 HandleUnknownMsg(); |
| 237 msgbuf_->PopMessage(); | 243 msgbuf_->PopMessage(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 263 | 269 |
| 264 | 270 |
| 265 void DebuggerConnectionHandler::StartHandler(const char* address, | 271 void DebuggerConnectionHandler::StartHandler(const char* address, |
| 266 int port_number) { | 272 int port_number) { |
| 267 MonitorLocker ml(&handler_lock_); | 273 MonitorLocker ml(&handler_lock_); |
| 268 if (listener_fd_ != -1) { | 274 if (listener_fd_ != -1) { |
| 269 return; // The debugger connection handler was already started. | 275 return; // The debugger connection handler was already started. |
| 270 } | 276 } |
| 271 | 277 |
| 272 // First setup breakpoint, exception and delayed breakpoint handlers. | 278 // First setup breakpoint, exception and delayed breakpoint handlers. |
| 273 DbgMessageQueue::Initialize(); | 279 DbgMsgQueueList::Initialize(); |
| 274 | 280 |
| 275 // Now setup a listener socket and start a thread which will | 281 // Now setup a listener socket and start a thread which will |
| 276 // listen, accept connections from debuggers, read and handle/dispatch | 282 // listen, accept connections from debuggers, read and handle/dispatch |
| 277 // debugger commands received on these connections. | 283 // debugger commands received on these connections. |
| 278 ASSERT(listener_fd_ == -1); | 284 ASSERT(listener_fd_ == -1); |
| 279 listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1); | 285 listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1); |
| 280 DebuggerConnectionImpl::StartHandler(port_number); | 286 DebuggerConnectionImpl::StartHandler(port_number); |
| 281 } | 287 } |
| 282 | 288 |
| 283 | 289 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // corresponding to that fd and invoke HandleMessages on it. | 361 // corresponding to that fd and invoke HandleMessages on it. |
| 356 // For now we run that code here. | 362 // For now we run that code here. |
| 357 DebuggerConnectionHandler* handler = GetDebuggerConnectionHandler(debug_fd); | 363 DebuggerConnectionHandler* handler = GetDebuggerConnectionHandler(debug_fd); |
| 358 if (handler != NULL) { | 364 if (handler != NULL) { |
| 359 handler->HandleMessages(); | 365 handler->HandleMessages(); |
| 360 delete handler; | 366 delete handler; |
| 361 } | 367 } |
| 362 } | 368 } |
| 363 | 369 |
| 364 | 370 |
| 365 void DebuggerConnectionHandler::HandleInterruptCmd( | 371 void DebuggerConnectionHandler::HandleInterruptCmd(DbgMessage* in_msg) { |
| 366 DebuggerConnectionHandler* handler) { | 372 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len()); |
| 367 int msg_id = handler->MessageId(); | 373 int msg_id = msg_parser.MessageId(); |
| 368 ASSERT(msg_id >= 0); | 374 Dart_IsolateId isolate_id = |
| 369 SendError(handler->debug_fd(), msg_id, "interrupt command unimplemented"); | 375 static_cast<Dart_IsolateId>(msg_parser.GetIntParam("isolateId")); |
| 376 if (isolate_id == ILLEGAL_ISOLATE_ID || Dart_GetIsolate(isolate_id) == NULL) { |
| 377 in_msg->SendErrorReply(msg_id, "Invalid isolate specified"); |
| 378 return; |
| 379 } |
| 380 DbgMsgQueue* queue = DbgMsgQueueList::GetIsolateMsgQueue(isolate_id); |
| 381 ASSERT(queue != NULL); |
| 382 queue->InterruptIsolate(); |
| 383 dart::TextBuffer msg(64); |
| 384 msg.Printf("{ \"id\": %d }", msg_id); |
| 385 in_msg->SendReply(&msg); |
| 370 } | 386 } |
| 371 | 387 |
| 372 | 388 |
| 373 void DebuggerConnectionHandler::HandleIsolatesListCmd( | 389 void DebuggerConnectionHandler::HandleIsolatesListCmd(DbgMessage* in_msg) { |
| 374 DebuggerConnectionHandler* handler) { | 390 MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len()); |
| 375 int msg_id = handler->MessageId(); | 391 int msg_id = msg_parser.MessageId(); |
| 376 ASSERT(msg_id >= 0); | 392 ASSERT(msg_id >= 0); |
| 377 SendError(handler->debug_fd(), msg_id, "isolate list command unimplemented"); | 393 in_msg->SendErrorReply(msg_id, "isolate list command unimplemented"); |
| 378 } | |
| 379 | |
| 380 | |
| 381 void DebuggerConnectionHandler::HandleQuitCmd( | |
| 382 DebuggerConnectionHandler* handler) { | |
| 383 int msg_id = handler->MessageId(); | |
| 384 ASSERT(msg_id >= 0); | |
| 385 SendError(handler->debug_fd(), msg_id, "quit command unimplemented"); | |
| 386 } | 394 } |
| 387 | 395 |
| 388 | 396 |
| 389 void DebuggerConnectionHandler::AddNewDebuggerConnection(int debug_fd) { | 397 void DebuggerConnectionHandler::AddNewDebuggerConnection(int debug_fd) { |
| 390 // TODO(asiva): Support multiple debugger connections, for now we just | 398 // TODO(asiva): Support multiple debugger connections, for now we just |
| 391 // create one handler, store it in a static variable and use it. | 399 // create one handler, store it in a static variable and use it. |
| 392 ASSERT(singleton_handler == NULL); | 400 ASSERT(singleton_handler == NULL); |
| 393 singleton_handler = new DebuggerConnectionHandler(debug_fd); | 401 singleton_handler = new DebuggerConnectionHandler(debug_fd); |
| 394 } | 402 } |
| 395 | 403 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 409 ASSERT(singleton_handler != NULL); | 417 ASSERT(singleton_handler != NULL); |
| 410 return singleton_handler; | 418 return singleton_handler; |
| 411 } | 419 } |
| 412 | 420 |
| 413 | 421 |
| 414 bool DebuggerConnectionHandler::IsConnected() { | 422 bool DebuggerConnectionHandler::IsConnected() { |
| 415 // TODO(asiva): Support multiple debugger connections. | 423 // TODO(asiva): Support multiple debugger connections. |
| 416 // Return true if a connection has been established. | 424 // Return true if a connection has been established. |
| 417 return singleton_handler != NULL; | 425 return singleton_handler != NULL; |
| 418 } | 426 } |
| OLD | NEW |