- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / devtools / tethering_handler.cc
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.
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
22 namespace content {
23
24 namespace {
25
26 const char kTetheringBind[] = "Tethering.bind";
27 const char kTetheringUnbind[] = "Tethering.unbind";
28
29 const char kTetheringAccepted[] = "Tethering.accepted";
30
31 const char kPortParam[] = "port";
32 const char kConnectionIdParam[] = "connectionId";
33
34 const char kLocalhost[] = "127.0.0.1";
35
36 const int kListenBacklog = 5;
37 const int kBufferSize = 16 * 1024;
38
39 const int kMinTetheringPort = 5000;
40 const int kMaxTetheringPort = 10000;
41
42 class 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);
55     if (!server_socket_.get() || channel_name.empty())
56       SelfDestruct();
57     return channel_name;
58   }
59
60   virtual ~SocketPump() { }
61
62  private:
63   virtual void DidAccept(net::StreamListenSocket* server,
64                          scoped_ptr<net::StreamListenSocket> socket) OVERRIDE {
65     if (accepted_socket_.get())
66       return;
67
68     buffer_ = new net::IOBuffer(kBufferSize);
69     wire_buffer_ = new net::GrowableIOBuffer();
70     wire_buffer_->SetCapacity(kBufferSize);
71
72     accepted_socket_ = socket.Pass();
73     int result = client_socket_->Read(
74         buffer_.get(),
75         kBufferSize,
76         base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
77     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);
105     result = client_socket_->Read(
106         buffer_.get(),
107         kBufferSize,
108         base::Bind(&SocketPump::OnClientRead, base::Unretained(this)));
109     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(
133         buffer.get(),
134         remaining,
135         base::Bind(&SocketPump::OnClientWrite, base::Unretained(this)));
136
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_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_;
168 };
169
170 }  // namespace
171
172 const char TetheringHandler::kDomain[] = "Tethering";
173
174 class 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);
194     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
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)));
253 }
254
255 TetheringHandler::~TetheringHandler() {
256   STLDeleteContainerPairSecondPointers(bound_sockets_.begin(),
257                                        bound_sockets_.end());
258 }
259
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);
265 }
266
267 static int GetPort(scoped_refptr<DevToolsProtocol::Command> command) {
268   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
276 scoped_refptr<DevToolsProtocol::Response>
277 TetheringHandler::OnBind(scoped_refptr<DevToolsProtocol::Command> command) {
278   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
293 scoped_refptr<DevToolsProtocol::Response>
294 TetheringHandler::OnUnbind(scoped_refptr<DevToolsProtocol::Command> command) {
295   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