tethering_handler.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/devtools/tethering_handler.h" 6 7#include "base/bind.h" 8#include "base/callback.h" 9#include "base/stl_util.h" 10#include "base/values.h" 11#include "content/browser/devtools/devtools_http_handler_impl.h" 12#include "content/public/browser/devtools_client_host.h" 13#include "content/public/browser/devtools_http_handler_delegate.h" 14#include "net/base/io_buffer.h" 15#include "net/base/ip_endpoint.h" 16#include "net/base/net_errors.h" 17#include "net/base/net_log.h" 18#include "net/socket/stream_listen_socket.h" 19#include "net/socket/stream_socket.h" 20#include "net/socket/tcp_server_socket.h" 21 22namespace content { 23 24namespace { 25 26const char kTetheringBind[] = "Tethering.bind"; 27const char kTetheringUnbind[] = "Tethering.unbind"; 28 29const char kTetheringAccepted[] = "Tethering.accepted"; 30 31const char kPortParam[] = "port"; 32const char kConnectionIdParam[] = "connectionId"; 33 34const char kLocalhost[] = "127.0.0.1"; 35 36const int kListenBacklog = 5; 37const int kBufferSize = 16 * 1024; 38 39const int kMinTetheringPort = 5000; 40const int kMaxTetheringPort = 10000; 41 42class SocketPump : public net::StreamListenSocket::Delegate { 43 public: 44 SocketPump(DevToolsHttpHandlerDelegate* delegate, 45 net::StreamSocket* client_socket) 46 : client_socket_(client_socket), 47 delegate_(delegate), 48 wire_buffer_size_(0), 49 pending_destruction_(false) { 50 } 51 52 std::string Init() { 53 std::string channel_name; 54 server_socket_ = delegate_->CreateSocketForTethering(this, &channel_name); 55 if (!server_socket_ || channel_name.empty()) 56 SelfDestruct(); 57 return channel_name; 58 } 59 60 virtual ~SocketPump() { } 61 62 private: 63 virtual void DidAccept(net::StreamListenSocket* server, 64 net::StreamListenSocket* socket) OVERRIDE { 65 if (accepted_socket_) 66 return; 67 68 buffer_ = new net::IOBuffer(kBufferSize); 69 wire_buffer_ = new net::GrowableIOBuffer(); 70 wire_buffer_->SetCapacity(kBufferSize); 71 72 accepted_socket_ = socket; 73 int result = client_socket_->Read(buffer_, kBufferSize, 74 base::Bind(&SocketPump::OnClientRead, 75 base::Unretained(this))); 76 if (result != net::ERR_IO_PENDING) 77 OnClientRead(result); 78 } 79 80 virtual void DidRead(net::StreamListenSocket* socket, 81 const char* data, 82 int len) OVERRIDE { 83 int old_size = wire_buffer_size_; 84 wire_buffer_size_ += len; 85 while (wire_buffer_->capacity() < wire_buffer_size_) 86 wire_buffer_->SetCapacity(wire_buffer_->capacity() * 2); 87 memcpy(wire_buffer_->StartOfBuffer() + old_size, data, len); 88 if (old_size != wire_buffer_->offset()) 89 return; 90 OnClientWrite(0); 91 } 92 93 virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE { 94 SelfDestruct(); 95 } 96 97 void OnClientRead(int result) { 98 if (result <= 0) { 99 SelfDestruct(); 100 return; 101 } 102 103 accepted_socket_->Send(buffer_->data(), result); 104 result = client_socket_->Read(buffer_, kBufferSize, 105 base::Bind(&SocketPump::OnClientRead, 106 base::Unretained(this))); 107 if (result != net::ERR_IO_PENDING) 108 OnClientRead(result); 109 } 110 111 void OnClientWrite(int result) { 112 if (result < 0) 113 SelfDestruct(); 114 115 wire_buffer_->set_offset(wire_buffer_->offset() + result); 116 117 int remaining = wire_buffer_size_ - wire_buffer_->offset(); 118 if (remaining == 0) { 119 if (pending_destruction_) 120 SelfDestruct(); 121 return; 122 } 123 124 125 if (remaining > kBufferSize) 126 remaining = kBufferSize; 127 128 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(remaining); 129 memcpy(buffer->data(), wire_buffer_->data(), remaining); 130 result = client_socket_->Write( 131 buffer, remaining, base::Bind(&SocketPump::OnClientWrite, 132 base::Unretained(this))); 133 134 // Shrink buffer 135 int offset = wire_buffer_->offset(); 136 if (offset > kBufferSize) { 137 memcpy(wire_buffer_->StartOfBuffer(), wire_buffer_->data(), 138 wire_buffer_size_ - offset); 139 wire_buffer_size_ -= offset; 140 wire_buffer_->set_offset(0); 141 } 142 143 if (result != net::ERR_IO_PENDING) 144 OnClientWrite(result); 145 return; 146 } 147 148 void SelfDestruct() { 149 if (wire_buffer_->offset() != wire_buffer_size_) { 150 pending_destruction_ = true; 151 return; 152 } 153 delete this; 154 } 155 156 private: 157 scoped_ptr<net::StreamSocket> client_socket_; 158 scoped_refptr<net::StreamListenSocket> server_socket_; 159 scoped_refptr<net::StreamListenSocket> accepted_socket_; 160 scoped_refptr<net::IOBuffer> buffer_; 161 scoped_refptr<net::GrowableIOBuffer> wire_buffer_; 162 DevToolsHttpHandlerDelegate* delegate_; 163 int wire_buffer_size_; 164 bool pending_destruction_; 165}; 166 167} // namespace 168 169const char TetheringHandler::kDomain[] = "Tethering"; 170 171class TetheringHandler::BoundSocket { 172 public: 173 BoundSocket(TetheringHandler* handler, 174 DevToolsHttpHandlerDelegate* delegate) 175 : handler_(handler), 176 delegate_(delegate), 177 socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())), 178 port_(0) { 179 } 180 181 virtual ~BoundSocket() { 182 } 183 184 bool Listen(int port) { 185 port_ = port; 186 net::IPAddressNumber ip_number; 187 if (!net::ParseIPLiteralToNumber(kLocalhost, &ip_number)) 188 return false; 189 190 net::IPEndPoint end_point(ip_number, port); 191 socket_->AllowAddressReuse(); 192 int result = socket_->Listen(end_point, kListenBacklog); 193 if (result < 0) 194 return false; 195 196 net::IPEndPoint local_address; 197 result = socket_->GetLocalAddress(&local_address); 198 if (result < 0) 199 return false; 200 201 DoAccept(); 202 return true; 203 } 204 205 private: 206 typedef std::map<net::IPEndPoint, net::StreamSocket*> AcceptedSocketsMap; 207 208 void DoAccept() { 209 while (true) { 210 int result = socket_->Accept( 211 &accept_socket_, 212 base::Bind(&BoundSocket::OnAccepted, base::Unretained(this))); 213 if (result == net::ERR_IO_PENDING) 214 break; 215 else 216 HandleAcceptResult(result); 217 } 218 } 219 220 void OnAccepted(int result) { 221 HandleAcceptResult(result); 222 if (result == net::OK) 223 DoAccept(); 224 } 225 226 void HandleAcceptResult(int result) { 227 if (result != net::OK) 228 return; 229 230 SocketPump* pump = new SocketPump(delegate_, accept_socket_.release()); 231 std::string name = pump->Init(); 232 if (!name.empty()) 233 handler_->Accepted(port_, name); 234 } 235 236 TetheringHandler* handler_; 237 DevToolsHttpHandlerDelegate* delegate_; 238 scoped_ptr<net::ServerSocket> socket_; 239 scoped_ptr<net::StreamSocket> accept_socket_; 240 int port_; 241}; 242 243TetheringHandler::TetheringHandler(DevToolsHttpHandlerDelegate* delegate) 244 : delegate_(delegate) { 245 RegisterCommandHandler(kTetheringBind, 246 base::Bind(&TetheringHandler::OnBind, 247 base::Unretained(this))); 248 RegisterCommandHandler(kTetheringUnbind, 249 base::Bind(&TetheringHandler::OnUnbind, 250 base::Unretained(this))); 251} 252 253TetheringHandler::~TetheringHandler() { 254 STLDeleteContainerPairSecondPointers(bound_sockets_.begin(), 255 bound_sockets_.end()); 256} 257 258void TetheringHandler::Accepted(int port, const std::string& name) { 259 base::DictionaryValue* params = new base::DictionaryValue(); 260 params->SetInteger(kPortParam, port); 261 params->SetString(kConnectionIdParam, name); 262 SendNotification(kTetheringAccepted, params); 263} 264 265static int GetPort(DevToolsProtocol::Command* command) { 266 base::DictionaryValue* params = command->params(); 267 int port = 0; 268 if (!params || !params->GetInteger(kPortParam, &port) || 269 port < kMinTetheringPort || port > kMaxTetheringPort) 270 return 0; 271 return port; 272} 273 274scoped_ptr<DevToolsProtocol::Response> 275TetheringHandler::OnBind(DevToolsProtocol::Command* command) { 276 int port = GetPort(command); 277 if (port == 0) 278 return command->InvalidParamResponse(kPortParam); 279 280 if (bound_sockets_.find(port) != bound_sockets_.end()) 281 return command->InternalErrorResponse("Port already bound"); 282 283 scoped_ptr<BoundSocket> bound_socket(new BoundSocket(this, delegate_)); 284 if (!bound_socket->Listen(port)) 285 return command->InternalErrorResponse("Could not bind port"); 286 287 bound_sockets_[port] = bound_socket.release(); 288 return command->SuccessResponse(NULL); 289} 290 291scoped_ptr<DevToolsProtocol::Response> 292TetheringHandler::OnUnbind(DevToolsProtocol::Command* command) { 293 int port = GetPort(command); 294 if (port == 0) 295 return command->InvalidParamResponse(kPortParam); 296 297 BoundSockets::iterator it = bound_sockets_.find(port); 298 if (it == bound_sockets_.end()) 299 return command->InternalErrorResponse("Port is not bound"); 300 301 delete it->second; 302 bound_sockets_.erase(it); 303 return command->SuccessResponse(NULL); 304} 305 306} // namespace content 307