Home | History | Annotate | Download | only in sockets_udp
      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_udp/sockets_udp_api.h"
      6 
      7 #include "content/public/common/socket_permission_request.h"
      8 #include "extensions/browser/api/socket/udp_socket.h"
      9 #include "extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.h"
     10 #include "extensions/common/api/sockets/sockets_manifest_data.h"
     11 #include "net/base/net_errors.h"
     12 
     13 namespace extensions {
     14 namespace core_api {
     15 
     16 using content::SocketPermissionRequest;
     17 
     18 const char kSocketNotFoundError[] = "Socket not found";
     19 const char kPermissionError[] = "App does not have permission";
     20 const char kWildcardAddress[] = "*";
     21 const int kWildcardPort = 0;
     22 
     23 UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {}
     24 
     25 scoped_ptr<SocketResourceManagerInterface>
     26 UDPSocketAsyncApiFunction::CreateSocketResourceManager() {
     27   return scoped_ptr<SocketResourceManagerInterface>(
     28              new SocketResourceManager<ResumableUDPSocket>()).Pass();
     29 }
     30 
     31 ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) {
     32   return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
     33 }
     34 
     35 UDPSocketExtensionWithDnsLookupFunction::
     36     ~UDPSocketExtensionWithDnsLookupFunction() {}
     37 
     38 scoped_ptr<SocketResourceManagerInterface>
     39 UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() {
     40   return scoped_ptr<SocketResourceManagerInterface>(
     41              new SocketResourceManager<ResumableUDPSocket>()).Pass();
     42 }
     43 
     44 ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket(
     45     int socket_id) {
     46   return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
     47 }
     48 
     49 linked_ptr<sockets_udp::SocketInfo> CreateSocketInfo(
     50     int socket_id,
     51     ResumableUDPSocket* socket) {
     52   linked_ptr<sockets_udp::SocketInfo> socket_info(
     53       new sockets_udp::SocketInfo());
     54   // This represents what we know about the socket, and does not call through
     55   // to the system.
     56   socket_info->socket_id = socket_id;
     57   if (!socket->name().empty()) {
     58     socket_info->name.reset(new std::string(socket->name()));
     59   }
     60   socket_info->persistent = socket->persistent();
     61   if (socket->buffer_size() > 0) {
     62     socket_info->buffer_size.reset(new int(socket->buffer_size()));
     63   }
     64   socket_info->paused = socket->paused();
     65 
     66   // Grab the local address as known by the OS.
     67   net::IPEndPoint localAddress;
     68   if (socket->GetLocalAddress(&localAddress)) {
     69     socket_info->local_address.reset(
     70         new std::string(localAddress.ToStringWithoutPort()));
     71     socket_info->local_port.reset(new int(localAddress.port()));
     72   }
     73 
     74   return socket_info;
     75 }
     76 
     77 void SetSocketProperties(ResumableUDPSocket* socket,
     78                          sockets_udp::SocketProperties* properties) {
     79   if (properties->name.get()) {
     80     socket->set_name(*properties->name.get());
     81   }
     82   if (properties->persistent.get()) {
     83     socket->set_persistent(*properties->persistent.get());
     84   }
     85   if (properties->buffer_size.get()) {
     86     socket->set_buffer_size(*properties->buffer_size.get());
     87   }
     88 }
     89 
     90 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {}
     91 
     92 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {}
     93 
     94 bool SocketsUdpCreateFunction::Prepare() {
     95   params_ = sockets_udp::Create::Params::Create(*args_);
     96   EXTENSION_FUNCTION_VALIDATE(params_.get());
     97   return true;
     98 }
     99 
    100 void SocketsUdpCreateFunction::Work() {
    101   ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id());
    102 
    103   sockets_udp::SocketProperties* properties = params_.get()->properties.get();
    104   if (properties) {
    105     SetSocketProperties(socket, properties);
    106   }
    107 
    108   sockets_udp::CreateInfo create_info;
    109   create_info.socket_id = AddSocket(socket);
    110   results_ = sockets_udp::Create::Results::Create(create_info);
    111 }
    112 
    113 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {}
    114 
    115 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {}
    116 
    117 bool SocketsUdpUpdateFunction::Prepare() {
    118   params_ = sockets_udp::Update::Params::Create(*args_);
    119   EXTENSION_FUNCTION_VALIDATE(params_.get());
    120   return true;
    121 }
    122 
    123 void SocketsUdpUpdateFunction::Work() {
    124   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    125   if (!socket) {
    126     error_ = kSocketNotFoundError;
    127     return;
    128   }
    129 
    130   SetSocketProperties(socket, &params_.get()->properties);
    131   results_ = sockets_udp::Update::Results::Create();
    132 }
    133 
    134 SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction()
    135     : socket_event_dispatcher_(NULL) {}
    136 
    137 SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {}
    138 
    139 bool SocketsUdpSetPausedFunction::Prepare() {
    140   params_ = core_api::sockets_udp::SetPaused::Params::Create(*args_);
    141   EXTENSION_FUNCTION_VALIDATE(params_.get());
    142 
    143   socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context());
    144   DCHECK(socket_event_dispatcher_)
    145       << "There is no socket event dispatcher. "
    146          "If this assertion is failing during a test, then it is likely that "
    147          "TestExtensionSystem is failing to provide an instance of "
    148          "UDPSocketEventDispatcher.";
    149   return socket_event_dispatcher_ != NULL;
    150 }
    151 
    152 void SocketsUdpSetPausedFunction::Work() {
    153   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    154   if (!socket) {
    155     error_ = kSocketNotFoundError;
    156     return;
    157   }
    158 
    159   if (socket->paused() != params_->paused) {
    160     socket->set_paused(params_->paused);
    161     if (socket->IsBound() && !params_->paused) {
    162       socket_event_dispatcher_->OnSocketResume(extension_->id(),
    163                                                params_->socket_id);
    164     }
    165   }
    166 
    167   results_ = sockets_udp::SetPaused::Results::Create();
    168 }
    169 
    170 SocketsUdpBindFunction::SocketsUdpBindFunction()
    171     : socket_event_dispatcher_(NULL) {}
    172 
    173 SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
    174 
    175 bool SocketsUdpBindFunction::Prepare() {
    176   params_ = sockets_udp::Bind::Params::Create(*args_);
    177   EXTENSION_FUNCTION_VALIDATE(params_.get());
    178 
    179   socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context());
    180   DCHECK(socket_event_dispatcher_)
    181       << "There is no socket event dispatcher. "
    182          "If this assertion is failing during a test, then it is likely that "
    183          "TestExtensionSystem is failing to provide an instance of "
    184          "UDPSocketEventDispatcher.";
    185   return socket_event_dispatcher_ != NULL;
    186 }
    187 
    188 void SocketsUdpBindFunction::Work() {
    189   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    190   if (!socket) {
    191     error_ = kSocketNotFoundError;
    192     return;
    193   }
    194 
    195   content::SocketPermissionRequest param(
    196       SocketPermissionRequest::UDP_BIND, params_->address, params_->port);
    197   if (!SocketsManifestData::CheckRequest(extension(), param)) {
    198     error_ = kPermissionError;
    199     return;
    200   }
    201 
    202   int net_result = socket->Bind(params_->address, params_->port);
    203   if (net_result == net::OK) {
    204     socket_event_dispatcher_->OnSocketBind(extension_->id(),
    205                                            params_->socket_id);
    206   }
    207 
    208   if (net_result != net::OK)
    209     error_ = net::ErrorToString(net_result);
    210   results_ = sockets_udp::Bind::Results::Create(net_result);
    211 }
    212 
    213 SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {}
    214 
    215 SocketsUdpSendFunction::~SocketsUdpSendFunction() {}
    216 
    217 bool SocketsUdpSendFunction::Prepare() {
    218   params_ = sockets_udp::Send::Params::Create(*args_);
    219   EXTENSION_FUNCTION_VALIDATE(params_.get());
    220   io_buffer_size_ = params_->data.size();
    221   io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
    222 
    223   return true;
    224 }
    225 
    226 void SocketsUdpSendFunction::AsyncWorkStart() {
    227   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    228   if (!socket) {
    229     error_ = kSocketNotFoundError;
    230     AsyncWorkCompleted();
    231     return;
    232   }
    233 
    234   content::SocketPermissionRequest param(
    235       SocketPermissionRequest::UDP_SEND_TO, params_->address, params_->port);
    236   if (!SocketsManifestData::CheckRequest(extension(), param)) {
    237     error_ = kPermissionError;
    238     AsyncWorkCompleted();
    239     return;
    240   }
    241 
    242   StartDnsLookup(params_->address);
    243 }
    244 
    245 void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) {
    246   if (lookup_result == net::OK) {
    247     StartSendTo();
    248   } else {
    249     SetSendResult(lookup_result, -1);
    250   }
    251 }
    252 
    253 void SocketsUdpSendFunction::StartSendTo() {
    254   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    255   if (!socket) {
    256     error_ = kSocketNotFoundError;
    257     AsyncWorkCompleted();
    258     return;
    259   }
    260 
    261   socket->SendTo(io_buffer_,
    262                  io_buffer_size_,
    263                  resolved_address_,
    264                  params_->port,
    265                  base::Bind(&SocketsUdpSendFunction::OnCompleted, this));
    266 }
    267 
    268 void SocketsUdpSendFunction::OnCompleted(int net_result) {
    269   if (net_result >= net::OK) {
    270     SetSendResult(net::OK, net_result);
    271   } else {
    272     SetSendResult(net_result, -1);
    273   }
    274 }
    275 
    276 void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) {
    277   CHECK(net_result <= net::OK) << "Network status code must be < 0";
    278 
    279   sockets_udp::SendInfo send_info;
    280   send_info.result_code = net_result;
    281   if (net_result == net::OK) {
    282     send_info.bytes_sent.reset(new int(bytes_sent));
    283   }
    284 
    285   if (net_result != net::OK)
    286     error_ = net::ErrorToString(net_result);
    287   results_ = sockets_udp::Send::Results::Create(send_info);
    288   AsyncWorkCompleted();
    289 }
    290 
    291 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {}
    292 
    293 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {}
    294 
    295 bool SocketsUdpCloseFunction::Prepare() {
    296   params_ = sockets_udp::Close::Params::Create(*args_);
    297   EXTENSION_FUNCTION_VALIDATE(params_.get());
    298   return true;
    299 }
    300 
    301 void SocketsUdpCloseFunction::Work() {
    302   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    303   if (!socket) {
    304     error_ = kSocketNotFoundError;
    305     return;
    306   }
    307 
    308   socket->Disconnect();
    309   RemoveSocket(params_->socket_id);
    310   results_ = sockets_udp::Close::Results::Create();
    311 }
    312 
    313 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {}
    314 
    315 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {}
    316 
    317 bool SocketsUdpGetInfoFunction::Prepare() {
    318   params_ = sockets_udp::GetInfo::Params::Create(*args_);
    319   EXTENSION_FUNCTION_VALIDATE(params_.get());
    320   return true;
    321 }
    322 
    323 void SocketsUdpGetInfoFunction::Work() {
    324   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    325   if (!socket) {
    326     error_ = kSocketNotFoundError;
    327     return;
    328   }
    329 
    330   linked_ptr<sockets_udp::SocketInfo> socket_info =
    331       CreateSocketInfo(params_->socket_id, socket);
    332   results_ = sockets_udp::GetInfo::Results::Create(*socket_info);
    333 }
    334 
    335 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {}
    336 
    337 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {}
    338 
    339 bool SocketsUdpGetSocketsFunction::Prepare() { return true; }
    340 
    341 void SocketsUdpGetSocketsFunction::Work() {
    342   std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos;
    343   base::hash_set<int>* resource_ids = GetSocketIds();
    344   if (resource_ids != NULL) {
    345     for (base::hash_set<int>::iterator it = resource_ids->begin();
    346          it != resource_ids->end();
    347          ++it) {
    348       int socket_id = *it;
    349       ResumableUDPSocket* socket = GetUdpSocket(socket_id);
    350       if (socket) {
    351         socket_infos.push_back(CreateSocketInfo(socket_id, socket));
    352       }
    353     }
    354   }
    355   results_ = sockets_udp::GetSockets::Results::Create(socket_infos);
    356 }
    357 
    358 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {}
    359 
    360 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {}
    361 
    362 bool SocketsUdpJoinGroupFunction::Prepare() {
    363   params_ = sockets_udp::JoinGroup::Params::Create(*args_);
    364   EXTENSION_FUNCTION_VALIDATE(params_.get());
    365   return true;
    366 }
    367 
    368 void SocketsUdpJoinGroupFunction::Work() {
    369   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    370   if (!socket) {
    371     error_ = kSocketNotFoundError;
    372     return;
    373   }
    374 
    375   content::SocketPermissionRequest param(
    376       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
    377       kWildcardAddress,
    378       kWildcardPort);
    379   if (!SocketsManifestData::CheckRequest(extension(), param)) {
    380     error_ = kPermissionError;
    381     return;
    382   }
    383 
    384   int net_result = socket->JoinGroup(params_->address);
    385   if (net_result != net::OK)
    386     error_ = net::ErrorToString(net_result);
    387   results_ = sockets_udp::JoinGroup::Results::Create(net_result);
    388 }
    389 
    390 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {}
    391 
    392 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {}
    393 
    394 bool SocketsUdpLeaveGroupFunction::Prepare() {
    395   params_ = core_api::sockets_udp::LeaveGroup::Params::Create(*args_);
    396   EXTENSION_FUNCTION_VALIDATE(params_.get());
    397   return true;
    398 }
    399 
    400 void SocketsUdpLeaveGroupFunction::Work() {
    401   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    402   if (!socket) {
    403     error_ = kSocketNotFoundError;
    404     return;
    405   }
    406 
    407   content::SocketPermissionRequest param(
    408       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
    409       kWildcardAddress,
    410       kWildcardPort);
    411   if (!SocketsManifestData::CheckRequest(extension(), param)) {
    412     error_ = kPermissionError;
    413     return;
    414   }
    415 
    416   int net_result = socket->LeaveGroup(params_->address);
    417   if (net_result != net::OK)
    418     error_ = net::ErrorToString(net_result);
    419   results_ = sockets_udp::LeaveGroup::Results::Create(net_result);
    420 }
    421 
    422 SocketsUdpSetMulticastTimeToLiveFunction::
    423     SocketsUdpSetMulticastTimeToLiveFunction() {}
    424 
    425 SocketsUdpSetMulticastTimeToLiveFunction::
    426     ~SocketsUdpSetMulticastTimeToLiveFunction() {}
    427 
    428 bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() {
    429   params_ =
    430       core_api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_);
    431   EXTENSION_FUNCTION_VALIDATE(params_.get());
    432   return true;
    433 }
    434 
    435 void SocketsUdpSetMulticastTimeToLiveFunction::Work() {
    436   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    437   if (!socket) {
    438     error_ = kSocketNotFoundError;
    439     return;
    440   }
    441 
    442   int net_result = socket->SetMulticastTimeToLive(params_->ttl);
    443   if (net_result != net::OK)
    444     error_ = net::ErrorToString(net_result);
    445   results_ = sockets_udp::SetMulticastTimeToLive::Results::Create(net_result);
    446 }
    447 
    448 SocketsUdpSetMulticastLoopbackModeFunction::
    449     SocketsUdpSetMulticastLoopbackModeFunction() {}
    450 
    451 SocketsUdpSetMulticastLoopbackModeFunction::
    452     ~SocketsUdpSetMulticastLoopbackModeFunction() {}
    453 
    454 bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() {
    455   params_ =
    456       core_api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_);
    457   EXTENSION_FUNCTION_VALIDATE(params_.get());
    458   return true;
    459 }
    460 
    461 void SocketsUdpSetMulticastLoopbackModeFunction::Work() {
    462   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    463   if (!socket) {
    464     error_ = kSocketNotFoundError;
    465     return;
    466   }
    467 
    468   int net_result = socket->SetMulticastLoopbackMode(params_->enabled);
    469   if (net_result != net::OK)
    470     error_ = net::ErrorToString(net_result);
    471   results_ = sockets_udp::SetMulticastLoopbackMode::Results::Create(net_result);
    472 }
    473 
    474 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {}
    475 
    476 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {}
    477 
    478 bool SocketsUdpGetJoinedGroupsFunction::Prepare() {
    479   params_ = core_api::sockets_udp::GetJoinedGroups::Params::Create(*args_);
    480   EXTENSION_FUNCTION_VALIDATE(params_.get());
    481   return true;
    482 }
    483 
    484 void SocketsUdpGetJoinedGroupsFunction::Work() {
    485   ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
    486   if (!socket) {
    487     error_ = kSocketNotFoundError;
    488     return;
    489   }
    490 
    491   content::SocketPermissionRequest param(
    492       SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
    493       kWildcardAddress,
    494       kWildcardPort);
    495   if (!SocketsManifestData::CheckRequest(extension(), param)) {
    496     error_ = kPermissionError;
    497     return;
    498   }
    499 
    500   const std::vector<std::string>& groups = socket->GetJoinedGroups();
    501   results_ = sockets_udp::GetJoinedGroups::Results::Create(groups);
    502 }
    503 
    504 }  // namespace core_api
    505 }  // namespace extensions
    506