root/extensions/browser/api/sockets_udp/sockets_udp_api.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CreateSocketResourceManager
  2. GetUdpSocket
  3. UDPSocketExtensionWithDnsLookupFunction
  4. CreateSocketResourceManager
  5. GetUdpSocket
  6. CreateSocketInfo
  7. SetSocketProperties
  8. Prepare
  9. Work
  10. Prepare
  11. Work
  12. Prepare
  13. Work
  14. Prepare
  15. Work
  16. Prepare
  17. AsyncWorkStart
  18. AfterDnsLookup
  19. StartSendTo
  20. OnCompleted
  21. SetSendResult
  22. Prepare
  23. Work
  24. Prepare
  25. Work
  26. Prepare
  27. Work
  28. Prepare
  29. Work
  30. Prepare
  31. Work
  32. SocketsUdpSetMulticastTimeToLiveFunction
  33. SocketsUdpSetMulticastTimeToLiveFunction
  34. Prepare
  35. Work
  36. SocketsUdpSetMulticastLoopbackModeFunction
  37. SocketsUdpSetMulticastLoopbackModeFunction
  38. Prepare
  39. Work
  40. Prepare
  41. Work

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/browser/api/sockets_udp/sockets_udp_api.h"

#include "content/public/common/socket_permission_request.h"
#include "extensions/browser/api/socket/udp_socket.h"
#include "extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.h"
#include "extensions/common/api/sockets/sockets_manifest_data.h"
#include "net/base/net_errors.h"

namespace extensions {
namespace core_api {

using content::SocketPermissionRequest;

const char kSocketNotFoundError[] = "Socket not found";
const char kPermissionError[] = "App does not have permission";
const char kWildcardAddress[] = "*";
const int kWildcardPort = 0;

UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {}

scoped_ptr<SocketResourceManagerInterface>
UDPSocketAsyncApiFunction::CreateSocketResourceManager() {
  return scoped_ptr<SocketResourceManagerInterface>(
             new SocketResourceManager<ResumableUDPSocket>()).Pass();
}

ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) {
  return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
}

UDPSocketExtensionWithDnsLookupFunction::
    ~UDPSocketExtensionWithDnsLookupFunction() {}

scoped_ptr<SocketResourceManagerInterface>
UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() {
  return scoped_ptr<SocketResourceManagerInterface>(
             new SocketResourceManager<ResumableUDPSocket>()).Pass();
}

ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket(
    int socket_id) {
  return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
}

linked_ptr<sockets_udp::SocketInfo> CreateSocketInfo(
    int socket_id,
    ResumableUDPSocket* socket) {
  linked_ptr<sockets_udp::SocketInfo> socket_info(
      new sockets_udp::SocketInfo());
  // This represents what we know about the socket, and does not call through
  // to the system.
  socket_info->socket_id = socket_id;
  if (!socket->name().empty()) {
    socket_info->name.reset(new std::string(socket->name()));
  }
  socket_info->persistent = socket->persistent();
  if (socket->buffer_size() > 0) {
    socket_info->buffer_size.reset(new int(socket->buffer_size()));
  }
  socket_info->paused = socket->paused();

  // Grab the local address as known by the OS.
  net::IPEndPoint localAddress;
  if (socket->GetLocalAddress(&localAddress)) {
    socket_info->local_address.reset(
        new std::string(localAddress.ToStringWithoutPort()));
    socket_info->local_port.reset(new int(localAddress.port()));
  }

  return socket_info;
}

void SetSocketProperties(ResumableUDPSocket* socket,
                         sockets_udp::SocketProperties* properties) {
  if (properties->name.get()) {
    socket->set_name(*properties->name.get());
  }
  if (properties->persistent.get()) {
    socket->set_persistent(*properties->persistent.get());
  }
  if (properties->buffer_size.get()) {
    socket->set_buffer_size(*properties->buffer_size.get());
  }
}

SocketsUdpCreateFunction::SocketsUdpCreateFunction() {}

SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {}

bool SocketsUdpCreateFunction::Prepare() {
  params_ = sockets_udp::Create::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpCreateFunction::Work() {
  ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id());

  sockets_udp::SocketProperties* properties = params_.get()->properties.get();
  if (properties) {
    SetSocketProperties(socket, properties);
  }

  sockets_udp::CreateInfo create_info;
  create_info.socket_id = AddSocket(socket);
  results_ = sockets_udp::Create::Results::Create(create_info);
}

SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {}

SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {}

bool SocketsUdpUpdateFunction::Prepare() {
  params_ = sockets_udp::Update::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpUpdateFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  SetSocketProperties(socket, &params_.get()->properties);
  results_ = sockets_udp::Update::Results::Create();
}

SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction()
    : socket_event_dispatcher_(NULL) {}

SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {}

bool SocketsUdpSetPausedFunction::Prepare() {
  params_ = core_api::sockets_udp::SetPaused::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context());
  DCHECK(socket_event_dispatcher_)
      << "There is no socket event dispatcher. "
         "If this assertion is failing during a test, then it is likely that "
         "TestExtensionSystem is failing to provide an instance of "
         "UDPSocketEventDispatcher.";
  return socket_event_dispatcher_ != NULL;
}

void SocketsUdpSetPausedFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  if (socket->paused() != params_->paused) {
    socket->set_paused(params_->paused);
    if (socket->IsBound() && !params_->paused) {
      socket_event_dispatcher_->OnSocketResume(extension_->id(),
                                               params_->socket_id);
    }
  }

  results_ = sockets_udp::SetPaused::Results::Create();
}

SocketsUdpBindFunction::SocketsUdpBindFunction()
    : socket_event_dispatcher_(NULL) {}

SocketsUdpBindFunction::~SocketsUdpBindFunction() {}

bool SocketsUdpBindFunction::Prepare() {
  params_ = sockets_udp::Bind::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context());
  DCHECK(socket_event_dispatcher_)
      << "There is no socket event dispatcher. "
         "If this assertion is failing during a test, then it is likely that "
         "TestExtensionSystem is failing to provide an instance of "
         "UDPSocketEventDispatcher.";
  return socket_event_dispatcher_ != NULL;
}

void SocketsUdpBindFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  content::SocketPermissionRequest param(
      SocketPermissionRequest::UDP_BIND, params_->address, params_->port);
  if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
    error_ = kPermissionError;
    return;
  }

  int net_result = socket->Bind(params_->address, params_->port);
  if (net_result == net::OK) {
    socket_event_dispatcher_->OnSocketBind(extension_->id(),
                                           params_->socket_id);
  }

  if (net_result != net::OK)
    error_ = net::ErrorToString(net_result);
  results_ = sockets_udp::Bind::Results::Create(net_result);
}

SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {}

SocketsUdpSendFunction::~SocketsUdpSendFunction() {}

bool SocketsUdpSendFunction::Prepare() {
  params_ = sockets_udp::Send::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  io_buffer_size_ = params_->data.size();
  io_buffer_ = new net::WrappedIOBuffer(params_->data.data());

  return true;
}

void SocketsUdpSendFunction::AsyncWorkStart() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    AsyncWorkCompleted();
    return;
  }

  content::SocketPermissionRequest param(
      SocketPermissionRequest::UDP_SEND_TO, params_->address, params_->port);
  if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
    error_ = kPermissionError;
    AsyncWorkCompleted();
    return;
  }

  StartDnsLookup(params_->address);
}

void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) {
  if (lookup_result == net::OK) {
    StartSendTo();
  } else {
    SetSendResult(lookup_result, -1);
  }
}

void SocketsUdpSendFunction::StartSendTo() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    AsyncWorkCompleted();
    return;
  }

  socket->SendTo(io_buffer_,
                 io_buffer_size_,
                 resolved_address_,
                 params_->port,
                 base::Bind(&SocketsUdpSendFunction::OnCompleted, this));
}

void SocketsUdpSendFunction::OnCompleted(int net_result) {
  if (net_result >= net::OK) {
    SetSendResult(net::OK, net_result);
  } else {
    SetSendResult(net_result, -1);
  }
}

void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) {
  CHECK(net_result <= net::OK) << "Network status code must be < 0";

  sockets_udp::SendInfo send_info;
  send_info.result_code = net_result;
  if (net_result == net::OK) {
    send_info.bytes_sent.reset(new int(bytes_sent));
  }

  if (net_result != net::OK)
    error_ = net::ErrorToString(net_result);
  results_ = sockets_udp::Send::Results::Create(send_info);
  AsyncWorkCompleted();
}

SocketsUdpCloseFunction::SocketsUdpCloseFunction() {}

SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {}

bool SocketsUdpCloseFunction::Prepare() {
  params_ = sockets_udp::Close::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpCloseFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  socket->Disconnect();
  RemoveSocket(params_->socket_id);
  results_ = sockets_udp::Close::Results::Create();
}

SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {}

SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {}

bool SocketsUdpGetInfoFunction::Prepare() {
  params_ = sockets_udp::GetInfo::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpGetInfoFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  linked_ptr<sockets_udp::SocketInfo> socket_info =
      CreateSocketInfo(params_->socket_id, socket);
  results_ = sockets_udp::GetInfo::Results::Create(*socket_info);
}

SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {}

SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {}

bool SocketsUdpGetSocketsFunction::Prepare() { return true; }

void SocketsUdpGetSocketsFunction::Work() {
  std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos;
  base::hash_set<int>* resource_ids = GetSocketIds();
  if (resource_ids != NULL) {
    for (base::hash_set<int>::iterator it = resource_ids->begin();
         it != resource_ids->end();
         ++it) {
      int socket_id = *it;
      ResumableUDPSocket* socket = GetUdpSocket(socket_id);
      if (socket) {
        socket_infos.push_back(CreateSocketInfo(socket_id, socket));
      }
    }
  }
  results_ = sockets_udp::GetSockets::Results::Create(socket_infos);
}

SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {}

SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {}

bool SocketsUdpJoinGroupFunction::Prepare() {
  params_ = sockets_udp::JoinGroup::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpJoinGroupFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  content::SocketPermissionRequest param(
      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
      kWildcardAddress,
      kWildcardPort);
  if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
    error_ = kPermissionError;
    return;
  }

  int net_result = socket->JoinGroup(params_->address);
  if (net_result != net::OK)
    error_ = net::ErrorToString(net_result);
  results_ = sockets_udp::JoinGroup::Results::Create(net_result);
}

SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {}

SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {}

bool SocketsUdpLeaveGroupFunction::Prepare() {
  params_ = core_api::sockets_udp::LeaveGroup::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpLeaveGroupFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  content::SocketPermissionRequest param(
      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
      kWildcardAddress,
      kWildcardPort);
  if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
    error_ = kPermissionError;
    return;
  }

  int net_result = socket->LeaveGroup(params_->address);
  if (net_result != net::OK)
    error_ = net::ErrorToString(net_result);
  results_ = sockets_udp::LeaveGroup::Results::Create(net_result);
}

SocketsUdpSetMulticastTimeToLiveFunction::
    SocketsUdpSetMulticastTimeToLiveFunction() {}

SocketsUdpSetMulticastTimeToLiveFunction::
    ~SocketsUdpSetMulticastTimeToLiveFunction() {}

bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() {
  params_ =
      core_api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpSetMulticastTimeToLiveFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  int net_result = socket->SetMulticastTimeToLive(params_->ttl);
  if (net_result != net::OK)
    error_ = net::ErrorToString(net_result);
  results_ = sockets_udp::SetMulticastTimeToLive::Results::Create(net_result);
}

SocketsUdpSetMulticastLoopbackModeFunction::
    SocketsUdpSetMulticastLoopbackModeFunction() {}

SocketsUdpSetMulticastLoopbackModeFunction::
    ~SocketsUdpSetMulticastLoopbackModeFunction() {}

bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() {
  params_ =
      core_api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpSetMulticastLoopbackModeFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  int net_result = socket->SetMulticastLoopbackMode(params_->enabled);
  if (net_result != net::OK)
    error_ = net::ErrorToString(net_result);
  results_ = sockets_udp::SetMulticastLoopbackMode::Results::Create(net_result);
}

SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {}

SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {}

bool SocketsUdpGetJoinedGroupsFunction::Prepare() {
  params_ = core_api::sockets_udp::GetJoinedGroups::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());
  return true;
}

void SocketsUdpGetJoinedGroupsFunction::Work() {
  ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
  if (!socket) {
    error_ = kSocketNotFoundError;
    return;
  }

  content::SocketPermissionRequest param(
      SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
      kWildcardAddress,
      kWildcardPort);
  if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
    error_ = kPermissionError;
    return;
  }

  const std::vector<std::string>& groups = socket->GetJoinedGroups();
  results_ = sockets_udp::GetJoinedGroups::Results::Create(groups);
}

}  // namespace core_api
}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */