blob: 711adcd2d721088d3fc60d0b5a465fe8cce52abf [file] [log] [blame]
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001// 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.
4
5#include "content/browser/devtools/tethering_handler.h"
6
7#include "base/bind.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"
21
22namespace content {
23
24namespace {
25
26const char kTetheringBind[] = "Tethering.bind";
27const char kTetheringUnbind[] = "Tethering.unbind";
28
29const char kTetheringAccepted[] = "Tethering.accepted";
30
31const char kPortParam[] = "port";
32const char kConnectionIdParam[] = "connectionId";
33
34const char kLocalhost[] = "127.0.0.1";
35
36const int kListenBacklog = 5;
37const int kBufferSize = 16 * 1024;
38
39const int kMinTetheringPort = 5000;
40const int kMaxTetheringPort = 10000;
41
42class SocketPump : public net::StreamListenSocket::Delegate {
43 public:
44 SocketPump(DevToolsHttpHandlerDelegate* delegate,
45 net::StreamSocket* client_socket)
46 : client_socket_(client_socket),
47 delegate_(delegate),
48 wire_buffer_size_(0),
49 pending_destruction_(false) {
50 }
51
52 std::string Init() {
53 std::string channel_name;
54 server_socket_ = delegate_->CreateSocketForTethering(this, &channel_name);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010055 if (!server_socket_.get() || channel_name.empty())
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010056 SelfDestruct();
57 return channel_name;
58 }
59
60 virtual ~SocketPump() { }
61
62 private:
63 virtual void DidAccept(net::StreamListenSocket* server,
64 net::StreamListenSocket* socket) OVERRIDE {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010065 if (accepted_socket_.get())
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010066 return;
67
68 buffer_ = new net::IOBuffer(kBufferSize);
69 wire_buffer_ = new net::GrowableIOBuffer();
70 wire_buffer_->SetCapacity(kBufferSize);
71
72 accepted_socket_ = socket;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010073 int result = client_socket_->Read(
74 buffer_.get(),
75 kBufferSize,
76 base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010077 if (result != net::ERR_IO_PENDING)
78 OnClientRead(result);
79 }
80
81 virtual void DidRead(net::StreamListenSocket* socket,
82 const char* data,
83 int len) OVERRIDE {
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())
90 return;
91 OnClientWrite(0);
92 }
93
94 virtual void DidClose(net::StreamListenSocket* socket) OVERRIDE {
95 SelfDestruct();
96 }
97
98 void OnClientRead(int result) {
99 if (result <= 0) {
100 SelfDestruct();
101 return;
102 }
103
104 accepted_socket_->Send(buffer_->data(), result);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100105 result = client_socket_->Read(
106 buffer_.get(),
107 kBufferSize,
108 base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100109 if (result != net::ERR_IO_PENDING)
110 OnClientRead(result);
111 }
112
113 void OnClientWrite(int result) {
114 if (result < 0)
115 SelfDestruct();
116
117 wire_buffer_->set_offset(wire_buffer_->offset() + result);
118
119 int remaining = wire_buffer_size_ - wire_buffer_->offset();
120 if (remaining == 0) {
121 if (pending_destruction_)
122 SelfDestruct();
123 return;
124 }
125
126
127 if (remaining > kBufferSize)
128 remaining = kBufferSize;
129
130 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(remaining);
131 memcpy(buffer->data(), wire_buffer_->data(), remaining);
132 result = client_socket_->Write(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100133 buffer.get(),
134 remaining,
135 base::Bind(&SocketPump::OnClientWrite, base::Unretained(this)));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100136
137 // Shrink buffer
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);
144 }
145
146 if (result != net::ERR_IO_PENDING)
147 OnClientWrite(result);
148 return;
149 }
150
151 void SelfDestruct() {
152 if (wire_buffer_->offset() != wire_buffer_size_) {
153 pending_destruction_ = true;
154 return;
155 }
156 delete this;
157 }
158
159 private:
160 scoped_ptr<net::StreamSocket> client_socket_;
161 scoped_refptr<net::StreamListenSocket> server_socket_;
162 scoped_refptr<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_;
168};
169
170} // namespace
171
172const char TetheringHandler::kDomain[] = "Tethering";
173
174class TetheringHandler::BoundSocket {
175 public:
176 BoundSocket(TetheringHandler* handler,
177 DevToolsHttpHandlerDelegate* delegate)
178 : handler_(handler),
179 delegate_(delegate),
180 socket_(new net::TCPServerSocket(NULL, net::NetLog::Source())),
181 port_(0) {
182 }
183
184 virtual ~BoundSocket() {
185 }
186
187 bool Listen(int port) {
188 port_ = port;
189 net::IPAddressNumber ip_number;
190 if (!net::ParseIPLiteralToNumber(kLocalhost, &ip_number))
191 return false;
192
193 net::IPEndPoint end_point(ip_number, port);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100194 int result = socket_->Listen(end_point, kListenBacklog);
195 if (result < 0)
196 return false;
197
198 net::IPEndPoint local_address;
199 result = socket_->GetLocalAddress(&local_address);
200 if (result < 0)
201 return false;
202
203 DoAccept();
204 return true;
205 }
206
207 private:
208 typedef std::map<net::IPEndPoint, net::StreamSocket*> AcceptedSocketsMap;
209
210 void DoAccept() {
211 while (true) {
212 int result = socket_->Accept(
213 &accept_socket_,
214 base::Bind(&BoundSocket::OnAccepted, base::Unretained(this)));
215 if (result == net::ERR_IO_PENDING)
216 break;
217 else
218 HandleAcceptResult(result);
219 }
220 }
221
222 void OnAccepted(int result) {
223 HandleAcceptResult(result);
224 if (result == net::OK)
225 DoAccept();
226 }
227
228 void HandleAcceptResult(int result) {
229 if (result != net::OK)
230 return;
231
232 SocketPump* pump = new SocketPump(delegate_, accept_socket_.release());
233 std::string name = pump->Init();
234 if (!name.empty())
235 handler_->Accepted(port_, name);
236 }
237
238 TetheringHandler* handler_;
239 DevToolsHttpHandlerDelegate* delegate_;
240 scoped_ptr<net::ServerSocket> socket_;
241 scoped_ptr<net::StreamSocket> accept_socket_;
242 int port_;
243};
244
245TetheringHandler::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)));
253}
254
255TetheringHandler::~TetheringHandler() {
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100256 STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
257 bound_sockets_.end());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100258}
259
260void 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);
265}
266
Ben Murdochbb1529c2013-08-08 10:24:53 +0100267static int GetPort(scoped_refptr<DevToolsProtocol::Command> command) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100268 base::DictionaryValue* params = command->params();
269 int port = 0;
270 if (!params || !params->GetInteger(kPortParam, &port) ||
271 port < kMinTetheringPort || port > kMaxTetheringPort)
272 return 0;
273 return port;
274}
275
Ben Murdochbb1529c2013-08-08 10:24:53 +0100276scoped_refptr<DevToolsProtocol::Response>
277TetheringHandler::OnBind(scoped_refptr<DevToolsProtocol::Command> command) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100278 int port = GetPort(command);
279 if (port == 0)
280 return command->InvalidParamResponse(kPortParam);
281
282 if (bound_sockets_.find(port) != bound_sockets_.end())
283 return command->InternalErrorResponse("Port already bound");
284
285 scoped_ptr<BoundSocket> bound_socket(new BoundSocket(this, delegate_));
286 if (!bound_socket->Listen(port))
287 return command->InternalErrorResponse("Could not bind port");
288
289 bound_sockets_[port] = bound_socket.release();
290 return command->SuccessResponse(NULL);
291}
292
Ben Murdochbb1529c2013-08-08 10:24:53 +0100293scoped_refptr<DevToolsProtocol::Response>
294TetheringHandler::OnUnbind(scoped_refptr<DevToolsProtocol::Command> command) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100295 int port = GetPort(command);
296 if (port == 0)
297 return command->InvalidParamResponse(kPortParam);
298
299 BoundSockets::iterator it = bound_sockets_.find(port);
300 if (it == bound_sockets_.end())
301 return command->InternalErrorResponse("Port is not bound");
302
303 delete it->second;
304 bound_sockets_.erase(it);
305 return command->SuccessResponse(NULL);
306}
307
308} // namespace content