Home | History | Annotate | Download | only in sockets_tcp
      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.
      4 
      5 #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h"
      6 
      7 #include "content/public/common/socket_permission_request.h"
      8 #include "extensions/browser/api/socket/tcp_socket.h"
      9 #include "extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.h"
     10 #include "extensions/common/api/sockets/sockets_manifest_data.h"
     11 #include "net/base/net_errors.h"
     12 
     13 using extensions::ResumableTCPSocket;
     14 using extensions::core_api::sockets_tcp::SocketInfo;
     15 using extensions::core_api::sockets_tcp::SocketProperties;
     16 
     17 namespace {
     18 
     19 const char kSocketNotFoundError[] = "Socket not found";
     20 const char kPermissionError[] = "Does not have permission";
     21 
     22 linked_ptr<SocketInfo> CreateSocketInfo(int socket_id,
     23                                         ResumableTCPSocket* socket) {
     24   linked_ptr<SocketInfo> socket_info(new SocketInfo());
     25   // This represents what we know about the socket, and does not call through
     26   // to the system.
     27   socket_info->socket_id = socket_id;
     28   if (!socket->name().empty()) {
     29     socket_info->name.reset(new std::string(socket->name()));
     30   }
     31   socket_info->persistent = socket->persistent();
     32   if (socket->buffer_size() > 0) {
     33     socket_info->buffer_size.reset(new int(socket->buffer_size()));
     34   }
     35   socket_info->paused = socket->paused();
     36   socket_info->connected = socket->IsConnected();
     37 
     38   // Grab the local address as known by the OS.
     39   net::IPEndPoint localAddress;
     40   if (socket->GetLocalAddress(&localAddress)) {
     41     socket_info->local_address.reset(
     42         new std::string(localAddress.ToStringWithoutPort()));
     43     socket_info->local_port.reset(new int(localAddress.port()));
     44   }
     45 
     46   // Grab the peer address as known by the OS. This and the call below will
     47   // always succeed while the socket is connected, even if the socket has
     48   // been remotely closed by the peer; only reading the socket will reveal
     49   // that it should be closed locally.
     50   net::IPEndPoint peerAddress;
     51   if (socket->GetPeerAddress(&peerAddress)) {
     52     socket_info->peer_address.reset(
     53         new std::string(peerAddress.ToStringWithoutPort()));
     54     socket_info->peer_port.reset(new int(peerAddress.port()));
     55   }
     56 
     57   return socket_info;
     58 }
     59 
     60 void SetSocketProperties(ResumableTCPSocket* socket,
     61                          SocketProperties* properties) {
     62   if (properties->name.get()) {
     63     socket->set_name(*properties->name.get());
     64   }
     65   if (properties->persistent.get()) {
     66     socket->set_persistent(*properties->persistent.get());
     67   }
     68   if (properties->buffer_size.get()) {
     69     // buffer size is validated when issuing the actual Recv operation
     70     // on the socket.
     71     socket->set_buffer_size(*properties->buffer_size.get());
     72   }
     73 }
     74 
     75 }  // namespace
     76 
     77 namespace extensions {
     78 namespace core_api {
     79 
     80 using content::SocketPermissionRequest;
     81 
     82 TCPSocketAsyncApiFunction::~TCPSocketAsyncApiFunction() {}
     83 
     84 scoped_ptr<SocketResourceManagerInterface>
     85 TCPSocketAsyncApiFunction::CreateSocketResourceManager() {
     86   return scoped_ptr<SocketResourceManagerInterface>(
     87              new SocketResourceManager<ResumableTCPSocket>()).Pass();
     88 }
     89 
     90 ResumableTCPSocket* TCPSocketAsyncApiFunction::GetTcpSocket(int socket_id) {
     91   return static_cast<ResumableTCPSocket*>(GetSocket(socket_id));
     92 }
     93 
     94 TCPSocketExtensionWithDnsLookupFunction::
     95     ~TCPSocketExtensionWithDnsLookupFunction() {}
     96 
     97 scoped_ptr<SocketResourceManagerInterface>
     98 TCPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() {
     99   return scoped_ptr<SocketResourceManagerInterface>(
    100              new SocketResourceManager<ResumableTCPSocket>()).Pass();
    101 }
    102 
    103 ResumableTCPSocket* TCPSocketExtensionWithDnsLookupFunction::GetTcpSocket(
    104     int socket_id) {
    105   return static_cast<ResumableTCPSocket*>(GetSocket(socket_id));
    106 }
    107 
    108 SocketsTcpCreateFunction::SocketsTcpCreateFunction() {}
    109 
    110 SocketsTcpCreateFunction::~SocketsTcpCreateFunction() {}
    111 
    112 bool SocketsTcpCreateFunction::Prepare() {
    113   params_ = sockets_tcp::Create::Params::Create(*args_);
    114   EXTENSION_FUNCTION_VALIDATE(params_.get());
    115   return true;
    116 }
    117 
    118 void SocketsTcpCreateFunction::Work() {
    119   ResumableTCPSocket* socket = new ResumableTCPSocket(extension_->id());
    120 
    121   sockets_tcp::SocketProperties* properties = params_.get()->properties.get();
    122   if (properties) {
    123     SetSocketProperties(socket, properties);
    124   }
    125 
    126   sockets_tcp::CreateInfo create_info;
    127   create_info.socket_id = AddSocket(socket);
    128   results_ = sockets_tcp::Create::Results::Create(create_info);
    129 }
    130 
    131 SocketsTcpUpdateFunction::SocketsTcpUpdateFunction() {}
    132 
    133 SocketsTcpUpdateFunction::~SocketsTcpUpdateFunction() {}
    134 
    135 bool SocketsTcpUpdateFunction::Prepare() {
    136   params_ = sockets_tcp::Update::Params::Create(*args_);
    137   EXTENSION_FUNCTION_VALIDATE(params_.get());
    138   return true;
    139 }
    140 
    141 void SocketsTcpUpdateFunction::Work() {
    142   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    143   if (!socket) {
    144     error_ = kSocketNotFoundError;
    145     return;
    146   }
    147 
    148   SetSocketProperties(socket, &params_.get()->properties);
    149   results_ = sockets_tcp::Update::Results::Create();
    150 }
    151 
    152 SocketsTcpSetPausedFunction::SocketsTcpSetPausedFunction()
    153     : socket_event_dispatcher_(NULL) {}
    154 
    155 SocketsTcpSetPausedFunction::~SocketsTcpSetPausedFunction() {}
    156 
    157 bool SocketsTcpSetPausedFunction::Prepare() {
    158   params_ = core_api::sockets_tcp::SetPaused::Params::Create(*args_);
    159   EXTENSION_FUNCTION_VALIDATE(params_.get());
    160 
    161   socket_event_dispatcher_ = TCPSocketEventDispatcher::Get(browser_context());
    162   DCHECK(socket_event_dispatcher_)
    163       << "There is no socket event dispatcher. "
    164          "If this assertion is failing during a test, then it is likely that "
    165          "TestExtensionSystem is failing to provide an instance of "
    166          "TCPSocketEventDispatcher.";
    167   return socket_event_dispatcher_ != NULL;
    168 }
    169 
    170 void SocketsTcpSetPausedFunction::Work() {
    171   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    172   if (!socket) {
    173     error_ = kSocketNotFoundError;
    174     return;
    175   }
    176 
    177   if (socket->paused() != params_->paused) {
    178     socket->set_paused(params_->paused);
    179     if (socket->IsConnected() && !params_->paused) {
    180       socket_event_dispatcher_->OnSocketResume(extension_->id(),
    181                                                params_->socket_id);
    182     }
    183   }
    184 
    185   results_ = sockets_tcp::SetPaused::Results::Create();
    186 }
    187 
    188 SocketsTcpSetKeepAliveFunction::SocketsTcpSetKeepAliveFunction() {}
    189 
    190 SocketsTcpSetKeepAliveFunction::~SocketsTcpSetKeepAliveFunction() {}
    191 
    192 bool SocketsTcpSetKeepAliveFunction::Prepare() {
    193   params_ = core_api::sockets_tcp::SetKeepAlive::Params::Create(*args_);
    194   EXTENSION_FUNCTION_VALIDATE(params_.get());
    195   return true;
    196 }
    197 
    198 void SocketsTcpSetKeepAliveFunction::Work() {
    199   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    200   if (!socket) {
    201     error_ = kSocketNotFoundError;
    202     return;
    203   }
    204 
    205   int delay = params_->delay ? *params_->delay.get() : 0;
    206 
    207   bool success = socket->SetKeepAlive(params_->enable, delay);
    208   int net_result = (success ? net::OK : net::ERR_FAILED);
    209   if (net_result != net::OK)
    210     error_ = net::ErrorToString(net_result);
    211   results_ = sockets_tcp::SetKeepAlive::Results::Create(net_result);
    212 }
    213 
    214 SocketsTcpSetNoDelayFunction::SocketsTcpSetNoDelayFunction() {}
    215 
    216 SocketsTcpSetNoDelayFunction::~SocketsTcpSetNoDelayFunction() {}
    217 
    218 bool SocketsTcpSetNoDelayFunction::Prepare() {
    219   params_ = core_api::sockets_tcp::SetNoDelay::Params::Create(*args_);
    220   EXTENSION_FUNCTION_VALIDATE(params_.get());
    221   return true;
    222 }
    223 
    224 void SocketsTcpSetNoDelayFunction::Work() {
    225   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    226   if (!socket) {
    227     error_ = kSocketNotFoundError;
    228     return;
    229   }
    230 
    231   bool success = socket->SetNoDelay(params_->no_delay);
    232   int net_result = (success ? net::OK : net::ERR_FAILED);
    233   if (net_result != net::OK)
    234     error_ = net::ErrorToString(net_result);
    235   results_ = sockets_tcp::SetNoDelay::Results::Create(net_result);
    236 }
    237 
    238 SocketsTcpConnectFunction::SocketsTcpConnectFunction()
    239     : socket_event_dispatcher_(NULL) {}
    240 
    241 SocketsTcpConnectFunction::~SocketsTcpConnectFunction() {}
    242 
    243 bool SocketsTcpConnectFunction::Prepare() {
    244   params_ = sockets_tcp::Connect::Params::Create(*args_);
    245   EXTENSION_FUNCTION_VALIDATE(params_.get());
    246 
    247   socket_event_dispatcher_ = TCPSocketEventDispatcher::Get(browser_context());
    248   DCHECK(socket_event_dispatcher_)
    249       << "There is no socket event dispatcher. "
    250          "If this assertion is failing during a test, then it is likely that "
    251          "TestExtensionSystem is failing to provide an instance of "
    252          "TCPSocketEventDispatcher.";
    253   return socket_event_dispatcher_ != NULL;
    254 }
    255 
    256 void SocketsTcpConnectFunction::AsyncWorkStart() {
    257   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    258   if (!socket) {
    259     error_ = kSocketNotFoundError;
    260     AsyncWorkCompleted();
    261     return;
    262   }
    263 
    264   content::SocketPermissionRequest param(SocketPermissionRequest::TCP_CONNECT,
    265                                          params_->peer_address,
    266                                          params_->peer_port);
    267   if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
    268     error_ = kPermissionError;
    269     AsyncWorkCompleted();
    270     return;
    271   }
    272 
    273   StartDnsLookup(params_->peer_address);
    274 }
    275 
    276 void SocketsTcpConnectFunction::AfterDnsLookup(int lookup_result) {
    277   if (lookup_result == net::OK) {
    278     StartConnect();
    279   } else {
    280     OnCompleted(lookup_result);
    281   }
    282 }
    283 
    284 void SocketsTcpConnectFunction::StartConnect() {
    285   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    286   if (!socket) {
    287     error_ = kSocketNotFoundError;
    288     AsyncWorkCompleted();
    289     return;
    290   }
    291 
    292   socket->Connect(resolved_address_,
    293                   params_->peer_port,
    294                   base::Bind(&SocketsTcpConnectFunction::OnCompleted, this));
    295 }
    296 
    297 void SocketsTcpConnectFunction::OnCompleted(int net_result) {
    298   if (net_result == net::OK) {
    299     socket_event_dispatcher_->OnSocketConnect(extension_->id(),
    300                                               params_->socket_id);
    301   }
    302 
    303   if (net_result != net::OK)
    304     error_ = net::ErrorToString(net_result);
    305   results_ = sockets_tcp::Connect::Results::Create(net_result);
    306   AsyncWorkCompleted();
    307 }
    308 
    309 SocketsTcpDisconnectFunction::SocketsTcpDisconnectFunction() {}
    310 
    311 SocketsTcpDisconnectFunction::~SocketsTcpDisconnectFunction() {}
    312 
    313 bool SocketsTcpDisconnectFunction::Prepare() {
    314   params_ = sockets_tcp::Disconnect::Params::Create(*args_);
    315   EXTENSION_FUNCTION_VALIDATE(params_.get());
    316   return true;
    317 }
    318 
    319 void SocketsTcpDisconnectFunction::Work() {
    320   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    321   if (!socket) {
    322     error_ = kSocketNotFoundError;
    323     return;
    324   }
    325 
    326   socket->Disconnect();
    327   results_ = sockets_tcp::Disconnect::Results::Create();
    328 }
    329 
    330 SocketsTcpSendFunction::SocketsTcpSendFunction() : io_buffer_size_(0) {}
    331 
    332 SocketsTcpSendFunction::~SocketsTcpSendFunction() {}
    333 
    334 bool SocketsTcpSendFunction::Prepare() {
    335   params_ = sockets_tcp::Send::Params::Create(*args_);
    336   EXTENSION_FUNCTION_VALIDATE(params_.get());
    337   io_buffer_size_ = params_->data.size();
    338   io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
    339   return true;
    340 }
    341 
    342 void SocketsTcpSendFunction::AsyncWorkStart() {
    343   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    344   if (!socket) {
    345     error_ = kSocketNotFoundError;
    346     AsyncWorkCompleted();
    347     return;
    348   }
    349 
    350   socket->Write(io_buffer_,
    351                 io_buffer_size_,
    352                 base::Bind(&SocketsTcpSendFunction::OnCompleted, this));
    353 }
    354 
    355 void SocketsTcpSendFunction::OnCompleted(int net_result) {
    356   if (net_result >= net::OK) {
    357     SetSendResult(net::OK, net_result);
    358   } else {
    359     SetSendResult(net_result, -1);
    360   }
    361 }
    362 
    363 void SocketsTcpSendFunction::SetSendResult(int net_result, int bytes_sent) {
    364   CHECK(net_result <= net::OK) << "Network status code must be <= net::OK";
    365 
    366   sockets_tcp::SendInfo send_info;
    367   send_info.result_code = net_result;
    368   if (net_result == net::OK) {
    369     send_info.bytes_sent.reset(new int(bytes_sent));
    370   }
    371 
    372   if (net_result != net::OK)
    373     error_ = net::ErrorToString(net_result);
    374   results_ = sockets_tcp::Send::Results::Create(send_info);
    375   AsyncWorkCompleted();
    376 }
    377 
    378 SocketsTcpCloseFunction::SocketsTcpCloseFunction() {}
    379 
    380 SocketsTcpCloseFunction::~SocketsTcpCloseFunction() {}
    381 
    382 bool SocketsTcpCloseFunction::Prepare() {
    383   params_ = sockets_tcp::Close::Params::Create(*args_);
    384   EXTENSION_FUNCTION_VALIDATE(params_.get());
    385   return true;
    386 }
    387 
    388 void SocketsTcpCloseFunction::Work() {
    389   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    390   if (!socket) {
    391     error_ = kSocketNotFoundError;
    392     return;
    393   }
    394 
    395   RemoveSocket(params_->socket_id);
    396   results_ = sockets_tcp::Close::Results::Create();
    397 }
    398 
    399 SocketsTcpGetInfoFunction::SocketsTcpGetInfoFunction() {}
    400 
    401 SocketsTcpGetInfoFunction::~SocketsTcpGetInfoFunction() {}
    402 
    403 bool SocketsTcpGetInfoFunction::Prepare() {
    404   params_ = sockets_tcp::GetInfo::Params::Create(*args_);
    405   EXTENSION_FUNCTION_VALIDATE(params_.get());
    406   return true;
    407 }
    408 
    409 void SocketsTcpGetInfoFunction::Work() {
    410   ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id);
    411   if (!socket) {
    412     error_ = kSocketNotFoundError;
    413     return;
    414   }
    415 
    416   linked_ptr<sockets_tcp::SocketInfo> socket_info =
    417       CreateSocketInfo(params_->socket_id, socket);
    418   results_ = sockets_tcp::GetInfo::Results::Create(*socket_info);
    419 }
    420 
    421 SocketsTcpGetSocketsFunction::SocketsTcpGetSocketsFunction() {}
    422 
    423 SocketsTcpGetSocketsFunction::~SocketsTcpGetSocketsFunction() {}
    424 
    425 bool SocketsTcpGetSocketsFunction::Prepare() { return true; }
    426 
    427 void SocketsTcpGetSocketsFunction::Work() {
    428   std::vector<linked_ptr<sockets_tcp::SocketInfo> > socket_infos;
    429   base::hash_set<int>* resource_ids = GetSocketIds();
    430   if (resource_ids != NULL) {
    431     for (base::hash_set<int>::iterator it = resource_ids->begin();
    432          it != resource_ids->end();
    433          ++it) {
    434       int socket_id = *it;
    435       ResumableTCPSocket* socket = GetTcpSocket(socket_id);
    436       if (socket) {
    437         socket_infos.push_back(CreateSocketInfo(socket_id, socket));
    438       }
    439     }
    440   }
    441   results_ = sockets_tcp::GetSockets::Results::Create(socket_infos);
    442 }
    443 
    444 }  // namespace core_api
    445 }  // namespace extensions
    446