Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: runtime/bin/dbg_connection.cc

Issue 10357003: Beginnings of a debugger wire protocol (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/dbg_connection.h ('k') | runtime/bin/dbg_connection_linux.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "bin/dbg_connection.h"
6 #include "bin/dartutils.h"
7 #include "bin/fdutils.h"
8 #include "bin/socket.h"
9 #include "bin/thread.h"
10 #include "bin/utils.h"
11
12 #include "platform/globals.h"
13 #include "platform/json.h"
14 #include "platform/thread.h"
15 #include "platform/utils.h"
16
17 #include "include/dart_api.h"
18
19
20 int DebuggerConnectionHandler::listener_fd_ = -1;
21 int DebuggerConnectionHandler::debugger_fd_ = -1;
22 MessageBuffer* DebuggerConnectionHandler::msgbuf_ = NULL;
23
24 bool DebuggerConnectionHandler::handler_started_ = false;
25
26
27 // TODO(hausner): Need better error handling.
28 #define ASSERT_NOT_ERROR(handle) \
29 ASSERT(!Dart_IsError(handle))
30
31
32 class MessageBuffer {
33 public:
34 explicit MessageBuffer(int fd);
35 ~MessageBuffer();
36 void ReadData();
37 bool IsValidMessage() const;
38 void PopMessage();
39 int MessageId() const;
40 char* buf() const { return buf_; }
41 bool Alive() const { return connection_is_alive_; }
42
43 private:
44 static const int kInitialBufferSize = 256;
45 char* buf_;
46 int buf_length_;
47 int fd_;
48 int data_length_;
49 bool connection_is_alive_;
50
51 DISALLOW_COPY_AND_ASSIGN(MessageBuffer);
52 };
53
54
55 MessageBuffer::MessageBuffer(int fd)
56 : buf_(NULL),
57 buf_length_(0),
58 fd_(fd),
59 data_length_(0),
60 connection_is_alive_(true) {
61 buf_ = reinterpret_cast<char*>(malloc(kInitialBufferSize));
62 if (buf_ == NULL) {
63 FATAL("Failed to allocate message buffer\n");
64 }
65 buf_length_ = kInitialBufferSize;
66 buf_[0] = '\0';
67 data_length_ = 0;
68 }
69
70
71 MessageBuffer::~MessageBuffer() {
72 free(buf_);
73 buf_ = NULL;
74 fd_ = -1;
75 }
76
77
78 bool MessageBuffer::IsValidMessage() const {
79 if (data_length_ == 0) {
80 return false;
81 }
82 dart::JSONReader msg_reader(buf_);
83 return msg_reader.EndOfObject() != NULL;
84 }
85
86
87 int MessageBuffer::MessageId() const {
88 dart::JSONReader r(buf_);
89 r.Seek("id");
90 if (r.Type() == dart::JSONReader::kInteger) {
91 return atoi(r.ValueChars());
92 } else {
93 return -1;
94 }
95 }
96
97
98 void MessageBuffer::ReadData() {
99 ASSERT(data_length_ >= 0);
100 ASSERT(data_length_ < buf_length_);
101 int max_read = buf_length_ - data_length_ - 1;
102 if (max_read == 0) {
103 // TODO(hausner):
104 // Buffer is full. What should we do if there is no valid message
105 // in the buffer? This might be possible if the client sends a message
106 // that's larger than the buffer, of if the client sends malformed
107 // messages that keep piling up.
108 ASSERT(IsValidMessage());
109 return;
110 }
111 // TODO(hausner): Handle error conditions returned by Read. We may
112 // want to close the debugger connection if we get any errors.
113 int bytes_read = Socket::Read(fd_, buf_ + data_length_, max_read);
114 if (bytes_read == 0) {
115 connection_is_alive_ = false;
116 return;
117 }
118 ASSERT(bytes_read > 0);
119 data_length_ += bytes_read;
120 ASSERT(data_length_ < buf_length_);
121 buf_[data_length_] = '\0';
122 }
123
124
125 void MessageBuffer::PopMessage() {
126 dart::JSONReader msg_reader(buf_);
127 const char* end = msg_reader.EndOfObject();
128 if (end != NULL) {
129 ASSERT(*end == '}');
130 end++;
131 data_length_ = 0;
132 while (*end != '\0') {
133 buf_[data_length_] = *end++;
134 data_length_++;
135 }
136 buf_[data_length_] = '\0';
137 ASSERT(data_length_ < buf_length_);
138 }
139 }
140
141
142 static bool IsValidJSON(const char* msg) {
143 dart::JSONReader r(msg);
144 return r.EndOfObject() != NULL;
145 }
146
147
148 void DebuggerConnectionHandler::HandleResumeCmd() {
149 int msg_id = msgbuf_->MessageId();
150 dart::TextBuffer msg(64);
151 msg.Printf("{ \"id\": %d }", msg_id);
152 FDUtils::WriteToBlocking(debugger_fd_, msg.buf(), msg.length());
153 // TODO(hausner): Error checking. Probably just shut down the debugger
154 // session if we there is an error while writing.
155 }
156
157
158 void DebuggerConnectionHandler::HandleMessages() {
159 for (;;) {
160 while (!msgbuf_->IsValidMessage() && msgbuf_->Alive()) {
161 msgbuf_->ReadData();
162 }
163 if (!msgbuf_->Alive()) {
164 return;
165 }
166 dart::JSONReader r(msgbuf_->buf());
167 bool found = r.Seek("command");
168 if (r.Error()) {
169 FATAL("Illegal JSON message received");
170 }
171 if (!found) {
172 printf("'command' not found in JSON message: '%s'\n", msgbuf_->buf());
173 msgbuf_->PopMessage();
174 } else if (r.IsStringLiteral("resume")) {
175 HandleResumeCmd();
176 msgbuf_->PopMessage();
177 return;
178 } else {
179 printf("unrecognized command received: '%s'\n", msgbuf_->buf());
180 msgbuf_->PopMessage();
181 }
182 }
183 }
184
185
186 void DebuggerConnectionHandler::SendBreakpointEvent(Dart_Breakpoint bpt,
187 Dart_StackTrace trace) {
188 dart::TextBuffer msg(128);
189 intptr_t trace_len = 0;
190 Dart_Handle res = Dart_StackTraceLength(trace, &trace_len);
191 ASSERT_NOT_ERROR(res);
192 msg.Printf("{ \"command\" : \"paused\", \"params\" : ");
193 msg.Printf("{ \"callFrames\" : [ ");
194 for (int i = 0; i < trace_len; i++) {
195 Dart_ActivationFrame frame;
196 res = Dart_GetActivationFrame(trace, i, &frame);
197 ASSERT_NOT_ERROR(res);
198 Dart_Handle func_name;
199 Dart_Handle script_url;
200 intptr_t line_number = 0;
201 res = Dart_ActivationFrameInfo(
202 frame, &func_name, &script_url, &line_number);
203 ASSERT_NOT_ERROR(res);
204 ASSERT(Dart_IsString(func_name));
205 const char* func_name_chars;
206 Dart_StringToCString(func_name, &func_name_chars);
207 msg.Printf("%s { \"functionName\" : \"%s\" , ",
208 i > 0 ? "," : "",
209 func_name_chars);
210 ASSERT(Dart_IsString(script_url));
211 const char* script_url_chars;
212 Dart_StringToCString(script_url, &script_url_chars);
213 msg.Printf("\"location\": { \"scriptId\": \"%s\", \"lineNumber\": %d }}",
214 script_url_chars, line_number);
215 }
216 msg.Printf("]}}");
217 Socket::Write(debugger_fd_, msg.buf(), msg.length());
218 ASSERT(IsValidJSON(msg.buf()));
219 }
220
221
222 void DebuggerConnectionHandler::BreakpointHandler(Dart_Breakpoint bpt,
223 Dart_StackTrace trace) {
224 // TODO(hausner): rather than busy-waiting, block on the pipe to the
225 // debugger thread and wait until a debugger connection has been
226 // established.
227 while (!IsConnected()) {
228 printf("Waiting for debugger connection\n");
229 sleep(1);
230 }
231 SendBreakpointEvent(bpt, trace);
232 HandleMessages();
233 if (!msgbuf_->Alive()) {
234 CloseDbgConnection();
235 }
236 }
237
238
239 void DebuggerConnectionHandler::AcceptDbgConnection(int debugger_fd) {
240 debugger_fd_ = debugger_fd;
241 ASSERT(msgbuf_ == NULL);
242 msgbuf_ = new MessageBuffer(debugger_fd_);
243 }
244
245 void DebuggerConnectionHandler::CloseDbgConnection() {
246 if (debugger_fd_ >= 0) {
247 // TODO(hausner): need a Socket::Close() function.
248 }
249 if (msgbuf_ != NULL) {
250 delete msgbuf_;
251 msgbuf_ = NULL;
252 }
253 // TODO(hausner): Need to tell the VM debugger object to remove all
254 // breakpoints.
255 }
256
257 void DebuggerConnectionHandler::StartHandler(const char* address,
258 int port_number) {
259 if (handler_started_) {
260 return;
261 }
262 ASSERT(listener_fd_ == -1);
263 listener_fd_ = ServerSocket::CreateBindListen(address, port_number, 1);
264
265 handler_started_ = true;
266 DebuggerConnectionImpl::StartHandler(port_number);
267 Dart_SetBreakpointHandler(BreakpointHandler);
268 }
269
270
271 DebuggerConnectionHandler::~DebuggerConnectionHandler() {
272 CloseDbgConnection();
273 }
OLDNEW
« no previous file with comments | « runtime/bin/dbg_connection.h ('k') | runtime/bin/dbg_connection_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698