1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_remote_listen_socket.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <stdlib.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// winsock2.h must be included first in order to ensure it is included before
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// windows.h.
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <winsock2.h>
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_POSIX)
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <errno.h>
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <sys/socket.h>
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_pump_libevent.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/compiler_specific.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/eintr_wrapper.h"
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
263f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_remote.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/debugger/devtools_remote_message.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CONSUME_BUFFER_CHAR \
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pBuf++;\
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  len--
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used same name as in Windows to avoid #ifdef where refrenced
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define SOCKET int
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int INVALID_SOCKET = -1;
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int SOCKET_ERROR = -1;
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int kReadBufSize = 200;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDevToolsRemoteListenSocket::DevToolsRemoteListenSocket(
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SOCKET s,
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DevToolsRemoteListener* message_listener)
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        : ALLOW_THIS_IN_INITIALIZER_LIST(ListenSocket(s, this)),
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          state_(HANDSHAKE),
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          remaining_payload_length_(0),
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          message_listener_(message_listener),
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          cr_received_(false) {}
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::StartNextField() {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (state_) {
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case INVALID:
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      state_ = HANDSHAKE;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case HANDSHAKE:
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      state_ = HEADERS;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case HEADERS:
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (protocol_field_.empty()) {  // empty line - end of headers
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        const std::string& payload_length_string = GetHeader(
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            DevToolsRemoteMessageHeaders::kContentLength, "0");
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        base::StringToInt(payload_length_string, &remaining_payload_length_);
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        state_ = PAYLOAD;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (remaining_payload_length_ == 0) {  // no payload
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          DispatchField();
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          return;
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case PAYLOAD:
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      header_map_.clear();
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      payload_.clear();
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      state_ = HEADERS;
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  protocol_field_.clear();
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDevToolsRemoteListenSocket::~DevToolsRemoteListenSocket() {}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDevToolsRemoteListenSocket*
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DevToolsRemoteListenSocket::Listen(const std::string& ip,
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       int port,
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       DevToolsRemoteListener* listener) {
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SOCKET s = ListenSocket::Listen(ip, port);
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (s == INVALID_SOCKET) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(apavlov): error handling
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DevToolsRemoteListenSocket* sock =
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DevToolsRemoteListenSocket(s, listener);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sock->Listen();
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sock;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::DidAccept(ListenSocket *server,
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           ListenSocket *connection) {
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connection->AddRef();
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  message_listener_->OnAcceptConnection(connection);
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Dispatches data from socket to socket_delegate_, extracting messages
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// delimited by newlines.
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::DidRead(ListenSocket* connection,
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         const char* pBuf,
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         int len) {
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (len > 0) {
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (state_ != PAYLOAD) {
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (cr_received_ && *pBuf == '\n') {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        cr_received_ = false;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CONSUME_BUFFER_CHAR;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        while (*pBuf != '\r' && len > 0) {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          protocol_field_.push_back(*pBuf);
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          CONSUME_BUFFER_CHAR;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (*pBuf == '\r') {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          cr_received_ = true;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          CONSUME_BUFFER_CHAR;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        continue;
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      switch (state_) {
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case HANDSHAKE:
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case HEADERS:
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          DispatchField();
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        default:
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NOTREACHED();
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {  // PAYLOAD
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      while (remaining_payload_length_ > 0 && len > 0) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        protocol_field_.push_back(*pBuf);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        CONSUME_BUFFER_CHAR;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        remaining_payload_length_--;
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (remaining_payload_length_ == 0) {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DispatchField();
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::DidClose(ListenSocket *connection) {
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  message_listener_->OnConnectionLost();
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  connection->Release();
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::DispatchField() {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const std::string kHandshakeString = "ChromeDevToolsHandshake";
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (state_) {
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case HANDSHAKE:
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (protocol_field_.compare(kHandshakeString)) {
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        state_ = INVALID;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        Send(kHandshakeString, true);
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case HEADERS: {
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (!protocol_field_.empty()) {  // not end-of-headers
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::string::size_type colon_pos = protocol_field_.find_first_of(":");
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (colon_pos == std::string::npos) {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // TODO(apavlov): handle the error (malformed header)
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          const std::string header_name = protocol_field_.substr(0, colon_pos);
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string header_val = protocol_field_.substr(colon_pos + 1);
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          header_map_[header_name] = header_val;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case PAYLOAD:
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      payload_ = protocol_field_;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      HandleMessage();
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NOTREACHED();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  StartNextField();
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst std::string& DevToolsRemoteListenSocket::GetHeader(
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& header_name,
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& default_value) const {
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DevToolsRemoteMessage::HeaderMap::const_iterator it =
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      header_map_.find(header_name);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it == header_map_.end()) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return default_value;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return it->second;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Handle header_map_ and payload_
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::HandleMessage() {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (message_listener_ != NULL) {
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DevToolsRemoteMessage message(header_map_, payload_);
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    message_listener_->HandleMessage(message);
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid DevToolsRemoteListenSocket::Listen() {
21021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ListenSocket::Listen();
21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::Accept() {
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SOCKET conn = ListenSocket::Accept(socket_);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (conn != INVALID_SOCKET) {
216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    scoped_refptr<DevToolsRemoteListenSocket> sock(
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        new DevToolsRemoteListenSocket(conn,
218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                       message_listener_));
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // it's up to the delegate to AddRef if it wants to keep it around
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX)
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sock->WatchSocket(WAITING_READ);
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    socket_delegate_->DidAccept(this, sock);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(apavlov): some error handling required here
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::SendInternal(const char* bytes, int len) {
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* send_buf = const_cast<char *>(bytes);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int len_left = len;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (true) {
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int sent = HANDLE_EINTR(send(socket_, send_buf, len_left, 0));
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (sent == len_left) {  // A shortcut to avoid extraneous checks.
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (sent == kSocketError) {
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN)
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (WSAGetLastError() != WSAEWOULDBLOCK) {
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(ERROR) << "send failed: WSAGetLastError()==" << WSAGetLastError();
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_POSIX)
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (errno != EWOULDBLOCK && errno != EAGAIN) {
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        LOG(ERROR) << "send failed: errno==" << errno;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Otherwise we would block, and now we have to wait for a retry.
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Fall through to PlatformThread::YieldCurrentThread()
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // sent != len_left according to the shortcut above.
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Shift the buffer start and send the remainder after a short while.
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      send_buf += sent;
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      len_left -= sent;
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::PlatformThread::YieldCurrentThread();
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DevToolsRemoteListenSocket::Close() {
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListenSocket::Close();
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
262