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 "components/devtools_bridge/socket_tunnel_server.h"
8 #include "base/location.h"
9 #include "components/devtools_bridge/abstract_data_channel.h"
10 #include "components/devtools_bridge/session_dependency_factory.h"
11 #include "components/devtools_bridge/socket_tunnel_connection.h"
12 #include "components/devtools_bridge/socket_tunnel_packet_handler.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
15 #include "net/socket/unix_domain_client_socket_posix.h"
17 namespace devtools_bridge
{
19 class SocketTunnelServer::Connection
: public SocketTunnelConnection
{
23 virtual void RemoveConnection(int index
) = 0;
24 virtual void SendPacket(
25 const void* data
, size_t length
) = 0;
28 Connection(Delegate
* delegate
, int index
, const std::string
& socket_name
)
29 : SocketTunnelConnection(index
),
31 socket_(socket_name
, true) {
35 int result
= socket()->Connect(base::Bind(
36 &Connection::OnConnectionComplete
, base::Unretained(this)));
37 if (result
!= net::ERR_IO_PENDING
)
38 OnConnectionComplete(result
);
41 void ClosedByClient() {
42 if (socket()->IsConnected()) {
43 socket()->Disconnect();
44 SendControlPacket(SERVER_CLOSE
);
46 delegate_
->RemoveConnection(index_
);
50 net::StreamSocket
* socket() override
{
54 void OnDataPacketRead(const void* data
, size_t length
) override
{
55 delegate_
->SendPacket(data
, length
);
59 void OnReadError(int error
) override
{
60 socket()->Disconnect();
61 SendControlPacket(SERVER_CLOSE
);
62 delegate_
->RemoveConnection(index_
);
67 void OnConnectionComplete(int result
) {
68 if (result
== net::OK
) {
69 SendControlPacket(SERVER_OPEN_ACK
);
72 SendControlPacket(SERVER_CLOSE
);
73 delegate_
->RemoveConnection(index_
);
78 void SendControlPacket(ServerOpCode op_code
) {
79 char buffer
[kControlPacketSizeBytes
];
80 BuildControlPacket(buffer
, op_code
);
81 delegate_
->SendPacket(buffer
, kControlPacketSizeBytes
);
85 net::UnixDomainClientSocket socket_
;
89 * Lives on the IO thread.
91 class SocketTunnelServer::ConnectionController
92 : private Connection::Delegate
{
95 scoped_refptr
<base::TaskRunner
> io_task_runner
,
96 scoped_refptr
<AbstractDataChannel::Proxy
> data_channel
,
97 const std::string
& socket_name
)
98 : io_task_runner_(io_task_runner
),
99 data_channel_(data_channel
),
100 socket_name_(socket_name
) {
101 DCHECK(data_channel_
.get());
104 void HandleControlPacket(int connection_index
, int op_code
) {
105 DCHECK(connection_index
< kMaxConnectionCount
);
107 case SocketTunnelConnection::CLIENT_OPEN
:
108 if (connections_
[connection_index
].get() != NULL
) {
109 DLOG(ERROR
) << "Opening connection which already open: "
111 HandleProtocolError();
114 connections_
[connection_index
].reset(
115 new Connection(this, connection_index
, socket_name_
));
116 connections_
[connection_index
]->Connect();
119 case SocketTunnelConnection::CLIENT_CLOSE
:
120 if (connections_
[connection_index
].get() == NULL
) {
121 // Ignore. Client may close the connection before received
122 // notification from the server.
125 connections_
[connection_index
]->ClosedByClient();
129 DLOG(ERROR
) << "Invalid op_code: " << op_code
;
130 HandleProtocolError();
135 void HandleDataPacket(int connection_index
,
136 scoped_refptr
<net::IOBufferWithSize
> packet
) {
137 Connection
* connection
= connections_
[connection_index
].get();
138 if (connection
!= NULL
)
139 connection
->Write(packet
);
142 void HandleProtocolError() {
143 data_channel_
->Close();
146 void CloseAllConnections() {
147 for (int i
= 0; i
< kMaxConnectionCount
; i
++) {
148 connections_
[i
].reset();
153 static void DeleteConnectionImpl(Connection
*) {}
155 // Connection::Delegate implementation
156 void RemoveConnection(int connection_index
) override
{
157 // Remove immediately, delete later to preserve this of the caller.
158 Connection
* connection
= connections_
[connection_index
].release();
159 io_task_runner_
->PostTask(
160 FROM_HERE
, base::Bind(&ConnectionController::DeleteConnectionImpl
,
161 base::Owned(connection
)));
164 void SendPacket(const void* data
, size_t length
) override
{
165 data_channel_
->SendBinaryMessage(data
, length
);
168 static const int kMaxConnectionCount
=
169 SocketTunnelConnection::kMaxConnectionCount
;
171 scoped_refptr
<base::TaskRunner
> io_task_runner_
;
172 scoped_refptr
<AbstractDataChannel::Proxy
> data_channel_
;
173 scoped_ptr
<Connection
> connections_
[kMaxConnectionCount
];
174 const std::string socket_name_
;
177 class SocketTunnelServer::DataChannelObserver
178 : public AbstractDataChannel::Observer
,
179 private SocketTunnelPacketHandler
{
181 DataChannelObserver(scoped_refptr
<base::TaskRunner
> io_task_runner
,
182 scoped_ptr
<ConnectionController
> controller
)
183 : io_task_runner_(io_task_runner
),
184 controller_(controller
.Pass()) {
187 ~DataChannelObserver() override
{
188 // Deleting on IO thread allows post tasks with base::Unretained
189 // because all of them will be processed before deletion.
190 io_task_runner_
->PostTask(
191 FROM_HERE
, base::Bind(&DataChannelObserver::DeleteControllerOnIOThread
,
192 base::Passed(&controller_
)));
195 void OnOpen() override
{
196 // Nothing to do. Activity could only be initiated by a control packet.
199 void OnClose() override
{
200 io_task_runner_
->PostTask(
201 FROM_HERE
, base::Bind(
202 &ConnectionController::CloseAllConnections
,
203 base::Unretained(controller_
.get())));
206 void OnMessage(const void* data
, size_t length
) override
{
207 DecodePacket(data
, length
);
211 static void DeleteControllerOnIOThread(
212 scoped_ptr
<ConnectionController
> controller
) {}
214 // SocketTunnelPacketHandler implementation.
216 void HandleControlPacket(int connection_index
, int op_code
) override
{
217 io_task_runner_
->PostTask(
218 FROM_HERE
, base::Bind(
219 &ConnectionController::HandleControlPacket
,
220 base::Unretained(controller_
.get()),
225 void HandleDataPacket(int connection_index
,
226 scoped_refptr
<net::IOBufferWithSize
> data
) override
{
227 io_task_runner_
->PostTask(
228 FROM_HERE
, base::Bind(
229 &ConnectionController::HandleDataPacket
,
230 base::Unretained(controller_
.get()),
235 void HandleProtocolError() override
{
236 io_task_runner_
->PostTask(
237 FROM_HERE
, base::Bind(
238 &ConnectionController::HandleProtocolError
,
239 base::Unretained(controller_
.get())));
242 const scoped_refptr
<base::TaskRunner
> io_task_runner_
;
243 scoped_ptr
<ConnectionController
> controller_
;
246 SocketTunnelServer::SocketTunnelServer(SessionDependencyFactory
* factory
,
247 AbstractDataChannel
* data_channel
,
248 const std::string
& socket_name
)
249 : data_channel_(data_channel
) {
250 scoped_ptr
<ConnectionController
> controller(
251 new ConnectionController(factory
->io_thread_task_runner(),
252 data_channel
->proxy(),
255 scoped_ptr
<DataChannelObserver
> data_channel_observer(
256 new DataChannelObserver(factory
->io_thread_task_runner(),
259 data_channel_
->RegisterObserver(data_channel_observer
.Pass());
262 SocketTunnelServer::~SocketTunnelServer() {
263 data_channel_
->UnregisterObserver();
266 } // namespace devtools_bridge