// 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_tcp_socket_message_filter.h"

#include <cstring>

#include "base/bind.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
#include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
#include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/address_family.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/dns/single_request_host_resolver.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
#include "net/socket/tcp_client_socket.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/error_conversion.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/tcp_socket_resource_base.h"
#include "ppapi/shared_impl/private/net_address_private_impl.h"

using ppapi::NetAddressPrivateImpl;
using ppapi::host::NetErrorToPepperError;
using ppapi::proxy::TCPSocketResourceBase;
using ppapi::TCPSocketState;
using ppapi::TCPSocketVersion;

namespace {

size_t g_num_instances = 0;

}  // namespace

namespace content {

PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
    ContentBrowserPepperHostFactory* factory,
    BrowserPpapiHostImpl* host,
    PP_Instance instance,
    TCPSocketVersion version)
    : version_(version),
      external_plugin_(host->external_plugin()),
      render_process_id_(0),
      render_view_id_(0),
      ppapi_host_(host->GetPpapiHost()),
      factory_(factory),
      instance_(instance),
      state_(TCPSocketState::INITIAL),
      end_of_file_reached_(false),
      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
      socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
      ssl_context_helper_(host->ssl_context_helper()),
      pending_accept_(false) {
  DCHECK(host);
  ++g_num_instances;
  if (!host->GetRenderViewIDsForInstance(instance,
                                         &render_process_id_,
                                         &render_view_id_)) {
    NOTREACHED();
  }
}

PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
    BrowserPpapiHostImpl* host,
    PP_Instance instance,
    TCPSocketVersion version,
    scoped_ptr<net::TCPSocket> socket)
    : version_(version),
      external_plugin_(host->external_plugin()),
      render_process_id_(0),
      render_view_id_(0),
      ppapi_host_(host->GetPpapiHost()),
      factory_(NULL),
      instance_(instance),
      state_(TCPSocketState::CONNECTED),
      end_of_file_reached_(false),
      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
      socket_(socket.Pass()),
      ssl_context_helper_(host->ssl_context_helper()),
      pending_accept_(false) {
  DCHECK(host);
  DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);

  ++g_num_instances;
  if (!host->GetRenderViewIDsForInstance(instance,
                                         &render_process_id_,
                                         &render_view_id_)) {
    NOTREACHED();
  }
}

PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
  if (socket_)
    socket_->Close();
  if (ssl_socket_)
    ssl_socket_->Disconnect();
  --g_num_instances;
}

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

scoped_refptr<base::TaskRunner>
PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
    const IPC::Message& message) {
  switch (message.type()) {
    case PpapiHostMsg_TCPSocket_Bind::ID:
    case PpapiHostMsg_TCPSocket_Connect::ID:
    case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
    case PpapiHostMsg_TCPSocket_Listen::ID:
      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
    case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
    case PpapiHostMsg_TCPSocket_Read::ID:
    case PpapiHostMsg_TCPSocket_Write::ID:
    case PpapiHostMsg_TCPSocket_Accept::ID:
    case PpapiHostMsg_TCPSocket_Close::ID:
    case PpapiHostMsg_TCPSocket_SetOption::ID:
      return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
  }
  return NULL;
}

int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
    const IPC::Message& msg,
    ppapi::host::HostMessageContext* context) {
  IPC_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_Connect, OnMsgConnect)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
        OnMsgConnectWithNetAddress)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_SSLHandshake, OnMsgSSLHandshake)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_Read, OnMsgRead)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_Listen, OnMsgListen)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
        PpapiHostMsg_TCPSocket_Accept, OnMsgAccept)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
        PpapiHostMsg_TCPSocket_Close, OnMsgClose)
    PPAPI_DISPATCH_HOST_RESOURCE_CALL(
        PpapiHostMsg_TCPSocket_SetOption, OnMsgSetOption)
  IPC_END_MESSAGE_MAP()
  return PP_ERROR_FAILED;
}

int32_t PepperTCPSocketMessageFilter::OnMsgBind(
    const ppapi::host::HostMessageContext* context,
    const PP_NetAddress_Private& net_addr) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // This is only supported by PPB_TCPSocket v1.1 or above.
  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    NOTREACHED();
    return PP_ERROR_NOACCESS;
  }

  if (!pepper_socket_utils::CanUseSocketAPIs(
          external_plugin_, false /* private_api */, NULL, render_process_id_,
          render_view_id_)) {
    return PP_ERROR_NOACCESS;
  }

  bind_input_addr_ = net_addr;

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

int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
    const ppapi::host::HostMessageContext* context,
    const std::string& host,
    uint16_t port) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // This is only supported by PPB_TCPSocket_Private.
  if (!IsPrivateAPI()) {
    NOTREACHED();
    return PP_ERROR_NOACCESS;
  }

  SocketPermissionRequest request(SocketPermissionRequest::TCP_CONNECT,
                                  host,
                                  port);
  if (!pepper_socket_utils::CanUseSocketAPIs(
          external_plugin_, true /* private_api */, &request,
          render_process_id_, render_view_id_)) {
    return PP_ERROR_NOACCESS;
  }

  RenderProcessHost* render_process_host =
      RenderProcessHost::FromID(render_process_id_);
  if (!render_process_host)
    return PP_ERROR_FAILED;
  BrowserContext* browser_context = render_process_host->GetBrowserContext();
  if (!browser_context || !browser_context->GetResourceContext())
    return PP_ERROR_FAILED;

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&PepperTCPSocketMessageFilter::DoConnect, this,
                 context->MakeReplyMessageContext(),
                 host, port, browser_context->GetResourceContext()));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
    const ppapi::host::HostMessageContext* context,
    const PP_NetAddress_Private& net_addr) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  content::SocketPermissionRequest request =
      pepper_socket_utils::CreateSocketPermissionRequest(
          content::SocketPermissionRequest::TCP_CONNECT, net_addr);
  if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_, IsPrivateAPI(),
                                             &request, render_process_id_,
                                             render_view_id_)) {
    return PP_ERROR_NOACCESS;
  }

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress, this,
                 context->MakeReplyMessageContext(), net_addr));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
    const ppapi::host::HostMessageContext* context,
    const std::string& server_name,
    uint16_t server_port,
    const std::vector<std::vector<char> >& trusted_certs,
    const std::vector<std::vector<char> >& untrusted_certs) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  // Allow to do SSL handshake only if currently the socket has been connected
  // and there isn't pending read or write.
  if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
      read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
    return PP_ERROR_FAILED;
  }

  // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
  net::IPEndPoint peer_address;
  if (socket_->GetPeerAddress(&peer_address) != net::OK)
    return PP_ERROR_FAILED;

  scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
  handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
      new net::TCPClientSocket(socket_.Pass(), peer_address)));
  net::ClientSocketFactory* factory =
      net::ClientSocketFactory::GetDefaultFactory();
  net::HostPortPair host_port_pair(server_name, server_port);
  net::SSLClientSocketContext ssl_context;
  ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
  ssl_context.transport_security_state =
      ssl_context_helper_->GetTransportSecurityState();
  ssl_socket_ = factory->CreateSSLClientSocket(
      handle.Pass(), host_port_pair, ssl_context_helper_->ssl_config(),
      ssl_context);
  if (!ssl_socket_) {
    LOG(WARNING) << "Failed to create an SSL client socket.";
    state_.CompletePendingTransition(false);
    return PP_ERROR_FAILED;
  }

  state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);

  const ppapi::host::ReplyMessageContext reply_context(
      context->MakeReplyMessageContext());
  int net_result = ssl_socket_->Connect(
      base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
                 base::Unretained(this), reply_context));
  if (net_result != net::ERR_IO_PENDING)
    OnSSLHandshakeCompleted(reply_context, net_result);
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgRead(
    const ppapi::host::HostMessageContext* context,
    int32_t bytes_to_read) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (!state_.IsConnected() || end_of_file_reached_)
    return PP_ERROR_FAILED;
  if (read_buffer_.get())
    return PP_ERROR_INPROGRESS;
  if (bytes_to_read <= 0 ||
      bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
    return PP_ERROR_BADARGUMENT;
  }

  ppapi::host::ReplyMessageContext reply_context(
      context->MakeReplyMessageContext());
  read_buffer_ = new net::IOBuffer(bytes_to_read);

  int net_result = net::ERR_FAILED;
  if (socket_) {
    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
    net_result = socket_->Read(
        read_buffer_.get(),
        bytes_to_read,
        base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
                   base::Unretained(this), reply_context));
  } else if (ssl_socket_) {
    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
    net_result = ssl_socket_->Read(
        read_buffer_.get(),
        bytes_to_read,
        base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
                   base::Unretained(this), reply_context));
  }
  if (net_result != net::ERR_IO_PENDING)
    OnReadCompleted(reply_context, net_result);
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
    const ppapi::host::HostMessageContext* context,
    const std::string& data) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!state_.IsConnected())
    return PP_ERROR_FAILED;
  if (write_buffer_base_.get() || write_buffer_.get())
    return PP_ERROR_INPROGRESS;

  size_t data_size = data.size();
  if (data_size == 0 ||
      data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
    return PP_ERROR_BADARGUMENT;
  }

  write_buffer_base_ = new net::IOBuffer(data_size);
  memcpy(write_buffer_base_->data(), data.data(), data_size);
  write_buffer_ =
      new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
  DoWrite(context->MakeReplyMessageContext());
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgListen(
    const ppapi::host::HostMessageContext* context,
    int32_t backlog) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  // This is only supported by PPB_TCPSocket v1.1 or above.
  if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    NOTREACHED();
    return PP_ERROR_NOACCESS;
  }

  content::SocketPermissionRequest request =
      pepper_socket_utils::CreateSocketPermissionRequest(
          content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
  if (!pepper_socket_utils::CanUseSocketAPIs(
          external_plugin_, false /* private_api */, &request,
          render_process_id_, render_view_id_)) {
    return PP_ERROR_NOACCESS;
  }

  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::Bind(&PepperTCPSocketMessageFilter::DoListen, this,
                 context->MakeReplyMessageContext(), backlog));
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
    const ppapi::host::HostMessageContext* context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (pending_accept_)
    return PP_ERROR_INPROGRESS;
  if (state_.state() != TCPSocketState::LISTENING)
    return PP_ERROR_FAILED;

  pending_accept_ = true;
  ppapi::host::ReplyMessageContext reply_context(
      context->MakeReplyMessageContext());
  int net_result = socket_->Accept(
      &accepted_socket_,
      &accepted_address_,
      base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
                 base::Unretained(this), reply_context));
  if (net_result != net::ERR_IO_PENDING)
    OnAcceptCompleted(reply_context, net_result);
  return PP_OK_COMPLETIONPENDING;
}

int32_t PepperTCPSocketMessageFilter::OnMsgClose(
    const ppapi::host::HostMessageContext* context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (state_.state() == TCPSocketState::CLOSED)
    return PP_OK;

  state_.DoTransition(TCPSocketState::CLOSE, true);
  // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
  if (socket_) {
    socket_->Close();
  } else if (ssl_socket_) {
    ssl_socket_->Disconnect();
  }
  return PP_OK;
}

int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
    const ppapi::host::HostMessageContext* context,
    PP_TCPSocket_Option name,
    const ppapi::SocketOptionData& value) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  switch (name) {
    case PP_TCPSOCKET_OPTION_NO_DELAY: {
      if (state_.state() != TCPSocketState::CONNECTED)
        return PP_ERROR_FAILED;

      bool boolean_value = false;
      if (!value.GetBool(&boolean_value))
        return PP_ERROR_BADARGUMENT;
      return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
    }
    case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
    case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
      if (state_.state() != TCPSocketState::CONNECTED)
        return PP_ERROR_FAILED;

      int32_t integer_value = 0;
      if (!value.GetInt32(&integer_value) || integer_value <= 0)
        return PP_ERROR_BADARGUMENT;

      bool result = false;
      if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
        if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
          return PP_ERROR_BADARGUMENT;
        result = socket_->SetSendBufferSize(integer_value);
      } else {
        if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
          return PP_ERROR_BADARGUMENT;
        result = socket_->SetReceiveBufferSize(integer_value);
      }
      return result ? PP_OK : PP_ERROR_FAILED;
    }
    default: {
      NOTREACHED();
      return PP_ERROR_BADARGUMENT;
    }
  }
}

void PepperTCPSocketMessageFilter::DoBind(
    const ppapi::host::ReplyMessageContext& context,
    const PP_NetAddress_Private& net_addr) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (state_.IsPending(TCPSocketState::BIND)) {
    SendBindError(context, PP_ERROR_INPROGRESS);
    return;
  }
  if (!state_.IsValidTransition(TCPSocketState::BIND)) {
    SendBindError(context, PP_ERROR_FAILED);
    return;
  }

  int pp_result = PP_OK;
  do {
    net::IPAddressNumber address;
    int port;
    if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
                                                       &port)) {
      pp_result = PP_ERROR_ADDRESS_INVALID;
      break;
    }
    net::IPEndPoint bind_addr(address, port);

    DCHECK(!socket_->IsValid());
    pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
    if (pp_result != PP_OK)
      break;

    pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
    if (pp_result != PP_OK)
      break;

    pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
    if (pp_result != PP_OK)
      break;

    net::IPEndPoint ip_end_point_local;
    pp_result = NetErrorToPepperError(
        socket_->GetLocalAddress(&ip_end_point_local));
    if (pp_result != PP_OK)
      break;

    PP_NetAddress_Private local_addr =
        NetAddressPrivateImpl::kInvalidNetAddress;
    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
            ip_end_point_local.address(),
            ip_end_point_local.port(),
            &local_addr)) {
      pp_result = PP_ERROR_ADDRESS_INVALID;
      break;
    }

    SendBindReply(context, PP_OK, local_addr);
    state_.DoTransition(TCPSocketState::BIND, true);
    return;
  } while (false);
  if (socket_->IsValid())
    socket_->Close();
  SendBindError(context, pp_result);
  state_.DoTransition(TCPSocketState::BIND, false);
}

void PepperTCPSocketMessageFilter::DoConnect(
    const ppapi::host::ReplyMessageContext& context,
    const std::string& host,
    uint16_t port,
    ResourceContext* resource_context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
    SendConnectError(context, PP_ERROR_FAILED);
    return;
  }

  state_.SetPendingTransition(TCPSocketState::CONNECT);
  net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
  resolver_.reset(new net::SingleRequestHostResolver(
      resource_context->GetHostResolver()));
  int net_result = resolver_->Resolve(
      request_info,
      net::DEFAULT_PRIORITY,
      &address_list_,
      base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
                 base::Unretained(this), context),
      net::BoundNetLog());
  if (net_result != net::ERR_IO_PENDING)
    OnResolveCompleted(context, net_result);
}

void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
    const ppapi::host::ReplyMessageContext& context,
    const PP_NetAddress_Private& net_addr) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
    SendConnectError(context, PP_ERROR_FAILED);
    return;
  }

  state_.SetPendingTransition(TCPSocketState::CONNECT);

  net::IPAddressNumber address;
  int port;
  if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(net_addr, &address,
                                                     &port)) {
    state_.CompletePendingTransition(false);
    SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
    return;
  }

  // Copy the single IPEndPoint to address_list_.
  address_list_.clear();
  address_list_.push_back(net::IPEndPoint(address, port));
  StartConnect(context);
}

void PepperTCPSocketMessageFilter::DoWrite(
    const ppapi::host::ReplyMessageContext& context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(write_buffer_base_.get());
  DCHECK(write_buffer_.get());
  DCHECK_GT(write_buffer_->BytesRemaining(), 0);
  DCHECK(state_.IsConnected());

  int net_result = net::ERR_FAILED;
  if (socket_) {
    DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
    net_result = socket_->Write(
        write_buffer_.get(),
        write_buffer_->BytesRemaining(),
        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
                   base::Unretained(this), context));
  } else if (ssl_socket_) {
    DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
    net_result = ssl_socket_->Write(
        write_buffer_.get(),
        write_buffer_->BytesRemaining(),
        base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
                   base::Unretained(this), context));
  }
  if (net_result != net::ERR_IO_PENDING)
    OnWriteCompleted(context, net_result);
}

void PepperTCPSocketMessageFilter::DoListen(
    const ppapi::host::ReplyMessageContext& context,
    int32_t backlog) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (state_.IsPending(TCPSocketState::LISTEN)) {
    SendListenReply(context, PP_ERROR_INPROGRESS);
    return;
  }
  if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
    SendListenReply(context, PP_ERROR_FAILED);
    return;
  }

  int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
  SendListenReply(context, pp_result);
  state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
}

void PepperTCPSocketMessageFilter::OnResolveCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!state_.IsPending(TCPSocketState::CONNECT)) {
    DCHECK(state_.state() == TCPSocketState::CLOSED);
    SendConnectError(context, PP_ERROR_FAILED);
    return;
  }

  if (net_result != net::OK) {
    SendConnectError(context, NetErrorToPepperError(net_result));
    state_.CompletePendingTransition(false);
    return;
  }

  StartConnect(context);
}

void PepperTCPSocketMessageFilter::StartConnect(
    const ppapi::host::ReplyMessageContext& context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(state_.IsPending(TCPSocketState::CONNECT));

  int net_result = net::OK;
  if (!socket_->IsValid())
    net_result = socket_->Open(address_list_[0].GetFamily());

  if (net_result == net::OK) {
    net_result = socket_->Connect(
        address_list_[0],
        base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
                   base::Unretained(this), context));
  }
  if (net_result != net::ERR_IO_PENDING)
    OnConnectCompleted(context, net_result);
}

void PepperTCPSocketMessageFilter::OnConnectCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!state_.IsPending(TCPSocketState::CONNECT)) {
    DCHECK(state_.state() == TCPSocketState::CLOSED);
    SendConnectError(context, PP_ERROR_FAILED);
    return;
  }

  int32_t pp_result = NetErrorToPepperError(net_result);
  do {
    if (pp_result != PP_OK)
      break;

    net::IPEndPoint ip_end_point_local;
    net::IPEndPoint ip_end_point_remote;
    pp_result = NetErrorToPepperError(
        socket_->GetLocalAddress(&ip_end_point_local));
    if (pp_result != PP_OK)
      break;
    pp_result = NetErrorToPepperError(
        socket_->GetPeerAddress(&ip_end_point_remote));
    if (pp_result != PP_OK)
      break;

    PP_NetAddress_Private local_addr =
        NetAddressPrivateImpl::kInvalidNetAddress;
    PP_NetAddress_Private remote_addr =
        NetAddressPrivateImpl::kInvalidNetAddress;
    if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
            ip_end_point_local.address(),
            ip_end_point_local.port(),
            &local_addr) ||
        !NetAddressPrivateImpl::IPEndPointToNetAddress(
            ip_end_point_remote.address(),
            ip_end_point_remote.port(),
            &remote_addr)) {
      pp_result = PP_ERROR_ADDRESS_INVALID;
      break;
    }

    socket_->SetDefaultOptionsForClient();
    SendConnectReply(context, PP_OK, local_addr, remote_addr);
    state_.CompletePendingTransition(true);
    return;
  } while (false);

  SendConnectError(context, pp_result);
  if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    state_.CompletePendingTransition(false);
  } else {
    // In order to maintain backward compatibility, allow further attempts to
    // connect the socket.
    state_ = TCPSocketState(TCPSocketState::INITIAL);
    // We have to recreate |socket_| because it doesn't allow a second connect
    // attempt. We won't lose any state such as bound address or set options,
    // because in the private or v1.0 API, connect must be the first operation.
    socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
  }
}

void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
    DCHECK(state_.state() == TCPSocketState::CLOSED);
    SendSSLHandshakeReply(context, PP_ERROR_FAILED);
    return;
  }

  SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
  state_.CompletePendingTransition(net_result == net::OK);
}

void PepperTCPSocketMessageFilter::OnReadCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(read_buffer_.get());

  if (net_result > 0) {
    SendReadReply(context,
                  PP_OK,
                  std::string(read_buffer_->data(), net_result));
  } else if (net_result == 0) {
    end_of_file_reached_ = true;
    SendReadReply(context, PP_OK, std::string());
  } else {
    SendReadError(context, NetErrorToPepperError(net_result));
  }
  read_buffer_ = NULL;
}

void PepperTCPSocketMessageFilter::OnWriteCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(write_buffer_base_.get());
  DCHECK(write_buffer_.get());

  // Note: For partial writes of 0 bytes, don't continue writing to avoid a
  // likely infinite loop.
  if (net_result > 0) {
    write_buffer_->DidConsume(net_result);
    if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
      DoWrite(context);
      return;
    }
  }

  if (net_result >= 0)
    SendWriteReply(context, write_buffer_->BytesConsumed());
  else
    SendWriteReply(context, NetErrorToPepperError(net_result));

  write_buffer_ = NULL;
  write_buffer_base_ = NULL;
}

void PepperTCPSocketMessageFilter::OnAcceptCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(pending_accept_);

  pending_accept_ = false;

  if (net_result != net::OK) {
    SendAcceptError(context, NetErrorToPepperError(net_result));
    return;
  }

  DCHECK(accepted_socket_.get());

  net::IPEndPoint ip_end_point_local;
  PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
  PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;

  int32_t pp_result =
      NetErrorToPepperError(accepted_socket_->GetLocalAddress(
          &ip_end_point_local));
  if (pp_result != PP_OK) {
    SendAcceptError(context, pp_result);
    return;
  }
  if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
          ip_end_point_local.address(),
          ip_end_point_local.port(),
          &local_addr) ||
      !NetAddressPrivateImpl::IPEndPointToNetAddress(
          accepted_address_.address(),
          accepted_address_.port(),
          &remote_addr)) {
    SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
    return;
  }

  // |factory_| is guaranteed to be non-NULL here. Only those instances created
  // in CONNECTED state have a NULL |factory_|, while getting here requires
  // LISTENING state.
  scoped_ptr<ppapi::host::ResourceHost> host =
      factory_->CreateAcceptedTCPSocket(
          instance_, version_, accepted_socket_.Pass());
  if (!host) {
    SendAcceptError(context, PP_ERROR_NOSPACE);
    return;
  }
  int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
  if (pending_host_id)
    SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
  else
    SendAcceptError(context, PP_ERROR_NOSPACE);
}

void PepperTCPSocketMessageFilter::SendBindReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result,
    const PP_NetAddress_Private& local_addr) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
}

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

void PepperTCPSocketMessageFilter::SendConnectReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result,
    const PP_NetAddress_Private& local_addr,
    const PP_NetAddress_Private& remote_addr) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  SendReply(reply_context,
            PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
}

void PepperTCPSocketMessageFilter::SendConnectError(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_error) {
  SendConnectReply(context,
                   pp_error,
                   NetAddressPrivateImpl::kInvalidNetAddress,
                   NetAddressPrivateImpl::kInvalidNetAddress);
}

void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  ppapi::PPB_X509Certificate_Fields certificate_fields;
  if (pp_result == PP_OK) {
    // Our socket is guaranteed to be an SSL socket if we get here.
    net::SSLInfo ssl_info;
    ssl_socket_->GetSSLInfo(&ssl_info);
    if (ssl_info.cert.get()) {
      pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
                                                &certificate_fields);
    }
  }
  SendReply(reply_context,
            PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
}

void PepperTCPSocketMessageFilter::SendReadReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result,
    const std::string& data) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
}

void PepperTCPSocketMessageFilter::SendReadError(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_error) {
  SendReadReply(context, pp_error, std::string());
}

void PepperTCPSocketMessageFilter::SendWriteReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
}

void PepperTCPSocketMessageFilter::SendListenReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
}

void PepperTCPSocketMessageFilter::SendAcceptReply(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_result,
    int pending_host_id,
    const PP_NetAddress_Private& local_addr,
    const PP_NetAddress_Private& remote_addr) {
  ppapi::host::ReplyMessageContext reply_context(context);
  reply_context.params.set_result(pp_result);
  SendReply(reply_context,
            PpapiPluginMsg_TCPSocket_AcceptReply(
                pending_host_id, local_addr, remote_addr));
}

void PepperTCPSocketMessageFilter::SendAcceptError(
    const ppapi::host::ReplyMessageContext& context,
    int32_t pp_error) {
  SendAcceptReply(context, pp_error, 0,
                  NetAddressPrivateImpl::kInvalidNetAddress,
                  NetAddressPrivateImpl::kInvalidNetAddress);
}

}  // namespace content
