// 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_frame_id_(0),
      ppapi_host_(host->GetPpapiHost()),
      factory_(factory),
      instance_(instance),
      state_(TCPSocketState::INITIAL),
      end_of_file_reached_(false),
      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
      address_index_(0),
      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->GetRenderFrameIDsForInstance(
          instance, &render_process_id_, &render_frame_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_frame_id_(0),
      ppapi_host_(host->GetPpapiHost()),
      factory_(NULL),
      instance_(instance),
      state_(TCPSocketState::CONNECTED),
      end_of_file_reached_(false),
      bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
      address_index_(0),
      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->GetRenderFrameIDsForInstance(
          instance, &render_process_id_, &render_frame_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) {
  PPAPI_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)
  PPAPI_END_MESSAGE_MAP()
  return PP_ERROR_FAILED;
}

int32_t PepperTCPSocketMessageFilter::OnMsgBind(
    const ppapi::host::HostMessageContext* context,
    const PP_NetAddress_Private& net_addr) {
  DCHECK_CURRENTLY_ON(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_frame_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_CURRENTLY_ON(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_frame_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_CURRENTLY_ON(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_frame_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_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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_frame_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_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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;

      int net_result = net::ERR_UNEXPECTED;
      if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
        if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
          return PP_ERROR_BADARGUMENT;
        net_result = socket_->SetSendBufferSize(integer_value);
      } else {
        if (integer_value > TCPSocketResourceBase::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;
    }
  }
}

void PepperTCPSocketMessageFilter::DoBind(
    const ppapi::host::ReplyMessageContext& context,
    const PP_NetAddress_Private& net_addr) {
  DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(BrowserThread::IO);

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

  state_.SetPendingTransition(TCPSocketState::CONNECT);
  address_index_ = 0;
  address_list_.clear();
  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_CURRENTLY_ON(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_index_ = 0;
  address_list_.clear();
  address_list_.push_back(net::IPEndPoint(address, port));
  StartConnect(context);
}

void PepperTCPSocketMessageFilter::DoWrite(
    const ppapi::host::ReplyMessageContext& context) {
  DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(state_.IsPending(TCPSocketState::CONNECT));
  DCHECK_LT(address_index_, address_list_.size());

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

  if (net_result == net::OK) {
    net_result = socket_->Connect(
        address_list_[address_index_],
        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_CURRENTLY_ON(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);

  if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    DCHECK_EQ(1u, address_list_.size());

    SendConnectError(context, pp_result);
    state_.CompletePendingTransition(false);
  } else {
    // 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()));

    if (address_index_ + 1 < address_list_.size()) {
      DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
      address_index_++;
      StartConnect(context);
    } else {
      SendConnectError(context, pp_result);
      // In order to maintain backward compatibility, allow further attempts to
      // connect the socket.
      state_ = TCPSocketState(TCPSocketState::INITIAL);
    }
  }
}

void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
    const ppapi::host::ReplyMessageContext& context,
    int net_result) {
  DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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
