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_server_socket_message_filter.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/logging.h"
     10 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
     11 #include "content/browser/renderer_host/pepper/pepper_socket_utils.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "content/public/common/socket_permission_request.h"
     14 #include "net/base/ip_endpoint.h"
     15 #include "net/base/net_errors.h"
     16 #include "net/base/net_util.h"
     17 #include "net/socket/tcp_client_socket.h"
     18 #include "net/socket/tcp_server_socket.h"
     19 #include "ppapi/c/pp_errors.h"
     20 #include "ppapi/c/private/ppb_net_address_private.h"
     21 #include "ppapi/host/dispatch_host_message.h"
     22 #include "ppapi/host/error_conversion.h"
     23 #include "ppapi/proxy/ppapi_messages.h"
     24 #include "ppapi/shared_impl/api_id.h"
     25 #include "ppapi/shared_impl/private/net_address_private_impl.h"
     26 
     27 using ppapi::NetAddressPrivateImpl;
     28 using ppapi::host::NetErrorToPepperError;
     29 
     30 namespace {
     31 
     32 size_t g_num_instances = 0;
     33 
     34 }  // namespace
     35 
     36 namespace content {
     37 
     38 PepperTCPServerSocketMessageFilter::PepperTCPServerSocketMessageFilter(
     39     BrowserPpapiHostImpl* host,
     40     PP_Instance instance,
     41     bool private_api,
     42     const scoped_refptr<PepperMessageFilter>& pepper_message_filter)
     43     : state_(STATE_BEFORE_LISTENING),
     44       pepper_message_filter_(pepper_message_filter),
     45       external_plugin_(host->external_plugin()),
     46       private_api_(private_api),
     47       render_process_id_(0),
     48       render_view_id_(0) {
     49   ++g_num_instances;
     50   DCHECK(host);
     51   if (!host->GetRenderViewIDsForInstance(instance,
     52                                          &render_process_id_,
     53                                          &render_view_id_)) {
     54     NOTREACHED();
     55   }
     56 }
     57 
     58 PepperTCPServerSocketMessageFilter::~PepperTCPServerSocketMessageFilter() {
     59   --g_num_instances;
     60 }
     61 
     62 // static
     63 size_t PepperTCPServerSocketMessageFilter::GetNumInstances() {
     64   return g_num_instances;
     65 }
     66 
     67 scoped_refptr<base::TaskRunner>
     68 PepperTCPServerSocketMessageFilter::OverrideTaskRunnerForMessage(
     69     const IPC::Message& message) {
     70   switch (message.type()) {
     71     case PpapiHostMsg_TCPServerSocket_Listen::ID:
     72       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
     73     case PpapiHostMsg_TCPServerSocket_Accept::ID:
     74     case PpapiHostMsg_TCPServerSocket_StopListening::ID:
     75       return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
     76   }
     77   return NULL;
     78 }
     79 
     80 int32_t PepperTCPServerSocketMessageFilter::OnResourceMessageReceived(
     81     const IPC::Message& msg,
     82     ppapi::host::HostMessageContext* context) {
     83   IPC_BEGIN_MESSAGE_MAP(PepperTCPServerSocketMessageFilter, msg)
     84     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
     85         PpapiHostMsg_TCPServerSocket_Listen, OnMsgListen)
     86     PPAPI_DISPATCH_HOST_RESOURCE_CALL(
     87         PpapiHostMsg_TCPServerSocket_Accept, OnMsgAccept)
     88     PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
     89         PpapiHostMsg_TCPServerSocket_StopListening, OnMsgStopListening)
     90   IPC_END_MESSAGE_MAP()
     91   return PP_ERROR_FAILED;
     92 }
     93 
     94 int32_t PepperTCPServerSocketMessageFilter::OnMsgListen(
     95     const ppapi::host::HostMessageContext* context,
     96     const PP_NetAddress_Private& addr,
     97     int32_t backlog) {
     98   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     99   DCHECK(context);
    100 
    101   SocketPermissionRequest request =
    102       pepper_socket_utils::CreateSocketPermissionRequest(
    103           content::SocketPermissionRequest::TCP_LISTEN, addr);
    104   if (!pepper_socket_utils::CanUseSocketAPIs(external_plugin_,
    105                                              private_api_,
    106                                              request,
    107                                              render_process_id_,
    108                                              render_view_id_)) {
    109     return PP_ERROR_NOACCESS;
    110   }
    111 
    112   BrowserThread::PostTask(
    113       BrowserThread::IO, FROM_HERE,
    114       base::Bind(&PepperTCPServerSocketMessageFilter::DoListen, this,
    115                  context->MakeReplyMessageContext(), addr, backlog));
    116   return PP_OK_COMPLETIONPENDING;
    117 }
    118 
    119 int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
    120     const ppapi::host::HostMessageContext* context,
    121     uint32 plugin_dispatcher_id) {
    122   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    123   DCHECK(context);
    124 
    125   if (state_ != STATE_LISTENING)
    126     return PP_ERROR_FAILED;
    127 
    128   state_ = STATE_ACCEPT_IN_PROGRESS;
    129   ppapi::host::ReplyMessageContext reply_context(
    130       context->MakeReplyMessageContext());
    131   int net_result = socket_->Accept(
    132       &socket_buffer_,
    133       base::Bind(&PepperTCPServerSocketMessageFilter::OnAcceptCompleted,
    134                  base::Unretained(this),
    135                  reply_context, plugin_dispatcher_id));
    136   if (net_result != net::ERR_IO_PENDING)
    137     OnAcceptCompleted(reply_context, plugin_dispatcher_id, net_result);
    138   return PP_OK_COMPLETIONPENDING;
    139 }
    140 
    141 int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening(
    142     const ppapi::host::HostMessageContext* context) {
    143   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    144   DCHECK(context);
    145 
    146   state_ = STATE_CLOSED;
    147   socket_.reset();
    148   return PP_OK;
    149 }
    150 
    151 void PepperTCPServerSocketMessageFilter::DoListen(
    152     const ppapi::host::ReplyMessageContext& context,
    153     const PP_NetAddress_Private& addr,
    154     int32_t backlog) {
    155   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    156 
    157   net::IPAddressNumber address;
    158   int port;
    159   if (state_ != STATE_BEFORE_LISTENING ||
    160       !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
    161     SendListenError(context, PP_ERROR_FAILED);
    162     state_ = STATE_CLOSED;
    163     return;
    164   }
    165 
    166   state_ = STATE_LISTEN_IN_PROGRESS;
    167 
    168   socket_.reset(new net::TCPServerSocket(NULL, net::NetLog::Source()));
    169   int net_result = socket_->Listen(net::IPEndPoint(address, port), backlog);
    170   if (net_result != net::ERR_IO_PENDING)
    171     OnListenCompleted(context, net_result);
    172 }
    173 
    174 void PepperTCPServerSocketMessageFilter::OnListenCompleted(
    175     const ppapi::host::ReplyMessageContext& context,
    176     int net_result) {
    177   if (state_ != STATE_LISTEN_IN_PROGRESS) {
    178     SendListenError(context, PP_ERROR_FAILED);
    179     state_ = STATE_CLOSED;
    180     return;
    181   }
    182   if (net_result != net::OK) {
    183     SendListenError(context, NetErrorToPepperError(net_result));
    184     state_ = STATE_BEFORE_LISTENING;
    185     return;
    186   }
    187 
    188   DCHECK(socket_.get());
    189 
    190   net::IPEndPoint end_point;
    191   PP_NetAddress_Private addr;
    192 
    193   int32_t pp_result =
    194       NetErrorToPepperError(socket_->GetLocalAddress(&end_point));
    195   if (pp_result != PP_OK) {
    196     SendListenError(context, pp_result);
    197     state_ = STATE_BEFORE_LISTENING;
    198     return;
    199   }
    200   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(end_point.address(),
    201                                                      end_point.port(),
    202                                                      &addr)) {
    203     SendListenError(context, PP_ERROR_FAILED);
    204     state_ = STATE_BEFORE_LISTENING;
    205     return;
    206   }
    207 
    208   SendListenReply(context, PP_OK, addr);
    209   state_ = STATE_LISTENING;
    210 }
    211 
    212 void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
    213     const ppapi::host::ReplyMessageContext& context,
    214     uint32 plugin_dispatcher_id,
    215     int net_result) {
    216   if (state_ != STATE_ACCEPT_IN_PROGRESS) {
    217     SendAcceptError(context, PP_ERROR_FAILED);
    218     state_ = STATE_CLOSED;
    219     return;
    220   }
    221 
    222   state_ = STATE_LISTENING;
    223 
    224   if (net_result != net::OK) {
    225     SendAcceptError(context, NetErrorToPepperError(net_result));
    226     return;
    227   }
    228 
    229   DCHECK(socket_buffer_.get());
    230 
    231   scoped_ptr<net::StreamSocket> socket(socket_buffer_.release());
    232   net::IPEndPoint ip_end_point_local;
    233   net::IPEndPoint ip_end_point_remote;
    234   PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress;
    235   PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress;
    236 
    237   int32_t pp_result =
    238       NetErrorToPepperError(socket->GetLocalAddress(&ip_end_point_local));
    239   if (pp_result != PP_OK) {
    240     SendAcceptError(context, pp_result);
    241     return;
    242   }
    243   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    244           ip_end_point_local.address(),
    245           ip_end_point_local.port(),
    246           &local_addr)) {
    247     SendAcceptError(context, PP_ERROR_FAILED);
    248     return;
    249   }
    250   pp_result =
    251       NetErrorToPepperError(socket->GetPeerAddress(&ip_end_point_remote));
    252   if (pp_result != PP_OK) {
    253     SendAcceptError(context, pp_result);
    254     return;
    255   }
    256   if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
    257           ip_end_point_remote.address(),
    258           ip_end_point_remote.port(),
    259           &remote_addr)) {
    260     SendAcceptError(context, PP_ERROR_FAILED);
    261     return;
    262   }
    263   if (!pepper_message_filter_.get() || plugin_dispatcher_id == 0) {
    264     SendAcceptError(context, PP_ERROR_FAILED);
    265     return;
    266   }
    267   uint32 accepted_socket_id = pepper_message_filter_->AddAcceptedTCPSocket(
    268       ppapi::API_ID_PPB_TCPSOCKET_PRIVATE,
    269       plugin_dispatcher_id,
    270       socket.release());
    271   if (accepted_socket_id != 0) {
    272     SendAcceptReply(context, PP_OK, accepted_socket_id, local_addr,
    273                     remote_addr);
    274   } else {
    275     SendAcceptError(context, PP_ERROR_NOSPACE);
    276   }
    277 }
    278 
    279 void PepperTCPServerSocketMessageFilter::SendListenReply(
    280     const ppapi::host::ReplyMessageContext& context,
    281     int32_t pp_result,
    282     const PP_NetAddress_Private& local_addr) {
    283   ppapi::host::ReplyMessageContext reply_context(context);
    284   reply_context.params.set_result(pp_result);
    285   SendReply(reply_context,
    286             PpapiPluginMsg_TCPServerSocket_ListenReply(local_addr));
    287 }
    288 
    289 void PepperTCPServerSocketMessageFilter::SendListenError(
    290     const ppapi::host::ReplyMessageContext& context,
    291     int32_t pp_result) {
    292   SendListenReply(context, pp_result,
    293                   NetAddressPrivateImpl::kInvalidNetAddress);
    294 }
    295 
    296 void PepperTCPServerSocketMessageFilter::SendAcceptReply(
    297     const ppapi::host::ReplyMessageContext& context,
    298     int32_t pp_result,
    299     uint32 accepted_socket_id,
    300     const PP_NetAddress_Private& local_addr,
    301     const PP_NetAddress_Private& remote_addr) {
    302   ppapi::host::ReplyMessageContext reply_context(context);
    303   reply_context.params.set_result(pp_result);
    304   SendReply(reply_context, PpapiPluginMsg_TCPServerSocket_AcceptReply(
    305       accepted_socket_id, local_addr, remote_addr));
    306 }
    307 
    308 void PepperTCPServerSocketMessageFilter::SendAcceptError(
    309     const ppapi::host::ReplyMessageContext& context,
    310     int32_t pp_result) {
    311   SendAcceptReply(context,
    312                   pp_result,
    313                   0,
    314                   NetAddressPrivateImpl::kInvalidNetAddress,
    315                   NetAddressPrivateImpl::kInvalidNetAddress);
    316 }
    317 
    318 }  // namespace content
    319