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.
5 #include "content/browser/devtools/tethering_handler.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/browser/devtools/devtools_protocol_constants.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"
26 const char kLocalhost[] = "127.0.0.1";
28 const int kListenBacklog = 5;
29 const int kBufferSize = 16 * 1024;
31 const int kMinTetheringPort = 1024;
32 const int kMaxTetheringPort = 32767;
34 class SocketPump : public net::StreamListenSocket::Delegate {
36 SocketPump(DevToolsHttpHandlerDelegate* delegate,
37 net::StreamSocket* client_socket)
38 : client_socket_(client_socket),
41 pending_destruction_(false) {
45 std::string channel_name;
46 server_socket_ = delegate_->CreateSocketForTethering(this, &channel_name);
47 if (!server_socket_.get() || channel_name.empty())
52 virtual ~SocketPump() { }
55 virtual void DidAccept(net::StreamListenSocket* server,
56 scoped_ptr<net::StreamListenSocket> socket) OVERRIDE {
57 if (accepted_socket_.get())
60 buffer_ = new net::IOBuffer(kBufferSize);
61 wire_buffer_ = new net::GrowableIOBuffer();
62 wire_buffer_->SetCapacity(kBufferSize);
64 accepted_socket_ = socket.Pass();
65 int result = client_socket_->Read(
68 base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
69 if (result != net::ERR_IO_PENDING)
73 virtual void DidRead(net::StreamListenSocket* socket,
76 int old_size = wire_buffer_size_;
77 wire_buffer_size_ += len;
78 while (wire_buffer_->capacity() < wire_buffer_size_)
79 wire_buffer_->SetCapacity(wire_buffer_->capacity() * 2);
80 memcpy(wire_buffer_->StartOfBuffer() + old_size, data, len);
81 if (old_size != wire_buffer_->offset())
86 virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE {
90 void OnClientRead(int result) {
96 accepted_socket_->Send(buffer_->data(), result);
97 result = client_socket_->Read(
100 base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
101 if (result != net::ERR_IO_PENDING)
102 OnClientRead(result);
105 void OnClientWrite(int result) {
111 wire_buffer_->set_offset(wire_buffer_->offset() + result);
113 int remaining = wire_buffer_size_ - wire_buffer_->offset();
114 if (remaining == 0) {
115 if (pending_destruction_)
121 if (remaining > kBufferSize)
122 remaining = kBufferSize;
124 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(remaining);
125 memcpy(buffer->data(), wire_buffer_->data(), remaining);
126 result = client_socket_->Write(
129 base::Bind(&SocketPump::OnClientWrite, base::Unretained(this)));
132 int offset = wire_buffer_->offset();
133 if (offset > kBufferSize) {
134 memcpy(wire_buffer_->StartOfBuffer(), wire_buffer_->data(),
135 wire_buffer_size_ - offset);
136 wire_buffer_size_ -= offset;
137 wire_buffer_->set_offset(0);
140 if (result != net::ERR_IO_PENDING)
141 OnClientWrite(result);
145 void SelfDestruct() {
146 if (wire_buffer_.get() && wire_buffer_->offset() != wire_buffer_size_) {
147 pending_destruction_ = true;
154 scoped_ptr<net::StreamSocket> client_socket_;
155 scoped_ptr<net::StreamListenSocket> server_socket_;
156 scoped_ptr<net::StreamListenSocket> accepted_socket_;
157 scoped_refptr<net::IOBuffer> buffer_;
158 scoped_refptr<net::GrowableIOBuffer> wire_buffer_;
159 DevToolsHttpHandlerDelegate* delegate_;
160 int wire_buffer_size_;
161 bool pending_destruction_;
166 class TetheringHandler::BoundSocket {
168 BoundSocket(TetheringHandler* handler,
169 DevToolsHttpHandlerDelegate* delegate)
172 socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
176 virtual ~BoundSocket() {
179 bool Listen(int port) {
181 net::IPAddressNumber ip_number;
182 if (!net::ParseIPLiteralToNumber(kLocalhost, &ip_number))
185 net::IPEndPoint end_point(ip_number, port);
186 int result = socket_->Listen(end_point, kListenBacklog);
190 net::IPEndPoint local_address;
191 result = socket_->GetLocalAddress(&local_address);
200 typedef std::map<net::IPEndPoint, net::StreamSocket*> AcceptedSocketsMap;
204 int result = socket_->Accept(
206 base::Bind(&BoundSocket::OnAccepted, base::Unretained(this)));
207 if (result == net::ERR_IO_PENDING)
210 HandleAcceptResult(result);
214 void OnAccepted(int result) {
215 HandleAcceptResult(result);
216 if (result == net::OK)
220 void HandleAcceptResult(int result) {
221 if (result != net::OK)
224 SocketPump* pump = new SocketPump(delegate_, accept_socket_.release());
225 std::string name = pump->Init();
227 handler_->Accepted(port_, name);
230 TetheringHandler* handler_;
231 DevToolsHttpHandlerDelegate* delegate_;
232 scoped_ptr<net::ServerSocket> socket_;
233 scoped_ptr<net::StreamSocket> accept_socket_;
237 TetheringHandler::TetheringHandler(DevToolsHttpHandlerDelegate* delegate)
238 : delegate_(delegate) {
239 RegisterCommandHandler(devtools::Tethering::bind::kName,
240 base::Bind(&TetheringHandler::OnBind,
241 base::Unretained(this)));
242 RegisterCommandHandler(devtools::Tethering::unbind::kName,
243 base::Bind(&TetheringHandler::OnUnbind,
244 base::Unretained(this)));
247 TetheringHandler::~TetheringHandler() {
248 STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
249 bound_sockets_.end());
252 void TetheringHandler::Accepted(int port, const std::string& name) {
253 base::DictionaryValue* params = new base::DictionaryValue();
254 params->SetInteger(devtools::Tethering::accepted::kParamPort, port);
255 params->SetString(devtools::Tethering::accepted::kParamConnectionId, name);
256 SendNotification(devtools::Tethering::accepted::kName, params);
259 static int GetPort(scoped_refptr<DevToolsProtocol::Command> command,
260 const std::string& paramName) {
261 base::DictionaryValue* params = command->params();
264 !params->GetInteger(paramName, &port) ||
265 port < kMinTetheringPort || port > kMaxTetheringPort)
270 scoped_refptr<DevToolsProtocol::Response>
271 TetheringHandler::OnBind(scoped_refptr<DevToolsProtocol::Command> command) {
272 const std::string& portParamName = devtools::Tethering::bind::kParamPort;
273 int port = GetPort(command, portParamName);
275 return command->InvalidParamResponse(portParamName);
277 if (bound_sockets_.find(port) != bound_sockets_.end())
278 return command->InternalErrorResponse("Port already bound");
280 scoped_ptr<BoundSocket> bound_socket(new BoundSocket(this, delegate_));
281 if (!bound_socket->Listen(port))
282 return command->InternalErrorResponse("Could not bind port");
284 bound_sockets_[port] = bound_socket.release();
285 return command->SuccessResponse(NULL);
288 scoped_refptr<DevToolsProtocol::Response>
289 TetheringHandler::OnUnbind(scoped_refptr<DevToolsProtocol::Command> command) {
290 const std::string& portParamName = devtools::Tethering::unbind::kParamPort;
291 int port = GetPort(command, portParamName);
293 return command->InvalidParamResponse(portParamName);
295 BoundSockets::iterator it = bound_sockets_.find(port);
296 if (it == bound_sockets_.end())
297 return command->InternalErrorResponse("Port is not bound");
300 bound_sockets_.erase(it);
301 return command->SuccessResponse(NULL);
304 } // namespace content