1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
30086aeeaae12517475c22695a200be45495516549Ben Murdoch#include "debug.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "debug-agent.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
34086aeeaae12517475c22695a200be45495516549Ben Murdoch
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Public V8 debugger API message handler function. This function just delegates
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to the debugger agent through it's data parameter.
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
4144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DebuggerAgent* agent = Isolate::Current()->debugger_agent_instance();
4244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(agent != NULL);
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  agent->DebuggerMessage(message);
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Debugger agent main thread.
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::Run() {
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kOneSecondInMicros = 1000000;
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allow this socket to reuse port even if still in TIME_WAIT.
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  server_->SetReuseAddress(true);
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // First bind the socket to the requested port.
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool bound = false;
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!bound && !terminate_) {
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bound = server_->Bind(port_);
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    // If an error occurred wait a bit before retrying. The most common error
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // would be that the port is already in use so this avoids a busy loop and
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // make the agent take over the port when it becomes free.
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!bound) {
63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke      PrintF("Failed to open socket on port %d, "
64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke          "waiting %d ms before retrying\n", port_, kOneSecondInMicros / 1000);
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      terminate_now_->Wait(kOneSecondInMicros);
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accept connections on the bound port.
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!terminate_) {
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool ok = server_->Listen(1);
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    listening_->Signal();
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (ok) {
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Accept the new connection.
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Socket* client = server_->Accept();
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ok = client != NULL;
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (ok) {
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Create and start a new session.
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CreateSession(client);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::Shutdown() {
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the termination flag.
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  terminate_ = true;
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Signal termination and make the server exit either its listen call or its
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // binding loop. This makes sure that no new sessions can be established.
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  terminate_now_->Signal();
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  server_->Shutdown();
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Join();
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Close existing session if any.
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CloseSession();
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::WaitUntilListening() {
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  listening_->Wait();
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const char* kCreateSessionMessage =
10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    "Remote debugging session already active\r\n";
10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::CreateSession(Socket* client) {
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ScopedLock with(session_access_);
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If another session is already established terminate this one.
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (session_ != NULL) {
11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    client->Send(kCreateSessionMessage, StrLength(kCreateSessionMessage));
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    delete client;
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Create a new session and hook up the debug message handler.
1193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  session_ = new DebuggerAgentSession(this, client);
1203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler);
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  session_->Start();
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::CloseSession() {
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ScopedLock with(session_access_);
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Terminate the session.
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (session_ != NULL) {
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    session_->Shutdown();
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    session_->Join();
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    delete session_;
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    session_ = NULL;
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ScopedLock with(session_access_);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Forward the message handling to the session.
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (session_ != NULL) {
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::String::Value val(message.GetJSON());
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              val.length()));
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Don't do anything during termination.
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (terminate_) {
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Terminate the session.
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ScopedLock with(session_access_);
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(session == session_);
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (session == session_) {
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CloseSession();
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgentSession::Run() {
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send the hello message.
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool ok = DebuggerAgentUtil::SendConnectMessage(client_, *agent_->name_);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) return;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read data from the debugger front end.
172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    SmartArrayPointer<char> message =
173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        DebuggerAgentUtil::ReceiveMessage(client_);
174086aeeaae12517475c22695a200be45495516549Ben Murdoch
175086aeeaae12517475c22695a200be45495516549Ben Murdoch    const char* msg = *message;
176086aeeaae12517475c22695a200be45495516549Ben Murdoch    bool is_closing_session = (msg == NULL);
177086aeeaae12517475c22695a200be45495516549Ben Murdoch
178086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (msg == NULL) {
179086aeeaae12517475c22695a200be45495516549Ben Murdoch      // If we lost the connection, then simulate a disconnect msg:
180086aeeaae12517475c22695a200be45495516549Ben Murdoch      msg = "{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}";
181086aeeaae12517475c22695a200be45495516549Ben Murdoch
182086aeeaae12517475c22695a200be45495516549Ben Murdoch    } else {
183086aeeaae12517475c22695a200be45495516549Ben Murdoch      // Check if we're getting a disconnect request:
184086aeeaae12517475c22695a200be45495516549Ben Murdoch      const char* disconnectRequestStr =
185086aeeaae12517475c22695a200be45495516549Ben Murdoch          "\"type\":\"request\",\"command\":\"disconnect\"}";
186086aeeaae12517475c22695a200be45495516549Ben Murdoch      const char* result = strstr(msg, disconnectRequestStr);
187086aeeaae12517475c22695a200be45495516549Ben Murdoch      if (result != NULL) {
188086aeeaae12517475c22695a200be45495516549Ben Murdoch        is_closing_session = true;
189086aeeaae12517475c22695a200be45495516549Ben Murdoch      }
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Convert UTF-8 to UTF-16.
193086aeeaae12517475c22695a200be45495516549Ben Murdoch    unibrow::Utf8InputBuffer<> buf(msg, StrLength(msg));
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int len = 0;
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (buf.has_more()) {
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      buf.GetNext();
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      len++;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
19925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    ScopedVector<int16_t> temp(len + 1);
200086aeeaae12517475c22695a200be45495516549Ben Murdoch    buf.Reset(msg, StrLength(msg));
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < len; i++) {
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      temp[i] = buf.GetNext();
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Send the request received to the debugger.
20625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen    v8::Debug::SendCommand(reinterpret_cast<const uint16_t *>(temp.start()),
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           len,
2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           NULL,
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           reinterpret_cast<v8::Isolate*>(agent_->isolate()));
210086aeeaae12517475c22695a200be45495516549Ben Murdoch
211086aeeaae12517475c22695a200be45495516549Ben Murdoch    if (is_closing_session) {
212086aeeaae12517475c22695a200be45495516549Ben Murdoch      // Session is closed.
213086aeeaae12517475c22695a200be45495516549Ben Murdoch      agent_->OnSessionClosed(this);
214086aeeaae12517475c22695a200be45495516549Ben Murdoch      return;
215086aeeaae12517475c22695a200be45495516549Ben Murdoch    }
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgentSession::DebuggerMessage(Vector<uint16_t> message) {
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebuggerAgentUtil::SendMessage(client_, message);
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid DebuggerAgentSession::Shutdown() {
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shutdown the socket to end the blocking receive.
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  client_->Shutdown();
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
23144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst char* const DebuggerAgentUtil::kContentLength = "Content-Length";
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochSmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(const Socket* conn) {
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int received;
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Read header.
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int content_length = 0;
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int kHeaderBufferSize = 80;
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char header_buffer[kHeaderBufferSize];
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int header_buffer_position = 0;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char c = '\0';  // One character receive buffer.
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char prev_c = '\0';  // Previous character.
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read until CRLF.
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (!(c == '\n' && prev_c == '\r')) {
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      prev_c = c;
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      received = conn->Receive(&c, 1);
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (received <= 0) {
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        PrintF("Error %d\n", Socket::LastError());
252589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return SmartArrayPointer<char>();
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Add character to header buffer.
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (header_buffer_position < kHeaderBufferSize) {
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        header_buffer[header_buffer_position++] = c;
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check for end of header (empty header line).
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (header_buffer_position == 2) {  // Receive buffer contains CRLF.
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      break;
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Terminate header.
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(header_buffer_position > 1);  // At least CRLF is received.
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(header_buffer_position <= kHeaderBufferSize);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    header_buffer[header_buffer_position - 2] = '\0';
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Split header.
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* key = header_buffer;
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char* value = NULL;
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; header_buffer[i] != '\0'; i++) {
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (header_buffer[i] == ':') {
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        header_buffer[i] = '\0';
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        value = header_buffer + i + 1;
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        while (*value == ' ') {
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          value++;
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Check that key is Content-Length.
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (strcmp(key, kContentLength) == 0) {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Get the content length value if present and within a sensible range.
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (value == NULL || strlen(value) > 7) {
289589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return SmartArrayPointer<char>();
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int i = 0; value[i] != '\0'; i++) {
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Bail out if illegal data.
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (value[i] < '0' || value[i] > '9') {
294589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch          return SmartArrayPointer<char>();
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        content_length = 10 * content_length + (value[i] - '0');
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // For now just print all other headers than Content-Length.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("%s: %s\n", key, value != NULL ? value : "(no value)");
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return now if no body.
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (content_length == 0) {
306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return SmartArrayPointer<char>();
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Read body.
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char* buffer = NewArray<char>(content_length + 1);
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  received = ReceiveAll(conn, buffer, content_length);
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (received < content_length) {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("Error %d\n", Socket::LastError());
314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    return SmartArrayPointer<char>();
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  buffer[content_length] = '\0';
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  return SmartArrayPointer<char>(buffer);
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool DebuggerAgentUtil::SendConnectMessage(const Socket* conn,
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                           const char* embedding_host) {
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 80;
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buffer[kBufferSize];  // Sending buffer.
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool ok;
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int len;
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send the header.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "Type: connect\r\n");
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = conn->Send(buffer, len);
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) return false;
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "V8-Version: %s\r\n", v8::V8::GetVersion());
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = conn->Send(buffer, len);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) return false;
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "Protocol-Version: 1\r\n");
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = conn->Send(buffer, len);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) return false;
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (embedding_host != NULL) {
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       "Embedding-Host: %s\r\n", embedding_host);
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ok = conn->Send(buffer, len);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!ok) return false;
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "%s: 0\r\n", kContentLength);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = conn->Send(buffer, len);
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) return false;
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Terminate header with empty line.
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ok = conn->Send(buffer, len);
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!ok) return false;
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // No body for connect message.
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool DebuggerAgentUtil::SendMessage(const Socket* conn,
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const Vector<uint16_t> message) {
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 80;
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buffer[kBufferSize];  // Sending buffer both for header and body.
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calculate the message size in UTF-8 encoding.
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int utf8_len = 0;
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int previous = unibrow::Utf16::kNoPreviousCharacter;
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < message.length(); i++) {
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint16_t character = message[i];
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    utf8_len += unibrow::Utf8::Length(character, previous);
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    previous = character;
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send the header.
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int len;
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "%s: %d\r\n", kContentLength, utf8_len);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  conn->Send(buffer, len);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Terminate header with empty line.
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  conn->Send(buffer, len);
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send message body as UTF-8.
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int buffer_position = 0;  // Current buffer position.
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  previous = unibrow::Utf16::kNoPreviousCharacter;
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < message.length(); i++) {
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Write next UTF-8 encoded character to buffer.
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint16_t character = message[i];
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    buffer_position +=
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        unibrow::Utf8::Encode(buffer + buffer_position, character, previous);
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(buffer_position < kBufferSize);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Send buffer if full or last character is encoded.
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (kBufferSize - buffer_position <
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit ||
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        i == message.length() - 1) {
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (unibrow::Utf16::IsLeadSurrogate(character)) {
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const int kEncodedSurrogateLength =
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            unibrow::Utf16::kUtf8BytesToCodeASurrogate;
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(buffer_position >= kEncodedSurrogateLength);
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        conn->Send(buffer, buffer_position - kEncodedSurrogateLength);
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < kEncodedSurrogateLength; i++) {
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          buffer[i] = buffer[buffer_position + i];
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        buffer_position = kEncodedSurrogateLength;
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        conn->Send(buffer, buffer_position);
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        buffer_position = 0;
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    previous = character;
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool DebuggerAgentUtil::SendMessage(const Socket* conn,
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                    const v8::Handle<v8::String> request) {
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kBufferSize = 80;
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  char buffer[kBufferSize];  // Sending buffer both for header and body.
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convert the request to UTF-8 encoding.
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::String::Utf8Value utf8_request(request);
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send the header.
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int len;
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     "Content-Length: %d\r\n", utf8_request.length());
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  conn->Send(buffer, len);
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Terminate header with empty line.
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  conn->Send(buffer, len);
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Send message body as UTF-8.
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  conn->Send(*utf8_request, utf8_request.length());
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Receive the full buffer before returning unless an error occours.
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint DebuggerAgentUtil::ReceiveAll(const Socket* conn, char* data, int len) {
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int total_received = 0;
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (total_received < len) {
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int received = conn->Receive(data + total_received, len - total_received);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (received <= 0) {
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return total_received;
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    total_received += received;
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return total_received;
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // ENABLE_DEBUGGER_SUPPORT
468