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