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_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"
26 const char kTetheringBind
[] = "Tethering.bind";
27 const char kTetheringUnbind
[] = "Tethering.unbind";
29 const char kTetheringAccepted
[] = "Tethering.accepted";
31 const char kPortParam
[] = "port";
32 const char kConnectionIdParam
[] = "connectionId";
34 const char kLocalhost
[] = "127.0.0.1";
36 const int kListenBacklog
= 5;
37 const int kBufferSize
= 16 * 1024;
39 const int kMinTetheringPort
= 5000;
40 const int kMaxTetheringPort
= 10000;
42 class SocketPump
: public net::StreamListenSocket::Delegate
{
44 SocketPump(DevToolsHttpHandlerDelegate
* delegate
,
45 net::StreamSocket
* client_socket
)
46 : client_socket_(client_socket
),
49 pending_destruction_(false) {
53 std::string channel_name
;
54 server_socket_
= delegate_
->CreateSocketForTethering(this, &channel_name
);
55 if (!server_socket_
.get() || channel_name
.empty())
60 virtual ~SocketPump() { }
63 virtual void DidAccept(net::StreamListenSocket
* server
,
64 scoped_ptr
<net::StreamListenSocket
> socket
) OVERRIDE
{
65 if (accepted_socket_
.get())
68 buffer_
= new net::IOBuffer(kBufferSize
);
69 wire_buffer_
= new net::GrowableIOBuffer();
70 wire_buffer_
->SetCapacity(kBufferSize
);
72 accepted_socket_
= socket
.Pass();
73 int result
= client_socket_
->Read(
76 base::Bind(&SocketPump::OnClientRead
, base::Unretained(this)));
77 if (result
!= net::ERR_IO_PENDING
)
81 virtual void DidRead(net::StreamListenSocket
* socket
,
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())
94 virtual void DidClose(net::StreamListenSocket
* socket
) OVERRIDE
{
98 void OnClientRead(int result
) {
104 accepted_socket_
->Send(buffer_
->data(), result
);
105 result
= client_socket_
->Read(
108 base::Bind(&SocketPump::OnClientRead
, base::Unretained(this)));
109 if (result
!= net::ERR_IO_PENDING
)
110 OnClientRead(result
);
113 void OnClientWrite(int result
) {
117 wire_buffer_
->set_offset(wire_buffer_
->offset() + result
);
119 int remaining
= wire_buffer_size_
- wire_buffer_
->offset();
120 if (remaining
== 0) {
121 if (pending_destruction_
)
127 if (remaining
> kBufferSize
)
128 remaining
= kBufferSize
;
130 scoped_refptr
<net::IOBuffer
> buffer
= new net::IOBuffer(remaining
);
131 memcpy(buffer
->data(), wire_buffer_
->data(), remaining
);
132 result
= client_socket_
->Write(
135 base::Bind(&SocketPump::OnClientWrite
, base::Unretained(this)));
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);
146 if (result
!= net::ERR_IO_PENDING
)
147 OnClientWrite(result
);
151 void SelfDestruct() {
152 if (wire_buffer_
&& wire_buffer_
->offset() != wire_buffer_size_
) {
153 pending_destruction_
= true;
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_
;
172 const char TetheringHandler::kDomain
[] = "Tethering";
174 class TetheringHandler::BoundSocket
{
176 BoundSocket(TetheringHandler
* handler
,
177 DevToolsHttpHandlerDelegate
* delegate
)
180 socket_(new net::TCPServerSocket(NULL
, net::NetLog::Source())),
184 virtual ~BoundSocket() {
187 bool Listen(int port
) {
189 net::IPAddressNumber ip_number
;
190 if (!net::ParseIPLiteralToNumber(kLocalhost
, &ip_number
))
193 net::IPEndPoint
end_point(ip_number
, port
);
194 int result
= socket_
->Listen(end_point
, kListenBacklog
);
198 net::IPEndPoint local_address
;
199 result
= socket_
->GetLocalAddress(&local_address
);
208 typedef std::map
<net::IPEndPoint
, net::StreamSocket
*> AcceptedSocketsMap
;
212 int result
= socket_
->Accept(
214 base::Bind(&BoundSocket::OnAccepted
, base::Unretained(this)));
215 if (result
== net::ERR_IO_PENDING
)
218 HandleAcceptResult(result
);
222 void OnAccepted(int result
) {
223 HandleAcceptResult(result
);
224 if (result
== net::OK
)
228 void HandleAcceptResult(int result
) {
229 if (result
!= net::OK
)
232 SocketPump
* pump
= new SocketPump(delegate_
, accept_socket_
.release());
233 std::string name
= pump
->Init();
235 handler_
->Accepted(port_
, name
);
238 TetheringHandler
* handler_
;
239 DevToolsHttpHandlerDelegate
* delegate_
;
240 scoped_ptr
<net::ServerSocket
> socket_
;
241 scoped_ptr
<net::StreamSocket
> accept_socket_
;
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)));
255 TetheringHandler::~TetheringHandler() {
256 STLDeleteContainerPairSecondPointers(bound_sockets_
.begin(),
257 bound_sockets_
.end());
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
);
267 static int GetPort(scoped_refptr
<DevToolsProtocol::Command
> command
) {
268 base::DictionaryValue
* params
= command
->params();
270 if (!params
|| !params
->GetInteger(kPortParam
, &port
) ||
271 port
< kMinTetheringPort
|| port
> kMaxTetheringPort
)
276 scoped_refptr
<DevToolsProtocol::Response
>
277 TetheringHandler::OnBind(scoped_refptr
<DevToolsProtocol::Command
> command
) {
278 int port
= GetPort(command
);
280 return command
->InvalidParamResponse(kPortParam
);
282 if (bound_sockets_
.find(port
) != bound_sockets_
.end())
283 return command
->InternalErrorResponse("Port already bound");
285 scoped_ptr
<BoundSocket
> bound_socket(new BoundSocket(this, delegate_
));
286 if (!bound_socket
->Listen(port
))
287 return command
->InternalErrorResponse("Could not bind port");
289 bound_sockets_
[port
] = bound_socket
.release();
290 return command
->SuccessResponse(NULL
);
293 scoped_refptr
<DevToolsProtocol::Response
>
294 TetheringHandler::OnUnbind(scoped_refptr
<DevToolsProtocol::Command
> command
) {
295 int port
= GetPort(command
);
297 return command
->InvalidParamResponse(kPortParam
);
299 BoundSockets::iterator it
= bound_sockets_
.find(port
);
300 if (it
== bound_sockets_
.end())
301 return command
->InternalErrorResponse("Port is not bound");
304 bound_sockets_
.erase(it
);
305 return command
->SuccessResponse(NULL
);
308 } // namespace content