1 // Copyright 2014 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/protocol/tethering_handler.h"
7 #include "content/public/browser/browser_thread.h"
8 #include "content/public/browser/devtools_http_handler_delegate.h"
9 #include "net/base/io_buffer.h"
10 #include "net/base/net_errors.h"
11 #include "net/socket/server_socket.h"
12 #include "net/socket/stream_socket.h"
13 #include "net/socket/tcp_server_socket.h"
21 const char kLocalhost
[] = "127.0.0.1";
23 const int kListenBacklog
= 5;
24 const int kBufferSize
= 16 * 1024;
26 const int kMinTetheringPort
= 1024;
27 const int kMaxTetheringPort
= 32767;
29 using Response
= DevToolsProtocolClient::Response
;
33 SocketPump(DevToolsHttpHandlerDelegate
* delegate
,
34 net::StreamSocket
* client_socket
)
35 : client_socket_(client_socket
),
38 pending_destruction_(false) {
42 std::string channel_name
;
43 server_socket_
= delegate_
->CreateSocketForTethering(&channel_name
);
44 if (!server_socket_
.get() || channel_name
.empty())
47 int result
= server_socket_
->Accept(
49 base::Bind(&SocketPump::OnAccepted
, base::Unretained(this)));
50 if (result
!= net::ERR_IO_PENDING
)
56 void OnAccepted(int result
) {
62 ++pending_writes_
; // avoid SelfDestruct in first Pump
63 Pump(client_socket_
.get(), accepted_socket_
.get());
65 if (pending_destruction_
) {
68 Pump(accepted_socket_
.get(), client_socket_
.get());
72 void Pump(net::StreamSocket
* from
, net::StreamSocket
* to
) {
73 scoped_refptr
<net::IOBuffer
> buffer
= new net::IOBuffer(kBufferSize
);
74 int result
= from
->Read(
78 &SocketPump::OnRead
, base::Unretained(this), from
, to
, buffer
));
79 if (result
!= net::ERR_IO_PENDING
)
80 OnRead(from
, to
, buffer
, result
);
83 void OnRead(net::StreamSocket
* from
,
84 net::StreamSocket
* to
,
85 scoped_refptr
<net::IOBuffer
> buffer
,
93 scoped_refptr
<net::DrainableIOBuffer
> drainable
=
94 new net::DrainableIOBuffer(buffer
.get(), total
);
97 result
= to
->Write(drainable
.get(),
99 base::Bind(&SocketPump::OnWritten
,
100 base::Unretained(this),
104 if (result
!= net::ERR_IO_PENDING
)
105 OnWritten(drainable
, from
, to
, result
);
108 void OnWritten(scoped_refptr
<net::DrainableIOBuffer
> drainable
,
109 net::StreamSocket
* from
,
110 net::StreamSocket
* to
,
118 drainable
->DidConsume(result
);
119 if (drainable
->BytesRemaining() > 0) {
121 result
= to
->Write(drainable
.get(),
122 drainable
->BytesRemaining(),
123 base::Bind(&SocketPump::OnWritten
,
124 base::Unretained(this),
128 if (result
!= net::ERR_IO_PENDING
)
129 OnWritten(drainable
, from
, to
, result
);
133 if (pending_destruction_
) {
140 void SelfDestruct() {
141 if (pending_writes_
> 0) {
142 pending_destruction_
= true;
150 scoped_ptr
<net::StreamSocket
> client_socket_
;
151 scoped_ptr
<net::ServerSocket
> server_socket_
;
152 scoped_ptr
<net::StreamSocket
> accepted_socket_
;
153 DevToolsHttpHandlerDelegate
* delegate_
;
155 bool pending_destruction_
;
160 typedef base::Callback
<void(uint16
, const std::string
&)> AcceptedCallback
;
162 BoundSocket(AcceptedCallback accepted_callback
,
163 DevToolsHttpHandlerDelegate
* delegate
)
164 : accepted_callback_(accepted_callback
),
166 socket_(new net::TCPServerSocket(NULL
, net::NetLog::Source())),
170 virtual ~BoundSocket() {
173 bool Listen(uint16 port
) {
175 net::IPAddressNumber ip_number
;
176 if (!net::ParseIPLiteralToNumber(kLocalhost
, &ip_number
))
179 net::IPEndPoint
end_point(ip_number
, port
);
180 int result
= socket_
->Listen(end_point
, kListenBacklog
);
184 net::IPEndPoint local_address
;
185 result
= socket_
->GetLocalAddress(&local_address
);
194 typedef std::map
<net::IPEndPoint
, net::StreamSocket
*> AcceptedSocketsMap
;
198 int result
= socket_
->Accept(
200 base::Bind(&BoundSocket::OnAccepted
, base::Unretained(this)));
201 if (result
== net::ERR_IO_PENDING
)
204 HandleAcceptResult(result
);
208 void OnAccepted(int result
) {
209 HandleAcceptResult(result
);
210 if (result
== net::OK
)
214 void HandleAcceptResult(int result
) {
215 if (result
!= net::OK
)
218 SocketPump
* pump
= new SocketPump(delegate_
, accept_socket_
.release());
219 std::string name
= pump
->Init();
221 accepted_callback_
.Run(port_
, name
);
224 AcceptedCallback accepted_callback_
;
225 DevToolsHttpHandlerDelegate
* delegate_
;
226 scoped_ptr
<net::ServerSocket
> socket_
;
227 scoped_ptr
<net::StreamSocket
> accept_socket_
;
233 // TetheringHandler::TetheringImpl -------------------------------------------
235 class TetheringHandler::TetheringImpl
{
238 base::WeakPtr
<TetheringHandler
> handler
,
239 DevToolsHttpHandlerDelegate
* delegate
);
242 void Bind(DevToolsCommandId command_id
, uint16 port
);
243 void Unbind(DevToolsCommandId command_id
, uint16 port
);
244 void Accepted(uint16 port
, const std::string
& name
);
247 void SendInternalError(DevToolsCommandId command_id
,
248 const std::string
& message
);
250 base::WeakPtr
<TetheringHandler
> handler_
;
251 DevToolsHttpHandlerDelegate
* delegate_
;
253 typedef std::map
<uint16
, BoundSocket
*> BoundSockets
;
254 BoundSockets bound_sockets_
;
257 TetheringHandler::TetheringImpl::TetheringImpl(
258 base::WeakPtr
<TetheringHandler
> handler
,
259 DevToolsHttpHandlerDelegate
* delegate
)
261 delegate_(delegate
) {
264 TetheringHandler::TetheringImpl::~TetheringImpl() {
265 STLDeleteContainerPairSecondPointers(bound_sockets_
.begin(),
266 bound_sockets_
.end());
269 void TetheringHandler::TetheringImpl::Bind(
270 DevToolsCommandId command_id
, uint16 port
) {
271 if (bound_sockets_
.find(port
) != bound_sockets_
.end()) {
272 SendInternalError(command_id
, "Port already bound");
276 BoundSocket::AcceptedCallback callback
= base::Bind(
277 &TetheringHandler::TetheringImpl::Accepted
, base::Unretained(this));
278 scoped_ptr
<BoundSocket
> bound_socket(new BoundSocket(callback
, delegate_
));
279 if (!bound_socket
->Listen(port
)) {
280 SendInternalError(command_id
, "Could not bind port");
284 bound_sockets_
[port
] = bound_socket
.release();
285 BrowserThread::PostTask(
288 base::Bind(&TetheringHandler::SendBindSuccess
, handler_
, command_id
));
291 void TetheringHandler::TetheringImpl::Unbind(
292 DevToolsCommandId command_id
, uint16 port
) {
294 BoundSockets::iterator it
= bound_sockets_
.find(port
);
295 if (it
== bound_sockets_
.end()) {
296 SendInternalError(command_id
, "Port is not bound");
301 bound_sockets_
.erase(it
);
302 BrowserThread::PostTask(
305 base::Bind(&TetheringHandler::SendUnbindSuccess
, handler_
, command_id
));
308 void TetheringHandler::TetheringImpl::Accepted(
309 uint16 port
, const std::string
& name
) {
310 BrowserThread::PostTask(
313 base::Bind(&TetheringHandler::Accepted
, handler_
, port
, name
));
316 void TetheringHandler::TetheringImpl::SendInternalError(
317 DevToolsCommandId command_id
,
318 const std::string
& message
) {
319 BrowserThread::PostTask(
322 base::Bind(&TetheringHandler::SendInternalError
, handler_
,
323 command_id
, message
));
327 // TetheringHandler ----------------------------------------------------------
330 TetheringHandler::TetheringImpl
* TetheringHandler::impl_
= nullptr;
332 TetheringHandler::TetheringHandler(
333 DevToolsHttpHandlerDelegate
* delegate
,
334 scoped_refptr
<base::MessageLoopProxy
> message_loop_proxy
)
335 : delegate_(delegate
),
336 message_loop_proxy_(message_loop_proxy
),
338 weak_factory_(this) {
341 TetheringHandler::~TetheringHandler() {
343 message_loop_proxy_
->DeleteSoon(FROM_HERE
, impl_
);
348 void TetheringHandler::SetClient(scoped_ptr
<Client
> client
) {
349 client_
.swap(client
);
352 void TetheringHandler::Accepted(uint16 port
, const std::string
& name
) {
353 client_
->Accepted(AcceptedParams::Create()->set_port(port
)
354 ->set_connection_id(name
));
357 bool TetheringHandler::Activate() {
363 impl_
= new TetheringImpl(weak_factory_
.GetWeakPtr(), delegate_
);
367 Response
TetheringHandler::Bind(DevToolsCommandId command_id
, int port
) {
368 if (port
< kMinTetheringPort
|| port
> kMaxTetheringPort
)
369 return Response::InvalidParams("port");
372 return Response::ServerError("Tethering is used by another connection");
375 message_loop_proxy_
->PostTask(
377 base::Bind(&TetheringImpl::Bind
, base::Unretained(impl_
),
379 return Response::OK();
382 Response
TetheringHandler::Unbind(DevToolsCommandId command_id
, int port
) {
384 return Response::ServerError("Tethering is used by another connection");
387 message_loop_proxy_
->PostTask(
389 base::Bind(&TetheringImpl::Unbind
, base::Unretained(impl_
),
391 return Response::OK();
394 void TetheringHandler::SendBindSuccess(DevToolsCommandId command_id
) {
395 client_
->SendBindResponse(command_id
, BindResponse::Create());
398 void TetheringHandler::SendUnbindSuccess(DevToolsCommandId command_id
) {
399 client_
->SendUnbindResponse(command_id
, UnbindResponse::Create());
402 void TetheringHandler::SendInternalError(DevToolsCommandId command_id
,
403 const std::string
& message
) {
404 client_
->SendError(command_id
, Response::InternalError(message
));
407 } // namespace tethering
408 } // namespace devtools
409 } // namespace content