// 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 "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h"

#include <cstring>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/process_type.h"
#include "content/public/common/socket_permission_request.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/udp/udp_server_socket.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/udp_socket_resource_base.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"
#include "ppapi/shared_impl/socket_option_data.h"

using ppapi::NetAddressPrivateImpl;
using ppapi::host::NetErrorToPepperError;

namespace {

size_t g_num_instances = 0;

}  // namespace

namespace content {

PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter(
    BrowserPpapiHostImpl* host,
    PP_Instance instance,
    bool private_api)
    : allow_address_reuse_(false),
      allow_broadcast_(false),
      closed_(false),
      remaining_recv_slots_(
          ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots),
      external_plugin_(host->external_plugin()),
      private_api_(private_api),
      render_process_id_(0),
      render_frame_id_(0) {
  ++g_num_instances;
  DCHECK(host);

  if (!host->GetRenderFrameIDsForInstance(
          instance, &render_process_id_, &render_frame_id_)) {
    NOTREACHED();
  }
}

PepperUDPSocketMessageFilter::~PepperUDPSocketMessageFilter() {
  Close();
  --g_num_instances;
}

// static
size_t PepperUDPSocketMessageFilter::GetNumInstances() {
  return g_num_instances;
}

scoped_refptr<base::TaskRunner>
PepperUDPSocketMessageFilter::OverrideTaskRunnerForMessage(
    const IPC::Message& message) {
  switch (message.type()) {
    case PpapiHostMsg_UDPSocket_SetOption::ID:
    case PpapiHostMsg_UDPSocket_Close::ID:
    case PpapiHostMsg_UDPSocket_RecvSlotAvailable::ID:
      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    case PpapiHostMsg_UDPSocket_Bind::ID:
    case PpapiHostMsg_UDPSocket_SendTo::ID:
      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
  }
  return NULL;
}

int32_t PepperUDPSocketMessageFilter::OnResourceMessageReceived(
    const IPC::Message& msg,
    ppapi::host::HostMessageContext* context) {
  PPAPI_BEGIN_MESSAGE_MAP(PepperUDPSocketMessageFilter, msg)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SetOption,
                                      OnMsgSetOption)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_Bind, OnMsgBind)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UDPSocket_SendTo,
                                      OnMsgSendTo)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_UDPSocket_Close,
                                        OnMsgClose)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
        PpapiHostMsg_UDPSocket_RecvSlotAvailable, OnMsgRecvSlotAvailable)
  PPAPI_END_MESSAGE_MAP()
  return PP_ERROR_FAILED;
}

int32_t PepperUDPSocketMessageFilter::OnMsgSetOption(
    const ppapi::host::HostMessageContext* context,
    PP_UDPSocket_Option name,
    const ppapi::SocketOptionData& value) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (closed_)
    return PP_ERROR_FAILED;

  switch (name) {
    case PP_UDPSOCKET_OPTION_ADDRESS_REUSE:
    case PP_UDPSOCKET_OPTION_BROADCAST: {
      if (socket_.get()) {
        // They only take effect before the socket is bound.
        return PP_ERROR_FAILED;
      }

      bool boolean_value = false;
      if (!value.GetBool(&boolean_value))
        return PP_ERROR_BADARGUMENT;

      if (name == PP_UDPSOCKET_OPTION_ADDRESS_REUSE)
        allow_address_reuse_ = boolean_value;
      else
        allow_broadcast_ = boolean_value;
      return PP_OK;
    }
    case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE:
    case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
      if (!socket_.get()) {
        // They only take effect after the socket is bound.
        return PP_ERROR_FAILED;
      }
      int32_t integer_value = 0;
      if (!value.GetInt32(&integer_value) || integer_value <= 0)
        return PP_ERROR_BADARGUMENT;

      int net_result = net::ERR_UNEXPECTED;
      if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) {
        if (integer_value >
            ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) {
          return PP_ERROR_BADARGUMENT;
        }
        net_result = socket_->SetSendBufferSize(integer_value);
      } else {
        if (integer_value >
            ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) {
          return PP_ERROR_BADARGUMENT;
        }
        net_result = socket_->SetReceiveBufferSize(integer_value);
      }
      // TODO(wtc): Add error mapping code.
      return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
    }
    default: {
      NOTREACHED();
      return PP_ERROR_BADARGUMENT;
    }
  }
}

int32_t PepperUDPSocketMessageFilter::OnMsgBind(
    const ppapi::host::HostMessageContext* context,
    const PP_NetAddress_Private& addr) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(context);

  SocketPermissionRequest request =
      pepper_socket_utils::CreateSocketPermissionRequest(
          SocketPermissionRequest::UDP_BIND, addr);
  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
                                             private_api_,
                                             &request,
                                             render_process_id_,
                                             render_frame_id_)) {
    return PP_ERROR_NOACCESS;
  }

  BrowserThread::PostTask(BrowserThread::IO,
                          FROM_HERE,
                          base::Bind(&PepperUDPSocketMessageFilter::DoBind,
                                     this,
                                     context->MakeReplyMessageContext(),
                                     addr));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperUDPSocketMessageFilter::OnMsgSendTo(
    const ppapi::host::HostMessageContext* context,
    const std::string& data,
    const PP_NetAddress_Private& addr) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(context);

  SocketPermissionRequest request =
      pepper_socket_utils::CreateSocketPermissionRequest(
          SocketPermissionRequest::UDP_SEND_TO, addr);
  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
                                             private_api_,
                                             &request,
                                             render_process_id_,
                                             render_frame_id_)) {
    return PP_ERROR_NOACCESS;
  }

  BrowserThread::PostTask(BrowserThread::IO,
                          FROM_HERE,
                          base::Bind(&PepperUDPSocketMessageFilter::DoSendTo,
                                     this,
                                     context->MakeReplyMessageContext(),
                                     data,
                                     addr));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperUDPSocketMessageFilter::OnMsgClose(
    const ppapi::host::HostMessageContext* context) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  Close();
  return PP_OK;
}

int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable(
    const ppapi::host::HostMessageContext* context) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (remaining_recv_slots_ <
          ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots) {
    remaining_recv_slots_++;
  }

  if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) {
    DCHECK_EQ(1u, remaining_recv_slots_);
    DoRecvFrom();
  }

  return PP_OK;
}

void PepperUDPSocketMessageFilter::DoBind(
    const ppapi::host::ReplyMessageContext& context,
    const PP_NetAddress_Private& addr) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (closed_ || socket_.get()) {
    SendBindError(context, PP_ERROR_FAILED);
    return;
  }

  scoped_ptr<net::UDPServerSocket> socket(
      new net::UDPServerSocket(NULL, net::NetLog::Source()));

  net::IPAddressNumber address;
  int port;
  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
    SendBindError(context, PP_ERROR_ADDRESS_INVALID);
    return;
  }

  if (allow_address_reuse_)
    socket->AllowAddressReuse();
  if (allow_broadcast_)
    socket->AllowBroadcast();

  int32_t pp_result =
      NetErrorToPepperError(socket->Listen(net::IPEndPoint(address, port)));
  if (pp_result != PP_OK) {
    SendBindError(context, pp_result);
    return;
  }

  net::IPEndPoint bound_address;
  pp_result = NetErrorToPepperError(socket->GetLocalAddress(&bound_address));
  if (pp_result != PP_OK) {
    SendBindError(context, pp_result);
    return;
  }

  PP_NetAddress_Private net_address = NetAddressPrivateImpl::kInvalidNetAddress;
  if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
          bound_address.address(), bound_address.port(), &net_address)) {
    SendBindError(context, PP_ERROR_ADDRESS_INVALID);
    return;
  }

  allow_address_reuse_ = false;
  allow_broadcast_ = false;
  socket_.swap(socket);
  SendBindReply(context, PP_OK, net_address);

  DoRecvFrom();
}

void PepperUDPSocketMessageFilter::DoRecvFrom() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(!closed_);
  DCHECK(socket_.get());
  DCHECK(!recvfrom_buffer_.get());
  DCHECK_GT(remaining_recv_slots_, 0u);

  recvfrom_buffer_ = new net::IOBuffer(
      ppapi::proxy::UDPSocketResourceBase::kMaxReadSize);

  // Use base::Unretained(this), so that the lifespan of this object doesn't
  // have to last until the callback is called.
  // It is safe to do so because |socket_| is owned by this object. If this
  // object gets destroyed (and so does |socket_|), the callback won't be
  // called.
  int net_result = socket_->RecvFrom(
      recvfrom_buffer_.get(),
      ppapi::proxy::UDPSocketResourceBase::kMaxReadSize,
      &recvfrom_address_,
      base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted,
                 base::Unretained(this)));
  if (net_result != net::ERR_IO_PENDING)
    OnRecvFromCompleted(net_result);
}

void PepperUDPSocketMessageFilter::DoSendTo(
    const ppapi::host::ReplyMessageContext& context,
    const std::string& data,
    const PP_NetAddress_Private& addr) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(socket_.get());

  if (closed_ || !socket_.get()) {
    SendSendToError(context, PP_ERROR_FAILED);
    return;
  }

  if (sendto_buffer_.get()) {
    SendSendToError(context, PP_ERROR_INPROGRESS);
    return;
  }

  size_t num_bytes = data.size();
  if (num_bytes == 0 ||
      num_bytes > static_cast<size_t>(
                      ppapi::proxy::UDPSocketResourceBase::kMaxWriteSize)) {
    // Size of |data| is checked on the plugin side.
    NOTREACHED();
    SendSendToError(context, PP_ERROR_BADARGUMENT);
    return;
  }

  sendto_buffer_ = new net::IOBufferWithSize(num_bytes);
  memcpy(sendto_buffer_->data(), data.data(), num_bytes);

  net::IPAddressNumber address;
  int port;
  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
    SendSendToError(context, PP_ERROR_ADDRESS_INVALID);
    return;
  }

  // Please see OnMsgRecvFrom() for the reason why we use base::Unretained(this)
  // when calling |socket_| methods.
  int net_result = socket_->SendTo(
      sendto_buffer_.get(),
      sendto_buffer_->size(),
      net::IPEndPoint(address, port),
      base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted,
                 base::Unretained(this),
                 context));
  if (net_result != net::ERR_IO_PENDING)
    OnSendToCompleted(context, net_result);
}

void PepperUDPSocketMessageFilter::Close() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (socket_.get() && !closed_)
    socket_->Close();
  closed_ = true;
}

void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(recvfrom_buffer_.get());

  int32_t pp_result = NetErrorToPepperError(net_result);

  // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private
  // to send back.
  PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress;
  if (pp_result >= 0 &&
      !NetAddressPrivateImpl::IPEndPointToNetAddress(
          recvfrom_address_.address(), recvfrom_address_.port(), &addr)) {
    pp_result = PP_ERROR_ADDRESS_INVALID;
  }

  if (pp_result >= 0) {
    SendRecvFromResult(PP_OK, std::string(recvfrom_buffer_->data(), pp_result),
                       addr);
  } else {
    SendRecvFromError(pp_result);
  }

  recvfrom_buffer_ = NULL;

  DCHECK_GT(remaining_recv_slots_, 0u);
  remaining_recv_slots_--;

  if (remaining_recv_slots_ > 0 && !closed_ && socket_.get())
    DoRecvFrom();
}

void PepperUDPSocketMessageFilter::OnSendToCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(sendto_buffer_.get());

  int32_t pp_result = NetErrorToPepperError(net_result);
  if (pp_result < 0)
    SendSendToError(context, pp_result);
  else
    SendSendToReply(context, PP_OK, pp_result);
  sendto_buffer_ = NULL;
}

void PepperUDPSocketMessageFilter::SendBindReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t result,
    const PP_NetAddress_Private& addr) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(result);
  SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr));
}

void PepperUDPSocketMessageFilter::SendRecvFromResult(
    int32_t result,
    const std::string& data,
    const PP_NetAddress_Private& addr) {
  if (resource_host()) {
    resource_host()->host()->SendUnsolicitedReply(
        resource_host()->pp_resource(),
        PpapiPluginMsg_UDPSocket_PushRecvResult(result, data, addr));
  }
}

void PepperUDPSocketMessageFilter::SendSendToReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t result,
    int32_t bytes_written) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(result);
  SendReply(reply_context, PpapiPluginMsg_UDPSocket_SendToReply(bytes_written));
}

void PepperUDPSocketMessageFilter::SendBindError(
    const ppapi::host::ReplyMessageContext& context,
    int32_t result) {
  SendBindReply(context, result, NetAddressPrivateImpl::kInvalidNetAddress);
}

void PepperUDPSocketMessageFilter::SendRecvFromError(
    int32_t result) {
  SendRecvFromResult(result, std::string(),
                     NetAddressPrivateImpl::kInvalidNetAddress);
}

void PepperUDPSocketMessageFilter::SendSendToError(
    const ppapi::host::ReplyMessageContext& context,
    int32_t result) {
  SendSendToReply(context, result, 0);
}

}  // namespace content
