// Copyright 2013 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 "chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h"

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

namespace extensions {
namespace 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_ = api::sockets_udp::SetPaused::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_.get());

  socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(GetProfile());
  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(GetProfile());
  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_ = 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_ = 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_ = 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_ = 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 api
}  // namespace extensions
