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