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/public/browser/devtools_http_handler_delegate.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/ip_endpoint.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/net_log.h"
17 #include "net/socket/stream_listen_socket.h"
18 #include "net/socket/stream_socket.h"
19 #include "net/socket/tcp_server_socket.h"
25 const char kTetheringBind
[] = "Tethering.bind";
26 const char kTetheringUnbind
[] = "Tethering.unbind";
28 const char kTetheringAccepted
[] = "Tethering.accepted";
30 const char kPortParam
[] = "port";
31 const char kConnectionIdParam
[] = "connectionId";
33 const char kLocalhost
[] = "127.0.0.1";
35 const int kListenBacklog
= 5;
36 const int kBufferSize
= 16 * 1024;
38 const int kMinTetheringPort
= 5000;
39 const int kMaxTetheringPort
= 10000;
41 class SocketPump
: public net::StreamListenSocket::Delegate
{
43 SocketPump(DevToolsHttpHandlerDelegate
* delegate
,
44 net::StreamSocket
* client_socket
)
45 : client_socket_(client_socket
),
48 pending_destruction_(false) {
52 std::string channel_name
;
53 server_socket_
= delegate_
->CreateSocketForTethering(this, &channel_name
);
54 if (!server_socket_
.get() || channel_name
.empty())
59 virtual ~SocketPump() { }
62 virtual void DidAccept(net::StreamListenSocket
* server
,
63 scoped_ptr
<net::StreamListenSocket
> socket
) OVERRIDE
{
64 if (accepted_socket_
.get())
67 buffer_
= new net::IOBuffer(kBufferSize
);
68 wire_buffer_
= new net::GrowableIOBuffer();
69 wire_buffer_
->SetCapacity(kBufferSize
);
71 accepted_socket_
= socket
.Pass();
72 int result
= client_socket_
->Read(
75 base::Bind(&SocketPump::OnClientRead
, base::Unretained(this)));
76 if (result
!= net::ERR_IO_PENDING
)
80 virtual void DidRead(net::StreamListenSocket
* socket
,
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())
93 virtual void DidClose(net::StreamListenSocket
* socket
) OVERRIDE
{
97 void OnClientRead(int result
) {
103 accepted_socket_
->Send(buffer_
->data(), result
);
104 result
= client_socket_
->Read(
107 base::Bind(&SocketPump::OnClientRead
, base::Unretained(this)));
108 if (result
!= net::ERR_IO_PENDING
)
109 OnClientRead(result
);
112 void OnClientWrite(int result
) {
118 wire_buffer_
->set_offset(wire_buffer_
->offset() + result
);
120 int remaining
= wire_buffer_size_
- wire_buffer_
->offset();
121 if (remaining
== 0) {
122 if (pending_destruction_
)
128 if (remaining
> kBufferSize
)
129 remaining
= kBufferSize
;
131 scoped_refptr
<net::IOBuffer
> buffer
= new net::IOBuffer(remaining
);
132 memcpy(buffer
->data(), wire_buffer_
->data(), remaining
);
133 result
= client_socket_
->Write(
136 base::Bind(&SocketPump::OnClientWrite
, base::Unretained(this)));
139 int offset
= wire_buffer_
->offset();
140 if (offset
> kBufferSize
) {
141 memcpy(wire_buffer_
->StartOfBuffer(), wire_buffer_
->data(),
142 wire_buffer_size_
- offset
);
143 wire_buffer_size_
-= offset
;
144 wire_buffer_
->set_offset(0);
147 if (result
!= net::ERR_IO_PENDING
)
148 OnClientWrite(result
);
152 void SelfDestruct() {
153 if (wire_buffer_
.get() && wire_buffer_
->offset() != wire_buffer_size_
) {
154 pending_destruction_
= true;
161 scoped_ptr
<net::StreamSocket
> client_socket_
;
162 scoped_ptr
<net::StreamListenSocket
> server_socket_
;
163 scoped_ptr
<net::StreamListenSocket
> accepted_socket_
;
164 scoped_refptr
<net::IOBuffer
> buffer_
;
165 scoped_refptr
<net::GrowableIOBuffer
> wire_buffer_
;
166 DevToolsHttpHandlerDelegate
* delegate_
;
167 int wire_buffer_size_
;
168 bool pending_destruction_
;
173 const char TetheringHandler::kDomain
[] = "Tethering";
175 class TetheringHandler::BoundSocket
{
177 BoundSocket(TetheringHandler
* handler
,
178 DevToolsHttpHandlerDelegate
* delegate
)
181 socket_(new net::TCPServerSocket(NULL
, net::NetLog::Source())),
185 virtual ~BoundSocket() {
188 bool Listen(int port
) {
190 net::IPAddressNumber ip_number
;
191 if (!net::ParseIPLiteralToNumber(kLocalhost
, &ip_number
))
194 net::IPEndPoint
end_point(ip_number
, port
);
195 int result
= socket_
->Listen(end_point
, kListenBacklog
);
199 net::IPEndPoint local_address
;
200 result
= socket_
->GetLocalAddress(&local_address
);
209 typedef std::map
<net::IPEndPoint
, net::StreamSocket
*> AcceptedSocketsMap
;
213 int result
= socket_
->Accept(
215 base::Bind(&BoundSocket::OnAccepted
, base::Unretained(this)));
216 if (result
== net::ERR_IO_PENDING
)
219 HandleAcceptResult(result
);
223 void OnAccepted(int result
) {
224 HandleAcceptResult(result
);
225 if (result
== net::OK
)
229 void HandleAcceptResult(int result
) {
230 if (result
!= net::OK
)
233 SocketPump
* pump
= new SocketPump(delegate_
, accept_socket_
.release());
234 std::string name
= pump
->Init();
236 handler_
->Accepted(port_
, name
);
239 TetheringHandler
* handler_
;
240 DevToolsHttpHandlerDelegate
* delegate_
;
241 scoped_ptr
<net::ServerSocket
> socket_
;
242 scoped_ptr
<net::StreamSocket
> accept_socket_
;
246 TetheringHandler::TetheringHandler(DevToolsHttpHandlerDelegate
* delegate
)
247 : delegate_(delegate
) {
248 RegisterCommandHandler(kTetheringBind
,
249 base::Bind(&TetheringHandler::OnBind
,
250 base::Unretained(this)));
251 RegisterCommandHandler(kTetheringUnbind
,
252 base::Bind(&TetheringHandler::OnUnbind
,
253 base::Unretained(this)));
256 TetheringHandler::~TetheringHandler() {
257 STLDeleteContainerPairSecondPointers(bound_sockets_
.begin(),
258 bound_sockets_
.end());
261 void TetheringHandler::Accepted(int port
, const std::string
& name
) {
262 base::DictionaryValue
* params
= new base::DictionaryValue();
263 params
->SetInteger(kPortParam
, port
);
264 params
->SetString(kConnectionIdParam
, name
);
265 SendNotification(kTetheringAccepted
, params
);
268 static int GetPort(scoped_refptr
<DevToolsProtocol::Command
> command
) {
269 base::DictionaryValue
* params
= command
->params();
271 if (!params
|| !params
->GetInteger(kPortParam
, &port
) ||
272 port
< kMinTetheringPort
|| port
> kMaxTetheringPort
)
277 scoped_refptr
<DevToolsProtocol::Response
>
278 TetheringHandler::OnBind(scoped_refptr
<DevToolsProtocol::Command
> command
) {
279 int port
= GetPort(command
);
281 return command
->InvalidParamResponse(kPortParam
);
283 if (bound_sockets_
.find(port
) != bound_sockets_
.end())
284 return command
->InternalErrorResponse("Port already bound");
286 scoped_ptr
<BoundSocket
> bound_socket(new BoundSocket(this, delegate_
));
287 if (!bound_socket
->Listen(port
))
288 return command
->InternalErrorResponse("Could not bind port");
290 bound_sockets_
[port
] = bound_socket
.release();
291 return command
->SuccessResponse(NULL
);
294 scoped_refptr
<DevToolsProtocol::Response
>
295 TetheringHandler::OnUnbind(scoped_refptr
<DevToolsProtocol::Command
> command
) {
296 int port
= GetPort(command
);
298 return command
->InvalidParamResponse(kPortParam
);
300 BoundSockets::iterator it
= bound_sockets_
.find(port
);
301 if (it
== bound_sockets_
.end())
302 return command
->InternalErrorResponse("Port is not bound");
305 bound_sockets_
.erase(it
);
306 return command
->SuccessResponse(NULL
);
309 } // namespace content