Home | History | Annotate | Download | only in devtools
      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_ && 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
    309