Home | History | Annotate | Download | only in pepper
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.h"
      6 
      7 #include <cstring>
      8 
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 #include "build/build_config.h"
     12 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
     13 #include "content/browser/renderer_host/pepper/content_browser_pepper_host_factory.h"
     14 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
     15 #include "content/public/browser/browser_context.h"
     16 #include "content/public/browser/browser_thread.h"
     17 #include "content/public/browser/render_process_host.h"
     18 #include "content/public/browser/resource_context.h"
     19 #include "content/public/common/socket_permission_request.h"
     20 #include "net/base/address_family.h"
     21 #include "net/base/host_port_pair.h"
     22 #include "net/base/io_buffer.h"
     23 #include "net/base/net_errors.h"
     24 #include "net/dns/single_request_host_resolver.h"
     25 #include "net/socket/client_socket_factory.h"
     26 #include "net/socket/client_socket_handle.h"
     27 #include "net/socket/ssl_client_socket.h"
     28 #include "net/socket/tcp_client_socket.h"
     29 #include "ppapi/host/dispatch_host_message.h"
     30 #include "ppapi/host/error_conversion.h"
     31 #include "ppapi/host/ppapi_host.h"
     32 #include "ppapi/host/resource_host.h"
     33 #include "ppapi/proxy/ppapi_messages.h"
     34 #include "ppapi/proxy/tcp_socket_resource_base.h"
     35 #include "ppapi/shared_impl/private/net_address_private_impl.h"
     36 
     37 using ppapi::NetAddressPrivateImpl;
     38 using ppapi::host::NetErrorToPepperError;
     39 using ppapi::proxy::TCPSocketResourceBase;
     40 using ppapi::TCPSocketState;
     41 using ppapi::TCPSocketVersion;
     42 
     43 namespace {
     44 
     45 size_t g_num_instances = 0;
     46 
     47 }  // namespace
     48 
     49 namespace content {
     50 
     51 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
     52     ContentBrowserPepperHostFactory* factory,
     53     BrowserPpapiHostImpl* host,
     54     PP_Instance instance,
     55     TCPSocketVersion version)
     56     : version_(version),
     57       external_plugin_(host->external_plugin()),
     58       render_process_id_(0),
     59       render_frame_id_(0),
     60       ppapi_host_(host->GetPpapiHost()),
     61       factory_(factory),
     62       instance_(instance),
     63       state_(TCPSocketState::INITIAL),
     64       end_of_file_reached_(false),
     65       bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
     66       address_index_(0),
     67       socket_(new net::TCPSocket(NULL, net::NetLog::Source())),
     68       ssl_context_helper_(host->ssl_context_helper()),
     69       pending_accept_(false) {
     70   DCHECK(host);
     71   ++g_num_instances;
     72   if (!host->GetRenderFrameIDsForInstance(
     73           instance, &render_process_id_, &render_frame_id_)) {
     74     NOTREACHED();
     75   }
     76 }
     77 
     78 PepperTCPSocketMessageFilter::PepperTCPSocketMessageFilter(
     79     BrowserPpapiHostImpl* host,
     80     PP_Instance instance,
     81     TCPSocketVersion version,
     82     scoped_ptr<net::TCPSocket> socket)
     83     : version_(version),
     84       external_plugin_(host->external_plugin()),
     85       render_process_id_(0),
     86       render_frame_id_(0),
     87       ppapi_host_(host->GetPpapiHost()),
     88       factory_(NULL),
     89       instance_(instance),
     90       state_(TCPSocketState::CONNECTED),
     91       end_of_file_reached_(false),
     92       bind_input_addr_(NetAddressPrivateImpl::kInvalidNetAddress),
     93       address_index_(0),
     94       socket_(socket.Pass()),
     95       ssl_context_helper_(host->ssl_context_helper()),
     96       pending_accept_(false) {
     97   DCHECK(host);
     98   DCHECK_NE(version, ppapi::TCP_SOCKET_VERSION_1_0);
     99 
    100   ++g_num_instances;
    101   if (!host->GetRenderFrameIDsForInstance(
    102           instance, &render_process_id_, &render_frame_id_)) {
    103     NOTREACHED();
    104   }
    105 }
    106 
    107 PepperTCPSocketMessageFilter::~PepperTCPSocketMessageFilter() {
    108   if (socket_)
    109     socket_->Close();
    110   if (ssl_socket_)
    111     ssl_socket_->Disconnect();
    112   --g_num_instances;
    113 }
    114 
    115 // static
    116 size_t PepperTCPSocketMessageFilter::GetNumInstances() {
    117   return g_num_instances;
    118 }
    119 
    120 scoped_refptr<base::TaskRunner>
    121 PepperTCPSocketMessageFilter::OverrideTaskRunnerForMessage(
    122     const IPC::Message& message) {
    123   switch (message.type()) {
    124     case PpapiHostMsg_TCPSocket_Bind::ID:
    125     case PpapiHostMsg_TCPSocket_Connect::ID:
    126     case PpapiHostMsg_TCPSocket_ConnectWithNetAddress::ID:
    127     case PpapiHostMsg_TCPSocket_Listen::ID:
    128       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
    129     case PpapiHostMsg_TCPSocket_SSLHandshake::ID:
    130     case PpapiHostMsg_TCPSocket_Read::ID:
    131     case PpapiHostMsg_TCPSocket_Write::ID:
    132     case PpapiHostMsg_TCPSocket_Accept::ID:
    133     case PpapiHostMsg_TCPSocket_Close::ID:
    134     case PpapiHostMsg_TCPSocket_SetOption::ID:
    135       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
    136   }
    137   return NULL;
    138 }
    139 
    140 int32_t PepperTCPSocketMessageFilter::OnResourceMessageReceived(
    141     const IPC::Message& msg,
    142     ppapi::host::HostMessageContext* context) {
    143   PPAPI_BEGIN_MESSAGE_MAP(PepperTCPSocketMessageFilter, msg)
    144     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Bind, OnMsgBind)
    145     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Connect,
    146                                       OnMsgConnect)
    147     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
    148         PpapiHostMsg_TCPSocket_ConnectWithNetAddress,
    149         OnMsgConnectWithNetAddress)
    150     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SSLHandshake,
    151                                       OnMsgSSLHandshake)
    152     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Read, OnMsgRead)
    153     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Write, OnMsgWrite)
    154     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_Listen,
    155                                       OnMsgListen)
    156     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Accept,
    157                                         OnMsgAccept)
    158     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(PpapiHostMsg_TCPSocket_Close,
    159                                         OnMsgClose)
    160     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_TCPSocket_SetOption,
    161                                       OnMsgSetOption)
    162   PPAPI_END_MESSAGE_MAP()
    163   return PP_ERROR_FAILED;
    164 }
    165 
    166 int32_t PepperTCPSocketMessageFilter::OnMsgBind(
    167     const ppapi::host::HostMessageContext* context,
    168     const PP_NetAddress_Private& net_addr) {
    169   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    170 
    171   // This is only supported by PPB_TCPSocket v1.1 or above.
    172   if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    173     NOTREACHED();
    174     return PP_ERROR_NOACCESS;
    175   }
    176 
    177   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
    178                                              false /* private_api */,
    179                                              NULL,
    180                                              render_process_id_,
    181                                              render_frame_id_)) {
    182     return PP_ERROR_NOACCESS;
    183   }
    184 
    185   bind_input_addr_ = net_addr;
    186 
    187   BrowserThread::PostTask(BrowserThread::IO,
    188                           FROM_HERE,
    189                           base::Bind(&PepperTCPSocketMessageFilter::DoBind,
    190                                      this,
    191                                      context->MakeReplyMessageContext(),
    192                                      net_addr));
    193   return PP_OK_COMPLETIONPENDING;
    194 }
    195 
    196 int32_t PepperTCPSocketMessageFilter::OnMsgConnect(
    197     const ppapi::host::HostMessageContext* context,
    198     const std::string& host,
    199     uint16_t port) {
    200   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    201 
    202   // This is only supported by PPB_TCPSocket_Private.
    203   if (!IsPrivateAPI()) {
    204     NOTREACHED();
    205     return PP_ERROR_NOACCESS;
    206   }
    207 
    208   SocketPermissionRequest request(
    209       SocketPermissionRequest::TCP_CONNECT, host, port);
    210   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
    211                                              true /* private_api */,
    212                                              &request,
    213                                              render_process_id_,
    214                                              render_frame_id_)) {
    215     return PP_ERROR_NOACCESS;
    216   }
    217 
    218   RenderProcessHost* render_process_host =
    219       RenderProcessHost::FromID(render_process_id_);
    220   if (!render_process_host)
    221     return PP_ERROR_FAILED;
    222   BrowserContext* browser_context = render_process_host->GetBrowserContext();
    223   if (!browser_context || !browser_context->GetResourceContext())
    224     return PP_ERROR_FAILED;
    225 
    226   BrowserThread::PostTask(BrowserThread::IO,
    227                           FROM_HERE,
    228                           base::Bind(&PepperTCPSocketMessageFilter::DoConnect,
    229                                      this,
    230                                      context->MakeReplyMessageContext(),
    231                                      host,
    232                                      port,
    233                                      browser_context->GetResourceContext()));
    234   return PP_OK_COMPLETIONPENDING;
    235 }
    236 
    237 int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
    238     const ppapi::host::HostMessageContext* context,
    239     const PP_NetAddress_Private& net_addr) {
    240   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    241 
    242   content::SocketPermissionRequest request =
    243       pepper_socket_utils::CreateSocketPermissionRequest(
    244           content::SocketPermissionRequest::TCP_CONNECT, net_addr);
    245   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
    246                                              IsPrivateAPI(),
    247                                              &request,
    248                                              render_process_id_,
    249                                              render_frame_id_)) {
    250     return PP_ERROR_NOACCESS;
    251   }
    252 
    253   BrowserThread::PostTask(
    254       BrowserThread::IO,
    255       FROM_HERE,
    256       base::Bind(&PepperTCPSocketMessageFilter::DoConnectWithNetAddress,
    257                  this,
    258                  context->MakeReplyMessageContext(),
    259                  net_addr));
    260   return PP_OK_COMPLETIONPENDING;
    261 }
    262 
    263 int32_t PepperTCPSocketMessageFilter::OnMsgSSLHandshake(
    264     const ppapi::host::HostMessageContext* context,
    265     const std::string& server_name,
    266     uint16_t server_port,
    267     const std::vector<std::vector<char> >& trusted_certs,
    268     const std::vector<std::vector<char> >& untrusted_certs) {
    269   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    270 
    271   // Allow to do SSL handshake only if currently the socket has been connected
    272   // and there isn't pending read or write.
    273   if (!state_.IsValidTransition(TCPSocketState::SSL_CONNECT) ||
    274       read_buffer_.get() || write_buffer_base_.get() || write_buffer_.get()) {
    275     return PP_ERROR_FAILED;
    276   }
    277 
    278   // TODO(raymes,rsleevi): Use trusted/untrusted certificates when connecting.
    279   net::IPEndPoint peer_address;
    280   if (socket_->GetPeerAddress(&peer_address) != net::OK)
    281     return PP_ERROR_FAILED;
    282 
    283   scoped_ptr<net::ClientSocketHandle> handle(new net::ClientSocketHandle());
    284   handle->SetSocket(make_scoped_ptr<net::StreamSocket>(
    285       new net::TCPClientSocket(socket_.Pass(), peer_address)));
    286   net::ClientSocketFactory* factory =
    287       net::ClientSocketFactory::GetDefaultFactory();
    288   net::HostPortPair host_port_pair(server_name, server_port);
    289   net::SSLClientSocketContext ssl_context;
    290   ssl_context.cert_verifier = ssl_context_helper_->GetCertVerifier();
    291   ssl_context.transport_security_state =
    292       ssl_context_helper_->GetTransportSecurityState();
    293   ssl_socket_ =
    294       factory->CreateSSLClientSocket(handle.Pass(),
    295                                      host_port_pair,
    296                                      ssl_context_helper_->ssl_config(),
    297                                      ssl_context);
    298   if (!ssl_socket_) {
    299     LOG(WARNING) << "Failed to create an SSL client socket.";
    300     state_.CompletePendingTransition(false);
    301     return PP_ERROR_FAILED;
    302   }
    303 
    304   state_.SetPendingTransition(TCPSocketState::SSL_CONNECT);
    305 
    306   const ppapi::host::ReplyMessageContext reply_context(
    307       context->MakeReplyMessageContext());
    308   int net_result = ssl_socket_->Connect(
    309       base::Bind(&PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted,
    310                  base::Unretained(this),
    311                  reply_context));
    312   if (net_result != net::ERR_IO_PENDING)
    313     OnSSLHandshakeCompleted(reply_context, net_result);
    314   return PP_OK_COMPLETIONPENDING;
    315 }
    316 
    317 int32_t PepperTCPSocketMessageFilter::OnMsgRead(
    318     const ppapi::host::HostMessageContext* context,
    319     int32_t bytes_to_read) {
    320   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    321   if (!state_.IsConnected() || end_of_file_reached_)
    322     return PP_ERROR_FAILED;
    323   if (read_buffer_.get())
    324     return PP_ERROR_INPROGRESS;
    325   if (bytes_to_read <= 0 ||
    326       bytes_to_read > TCPSocketResourceBase::kMaxReadSize) {
    327     return PP_ERROR_BADARGUMENT;
    328   }
    329 
    330   ppapi::host::ReplyMessageContext reply_context(
    331       context->MakeReplyMessageContext());
    332   read_buffer_ = new net::IOBuffer(bytes_to_read);
    333 
    334   int net_result = net::ERR_FAILED;
    335   if (socket_) {
    336     DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
    337     net_result =
    338         socket_->Read(read_buffer_.get(),
    339                       bytes_to_read,
    340                       base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
    341                                  base::Unretained(this),
    342                                  reply_context));
    343   } else if (ssl_socket_) {
    344     DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
    345     net_result = ssl_socket_->Read(
    346         read_buffer_.get(),
    347         bytes_to_read,
    348         base::Bind(&PepperTCPSocketMessageFilter::OnReadCompleted,
    349                    base::Unretained(this),
    350                    reply_context));
    351   }
    352   if (net_result != net::ERR_IO_PENDING)
    353     OnReadCompleted(reply_context, net_result);
    354   return PP_OK_COMPLETIONPENDING;
    355 }
    356 
    357 int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
    358     const ppapi::host::HostMessageContext* context,
    359     const std::string& data) {
    360   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    361 
    362   if (!state_.IsConnected())
    363     return PP_ERROR_FAILED;
    364   if (write_buffer_base_.get() || write_buffer_.get())
    365     return PP_ERROR_INPROGRESS;
    366 
    367   size_t data_size = data.size();
    368   if (data_size == 0 ||
    369       data_size > static_cast<size_t>(TCPSocketResourceBase::kMaxWriteSize)) {
    370     return PP_ERROR_BADARGUMENT;
    371   }
    372 
    373   write_buffer_base_ = new net::IOBuffer(data_size);
    374   memcpy(write_buffer_base_->data(), data.data(), data_size);
    375   write_buffer_ =
    376       new net::DrainableIOBuffer(write_buffer_base_.get(), data_size);
    377   DoWrite(context->MakeReplyMessageContext());
    378   return PP_OK_COMPLETIONPENDING;
    379 }
    380 
    381 int32_t PepperTCPSocketMessageFilter::OnMsgListen(
    382     const ppapi::host::HostMessageContext* context,
    383     int32_t backlog) {
    384   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    385 
    386   // This is only supported by PPB_TCPSocket v1.1 or above.
    387   if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    388     NOTREACHED();
    389     return PP_ERROR_NOACCESS;
    390   }
    391 
    392   content::SocketPermissionRequest request =
    393       pepper_socket_utils::CreateSocketPermissionRequest(
    394           content::SocketPermissionRequest::TCP_LISTEN, bind_input_addr_);
    395   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
    396                                              false /* private_api */,
    397                                              &request,
    398                                              render_process_id_,
    399                                              render_frame_id_)) {
    400     return PP_ERROR_NOACCESS;
    401   }
    402 
    403   BrowserThread::PostTask(BrowserThread::IO,
    404                           FROM_HERE,
    405                           base::Bind(&PepperTCPSocketMessageFilter::DoListen,
    406                                      this,
    407                                      context->MakeReplyMessageContext(),
    408                                      backlog));
    409   return PP_OK_COMPLETIONPENDING;
    410 }
    411 
    412 int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
    413     const ppapi::host::HostMessageContext* context) {
    414   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    415 
    416   if (pending_accept_)
    417     return PP_ERROR_INPROGRESS;
    418   if (state_.state() != TCPSocketState::LISTENING)
    419     return PP_ERROR_FAILED;
    420 
    421   pending_accept_ = true;
    422   ppapi::host::ReplyMessageContext reply_context(
    423       context->MakeReplyMessageContext());
    424   int net_result = socket_->Accept(
    425       &accepted_socket_,
    426       &accepted_address_,
    427       base::Bind(&PepperTCPSocketMessageFilter::OnAcceptCompleted,
    428                  base::Unretained(this),
    429                  reply_context));
    430   if (net_result != net::ERR_IO_PENDING)
    431     OnAcceptCompleted(reply_context, net_result);
    432   return PP_OK_COMPLETIONPENDING;
    433 }
    434 
    435 int32_t PepperTCPSocketMessageFilter::OnMsgClose(
    436     const ppapi::host::HostMessageContext* context) {
    437   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    438   if (state_.state() == TCPSocketState::CLOSED)
    439     return PP_OK;
    440 
    441   state_.DoTransition(TCPSocketState::CLOSE, true);
    442   // Make sure we get no further callbacks from |socket_| or |ssl_socket_|.
    443   if (socket_) {
    444     socket_->Close();
    445   } else if (ssl_socket_) {
    446     ssl_socket_->Disconnect();
    447   }
    448   return PP_OK;
    449 }
    450 
    451 int32_t PepperTCPSocketMessageFilter::OnMsgSetOption(
    452     const ppapi::host::HostMessageContext* context,
    453     PP_TCPSocket_Option name,
    454     const ppapi::SocketOptionData& value) {
    455   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    456 
    457   switch (name) {
    458     case PP_TCPSOCKET_OPTION_NO_DELAY: {
    459       if (state_.state() != TCPSocketState::CONNECTED)
    460         return PP_ERROR_FAILED;
    461 
    462       bool boolean_value = false;
    463       if (!value.GetBool(&boolean_value))
    464         return PP_ERROR_BADARGUMENT;
    465       return socket_->SetNoDelay(boolean_value) ? PP_OK : PP_ERROR_FAILED;
    466     }
    467     case PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE:
    468     case PP_TCPSOCKET_OPTION_RECV_BUFFER_SIZE: {
    469       if (state_.state() != TCPSocketState::CONNECTED)
    470         return PP_ERROR_FAILED;
    471 
    472       int32_t integer_value = 0;
    473       if (!value.GetInt32(&integer_value) || integer_value <= 0)
    474         return PP_ERROR_BADARGUMENT;
    475 
    476       int net_result = net::ERR_UNEXPECTED;
    477       if (name == PP_TCPSOCKET_OPTION_SEND_BUFFER_SIZE) {
    478         if (integer_value > TCPSocketResourceBase::kMaxSendBufferSize)
    479           return PP_ERROR_BADARGUMENT;
    480         net_result = socket_->SetSendBufferSize(integer_value);
    481       } else {
    482         if (integer_value > TCPSocketResourceBase::kMaxReceiveBufferSize)
    483           return PP_ERROR_BADARGUMENT;
    484         net_result = socket_->SetReceiveBufferSize(integer_value);
    485       }
    486       // TODO(wtc): Add error mapping code.
    487       return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED;
    488     }
    489     default: {
    490       NOTREACHED();
    491       return PP_ERROR_BADARGUMENT;
    492     }
    493   }
    494 }
    495 
    496 void PepperTCPSocketMessageFilter::DoBind(
    497     const ppapi::host::ReplyMessageContext& context,
    498     const PP_NetAddress_Private& net_addr) {
    499   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    500 
    501   if (state_.IsPending(TCPSocketState::BIND)) {
    502     SendBindError(context, PP_ERROR_INPROGRESS);
    503     return;
    504   }
    505   if (!state_.IsValidTransition(TCPSocketState::BIND)) {
    506     SendBindError(context, PP_ERROR_FAILED);
    507     return;
    508   }
    509 
    510   int pp_result = PP_OK;
    511   do {
    512     net::IPAddressNumber address;
    513     int port;
    514     if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
    515             net_addr, &address, &port)) {
    516       pp_result = PP_ERROR_ADDRESS_INVALID;
    517       break;
    518     }
    519     net::IPEndPoint bind_addr(address, port);
    520 
    521     DCHECK(!socket_->IsValid());
    522     pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
    523     if (pp_result != PP_OK)
    524       break;
    525 
    526     pp_result = NetErrorToPepperError(socket_->SetDefaultOptionsForServer());
    527     if (pp_result != PP_OK)
    528       break;
    529 
    530     pp_result = NetErrorToPepperError(socket_->Bind(bind_addr));
    531     if (pp_result != PP_OK)
    532       break;
    533 
    534     net::IPEndPoint ip_end_point_local;
    535     pp_result =
    536         NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
    537     if (pp_result != PP_OK)
    538       break;
    539 
    540     PP_NetAddress_Private local_addr =
    541         NetAddressPrivateImpl::kInvalidNetAddress;
    542     if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    543             ip_end_point_local.address(),
    544             ip_end_point_local.port(),
    545             &local_addr)) {
    546       pp_result = PP_ERROR_ADDRESS_INVALID;
    547       break;
    548     }
    549 
    550     SendBindReply(context, PP_OK, local_addr);
    551     state_.DoTransition(TCPSocketState::BIND, true);
    552     return;
    553   } while (false);
    554   if (socket_->IsValid())
    555     socket_->Close();
    556   SendBindError(context, pp_result);
    557   state_.DoTransition(TCPSocketState::BIND, false);
    558 }
    559 
    560 void PepperTCPSocketMessageFilter::DoConnect(
    561     const ppapi::host::ReplyMessageContext& context,
    562     const std::string& host,
    563     uint16_t port,
    564     ResourceContext* resource_context) {
    565   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    566 
    567   if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
    568     SendConnectError(context, PP_ERROR_FAILED);
    569     return;
    570   }
    571 
    572   state_.SetPendingTransition(TCPSocketState::CONNECT);
    573   address_index_ = 0;
    574   address_list_.clear();
    575   net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port));
    576   resolver_.reset(
    577       new net::SingleRequestHostResolver(resource_context->GetHostResolver()));
    578   int net_result = resolver_->Resolve(
    579       request_info,
    580       net::DEFAULT_PRIORITY,
    581       &address_list_,
    582       base::Bind(&PepperTCPSocketMessageFilter::OnResolveCompleted,
    583                  base::Unretained(this),
    584                  context),
    585       net::BoundNetLog());
    586   if (net_result != net::ERR_IO_PENDING)
    587     OnResolveCompleted(context, net_result);
    588 }
    589 
    590 void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
    591     const ppapi::host::ReplyMessageContext& context,
    592     const PP_NetAddress_Private& net_addr) {
    593   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    594 
    595   if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
    596     SendConnectError(context, PP_ERROR_FAILED);
    597     return;
    598   }
    599 
    600   state_.SetPendingTransition(TCPSocketState::CONNECT);
    601 
    602   net::IPAddressNumber address;
    603   int port;
    604   if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
    605           net_addr, &address, &port)) {
    606     state_.CompletePendingTransition(false);
    607     SendConnectError(context, PP_ERROR_ADDRESS_INVALID);
    608     return;
    609   }
    610 
    611   // Copy the single IPEndPoint to address_list_.
    612   address_index_ = 0;
    613   address_list_.clear();
    614   address_list_.push_back(net::IPEndPoint(address, port));
    615   StartConnect(context);
    616 }
    617 
    618 void PepperTCPSocketMessageFilter::DoWrite(
    619     const ppapi::host::ReplyMessageContext& context) {
    620   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    621   DCHECK(write_buffer_base_.get());
    622   DCHECK(write_buffer_.get());
    623   DCHECK_GT(write_buffer_->BytesRemaining(), 0);
    624   DCHECK(state_.IsConnected());
    625 
    626   int net_result = net::ERR_FAILED;
    627   if (socket_) {
    628     DCHECK_EQ(state_.state(), TCPSocketState::CONNECTED);
    629     net_result = socket_->Write(
    630         write_buffer_.get(),
    631         write_buffer_->BytesRemaining(),
    632         base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
    633                    base::Unretained(this),
    634                    context));
    635   } else if (ssl_socket_) {
    636     DCHECK_EQ(state_.state(), TCPSocketState::SSL_CONNECTED);
    637     net_result = ssl_socket_->Write(
    638         write_buffer_.get(),
    639         write_buffer_->BytesRemaining(),
    640         base::Bind(&PepperTCPSocketMessageFilter::OnWriteCompleted,
    641                    base::Unretained(this),
    642                    context));
    643   }
    644   if (net_result != net::ERR_IO_PENDING)
    645     OnWriteCompleted(context, net_result);
    646 }
    647 
    648 void PepperTCPSocketMessageFilter::DoListen(
    649     const ppapi::host::ReplyMessageContext& context,
    650     int32_t backlog) {
    651   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    652 
    653   if (state_.IsPending(TCPSocketState::LISTEN)) {
    654     SendListenReply(context, PP_ERROR_INPROGRESS);
    655     return;
    656   }
    657   if (!state_.IsValidTransition(TCPSocketState::LISTEN)) {
    658     SendListenReply(context, PP_ERROR_FAILED);
    659     return;
    660   }
    661 
    662   int32_t pp_result = NetErrorToPepperError(socket_->Listen(backlog));
    663   SendListenReply(context, pp_result);
    664   state_.DoTransition(TCPSocketState::LISTEN, pp_result == PP_OK);
    665 }
    666 
    667 void PepperTCPSocketMessageFilter::OnResolveCompleted(
    668     const ppapi::host::ReplyMessageContext& context,
    669     int net_result) {
    670   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    671 
    672   if (!state_.IsPending(TCPSocketState::CONNECT)) {
    673     DCHECK(state_.state() == TCPSocketState::CLOSED);
    674     SendConnectError(context, PP_ERROR_FAILED);
    675     return;
    676   }
    677 
    678   if (net_result != net::OK) {
    679     SendConnectError(context, NetErrorToPepperError(net_result));
    680     state_.CompletePendingTransition(false);
    681     return;
    682   }
    683 
    684   StartConnect(context);
    685 }
    686 
    687 void PepperTCPSocketMessageFilter::StartConnect(
    688     const ppapi::host::ReplyMessageContext& context) {
    689   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    690   DCHECK(state_.IsPending(TCPSocketState::CONNECT));
    691   DCHECK_LT(address_index_, address_list_.size());
    692 
    693   int net_result = net::OK;
    694   if (!socket_->IsValid())
    695     net_result = socket_->Open(address_list_[address_index_].GetFamily());
    696 
    697   if (net_result == net::OK) {
    698     net_result = socket_->Connect(
    699         address_list_[address_index_],
    700         base::Bind(&PepperTCPSocketMessageFilter::OnConnectCompleted,
    701                    base::Unretained(this),
    702                    context));
    703   }
    704   if (net_result != net::ERR_IO_PENDING)
    705     OnConnectCompleted(context, net_result);
    706 }
    707 
    708 void PepperTCPSocketMessageFilter::OnConnectCompleted(
    709     const ppapi::host::ReplyMessageContext& context,
    710     int net_result) {
    711   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    712 
    713   if (!state_.IsPending(TCPSocketState::CONNECT)) {
    714     DCHECK(state_.state() == TCPSocketState::CLOSED);
    715     SendConnectError(context, PP_ERROR_FAILED);
    716     return;
    717   }
    718 
    719   int32_t pp_result = NetErrorToPepperError(net_result);
    720   do {
    721     if (pp_result != PP_OK)
    722       break;
    723 
    724     net::IPEndPoint ip_end_point_local;
    725     net::IPEndPoint ip_end_point_remote;
    726     pp_result =
    727         NetErrorToPepperError(socket_->GetLocalAddress(&ip_end_point_local));
    728     if (pp_result != PP_OK)
    729       break;
    730     pp_result =
    731         NetErrorToPepperError(socket_->GetPeerAddress(&ip_end_point_remote));
    732     if (pp_result != PP_OK)
    733       break;
    734 
    735     PP_NetAddress_Private local_addr =
    736         NetAddressPrivateImpl::kInvalidNetAddress;
    737     PP_NetAddress_Private remote_addr =
    738         NetAddressPrivateImpl::kInvalidNetAddress;
    739     if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    740             ip_end_point_local.address(),
    741             ip_end_point_local.port(),
    742             &local_addr) ||
    743         !NetAddressPrivateImpl::IPEndPointToNetAddress(
    744             ip_end_point_remote.address(),
    745             ip_end_point_remote.port(),
    746             &remote_addr)) {
    747       pp_result = PP_ERROR_ADDRESS_INVALID;
    748       break;
    749     }
    750 
    751     socket_->SetDefaultOptionsForClient();
    752     SendConnectReply(context, PP_OK, local_addr, remote_addr);
    753     state_.CompletePendingTransition(true);
    754     return;
    755   } while (false);
    756 
    757   if (version_ == ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
    758     DCHECK_EQ(1u, address_list_.size());
    759 
    760     SendConnectError(context, pp_result);
    761     state_.CompletePendingTransition(false);
    762   } else {
    763     // We have to recreate |socket_| because it doesn't allow a second connect
    764     // attempt. We won't lose any state such as bound address or set options,
    765     // because in the private or v1.0 API, connect must be the first operation.
    766     socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
    767 
    768     if (address_index_ + 1 < address_list_.size()) {
    769       DCHECK_EQ(version_, ppapi::TCP_SOCKET_VERSION_PRIVATE);
    770       address_index_++;
    771       StartConnect(context);
    772     } else {
    773       SendConnectError(context, pp_result);
    774       // In order to maintain backward compatibility, allow further attempts to
    775       // connect the socket.
    776       state_ = TCPSocketState(TCPSocketState::INITIAL);
    777     }
    778   }
    779 }
    780 
    781 void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
    782     const ppapi::host::ReplyMessageContext& context,
    783     int net_result) {
    784   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    785 
    786   if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
    787     DCHECK(state_.state() == TCPSocketState::CLOSED);
    788     SendSSLHandshakeReply(context, PP_ERROR_FAILED);
    789     return;
    790   }
    791 
    792   SendSSLHandshakeReply(context, NetErrorToPepperError(net_result));
    793   state_.CompletePendingTransition(net_result == net::OK);
    794 }
    795 
    796 void PepperTCPSocketMessageFilter::OnReadCompleted(
    797     const ppapi::host::ReplyMessageContext& context,
    798     int net_result) {
    799   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    800   DCHECK(read_buffer_.get());
    801 
    802   if (net_result > 0) {
    803     SendReadReply(
    804         context, PP_OK, std::string(read_buffer_->data(), net_result));
    805   } else if (net_result == 0) {
    806     end_of_file_reached_ = true;
    807     SendReadReply(context, PP_OK, std::string());
    808   } else {
    809     SendReadError(context, NetErrorToPepperError(net_result));
    810   }
    811   read_buffer_ = NULL;
    812 }
    813 
    814 void PepperTCPSocketMessageFilter::OnWriteCompleted(
    815     const ppapi::host::ReplyMessageContext& context,
    816     int net_result) {
    817   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    818   DCHECK(write_buffer_base_.get());
    819   DCHECK(write_buffer_.get());
    820 
    821   // Note: For partial writes of 0 bytes, don't continue writing to avoid a
    822   // likely infinite loop.
    823   if (net_result > 0) {
    824     write_buffer_->DidConsume(net_result);
    825     if (write_buffer_->BytesRemaining() > 0 && state_.IsConnected()) {
    826       DoWrite(context);
    827       return;
    828     }
    829   }
    830 
    831   if (net_result >= 0)
    832     SendWriteReply(context, write_buffer_->BytesConsumed());
    833   else
    834     SendWriteReply(context, NetErrorToPepperError(net_result));
    835 
    836   write_buffer_ = NULL;
    837   write_buffer_base_ = NULL;
    838 }
    839 
    840 void PepperTCPSocketMessageFilter::OnAcceptCompleted(
    841     const ppapi::host::ReplyMessageContext& context,
    842     int net_result) {
    843   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    844   DCHECK(pending_accept_);
    845 
    846   pending_accept_ = false;
    847 
    848   if (net_result != net::OK) {
    849     SendAcceptError(context, NetErrorToPepperError(net_result));
    850     return;
    851   }
    852 
    853   DCHECK(accepted_socket_.get());
    854 
    855   net::IPEndPoint ip_end_point_local;
    856   PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
    857   PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
    858 
    859   int32_t pp_result = NetErrorToPepperError(
    860       accepted_socket_->GetLocalAddress(&ip_end_point_local));
    861   if (pp_result != PP_OK) {
    862     SendAcceptError(context, pp_result);
    863     return;
    864   }
    865   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    866           ip_end_point_local.address(),
    867           ip_end_point_local.port(),
    868           &local_addr) ||
    869       !NetAddressPrivateImpl::IPEndPointToNetAddress(
    870           accepted_address_.address(),
    871           accepted_address_.port(),
    872           &remote_addr)) {
    873     SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
    874     return;
    875   }
    876 
    877   // |factory_| is guaranteed to be non-NULL here. Only those instances created
    878   // in CONNECTED state have a NULL |factory_|, while getting here requires
    879   // LISTENING state.
    880   scoped_ptr<ppapi::host::ResourceHost> host =
    881       factory_->CreateAcceptedTCPSocket(
    882           instance_, version_, accepted_socket_.Pass());
    883   if (!host) {
    884     SendAcceptError(context, PP_ERROR_NOSPACE);
    885     return;
    886   }
    887   int pending_host_id = ppapi_host_->AddPendingResourceHost(host.Pass());
    888   if (pending_host_id)
    889     SendAcceptReply(context, PP_OK, pending_host_id, local_addr, remote_addr);
    890   else
    891     SendAcceptError(context, PP_ERROR_NOSPACE);
    892 }
    893 
    894 void PepperTCPSocketMessageFilter::SendBindReply(
    895     const ppapi::host::ReplyMessageContext& context,
    896     int32_t pp_result,
    897     const PP_NetAddress_Private& local_addr) {
    898   ppapi::host::ReplyMessageContext reply_context(context);
    899   reply_context.params.set_result(pp_result);
    900   SendReply(reply_context, PpapiPluginMsg_TCPSocket_BindReply(local_addr));
    901 }
    902 
    903 void PepperTCPSocketMessageFilter::SendBindError(
    904     const ppapi::host::ReplyMessageContext& context,
    905     int32_t pp_error) {
    906   SendBindReply(context, pp_error, NetAddressPrivateImpl::kInvalidNetAddress);
    907 }
    908 
    909 void PepperTCPSocketMessageFilter::SendConnectReply(
    910     const ppapi::host::ReplyMessageContext& context,
    911     int32_t pp_result,
    912     const PP_NetAddress_Private& local_addr,
    913     const PP_NetAddress_Private& remote_addr) {
    914   ppapi::host::ReplyMessageContext reply_context(context);
    915   reply_context.params.set_result(pp_result);
    916   SendReply(reply_context,
    917             PpapiPluginMsg_TCPSocket_ConnectReply(local_addr, remote_addr));
    918 }
    919 
    920 void PepperTCPSocketMessageFilter::SendConnectError(
    921     const ppapi::host::ReplyMessageContext& context,
    922     int32_t pp_error) {
    923   SendConnectReply(context,
    924                    pp_error,
    925                    NetAddressPrivateImpl::kInvalidNetAddress,
    926                    NetAddressPrivateImpl::kInvalidNetAddress);
    927 }
    928 
    929 void PepperTCPSocketMessageFilter::SendSSLHandshakeReply(
    930     const ppapi::host::ReplyMessageContext& context,
    931     int32_t pp_result) {
    932   ppapi::host::ReplyMessageContext reply_context(context);
    933   reply_context.params.set_result(pp_result);
    934   ppapi::PPB_X509Certificate_Fields certificate_fields;
    935   if (pp_result == PP_OK) {
    936     // Our socket is guaranteed to be an SSL socket if we get here.
    937     net::SSLInfo ssl_info;
    938     ssl_socket_->GetSSLInfo(&ssl_info);
    939     if (ssl_info.cert.get()) {
    940       pepper_socket_utils::GetCertificateFields(*ssl_info.cert.get(),
    941                                                 &certificate_fields);
    942     }
    943   }
    944   SendReply(reply_context,
    945             PpapiPluginMsg_TCPSocket_SSLHandshakeReply(certificate_fields));
    946 }
    947 
    948 void PepperTCPSocketMessageFilter::SendReadReply(
    949     const ppapi::host::ReplyMessageContext& context,
    950     int32_t pp_result,
    951     const std::string& data) {
    952   ppapi::host::ReplyMessageContext reply_context(context);
    953   reply_context.params.set_result(pp_result);
    954   SendReply(reply_context, PpapiPluginMsg_TCPSocket_ReadReply(data));
    955 }
    956 
    957 void PepperTCPSocketMessageFilter::SendReadError(
    958     const ppapi::host::ReplyMessageContext& context,
    959     int32_t pp_error) {
    960   SendReadReply(context, pp_error, std::string());
    961 }
    962 
    963 void PepperTCPSocketMessageFilter::SendWriteReply(
    964     const ppapi::host::ReplyMessageContext& context,
    965     int32_t pp_result) {
    966   ppapi::host::ReplyMessageContext reply_context(context);
    967   reply_context.params.set_result(pp_result);
    968   SendReply(reply_context, PpapiPluginMsg_TCPSocket_WriteReply());
    969 }
    970 
    971 void PepperTCPSocketMessageFilter::SendListenReply(
    972     const ppapi::host::ReplyMessageContext& context,
    973     int32_t pp_result) {
    974   ppapi::host::ReplyMessageContext reply_context(context);
    975   reply_context.params.set_result(pp_result);
    976   SendReply(reply_context, PpapiPluginMsg_TCPSocket_ListenReply());
    977 }
    978 
    979 void PepperTCPSocketMessageFilter::SendAcceptReply(
    980     const ppapi::host::ReplyMessageContext& context,
    981     int32_t pp_result,
    982     int pending_host_id,
    983     const PP_NetAddress_Private& local_addr,
    984     const PP_NetAddress_Private& remote_addr) {
    985   ppapi::host::ReplyMessageContext reply_context(context);
    986   reply_context.params.set_result(pp_result);
    987   SendReply(reply_context,
    988             PpapiPluginMsg_TCPSocket_AcceptReply(
    989                 pending_host_id, local_addr, remote_addr));
    990 }
    991 
    992 void PepperTCPSocketMessageFilter::SendAcceptError(
    993     const ppapi::host::ReplyMessageContext& context,
    994     int32_t pp_error) {
    995   SendAcceptReply(context,
    996                   pp_error,
    997                   0,
    998                   NetAddressPrivateImpl::kInvalidNetAddress,
    999                   NetAddressPrivateImpl::kInvalidNetAddress);
   1000 }
   1001 
   1002 }  // namespace content
   1003