Home | History | Annotate | Download | only in proxy
      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 "ppapi/proxy/ppb_tcp_socket_proxy.h"
      6 
      7 #include <map>
      8 
      9 #include "base/logging.h"
     10 #include "ppapi/proxy/plugin_dispatcher.h"
     11 #include "ppapi/proxy/plugin_globals.h"
     12 #include "ppapi/proxy/ppapi_messages.h"
     13 #include "ppapi/shared_impl/resource.h"
     14 #include "ppapi/shared_impl/socket_option_data.h"
     15 #include "ppapi/shared_impl/tcp_socket_shared.h"
     16 #include "ppapi/thunk/enter.h"
     17 #include "ppapi/thunk/ppb_net_address_api.h"
     18 #include "ppapi/thunk/ppb_tcp_socket_api.h"
     19 #include "ppapi/thunk/thunk.h"
     20 
     21 namespace ppapi {
     22 namespace proxy {
     23 
     24 namespace {
     25 
     26 typedef thunk::EnterResourceNoLock<thunk::PPB_NetAddress_API>
     27     EnterNetAddressNoLock;
     28 
     29 typedef std::map<uint32, TCPSocketShared*> IDToSocketMap;
     30 IDToSocketMap* g_id_to_socket = NULL;
     31 
     32 class TCPSocket : public thunk::PPB_TCPSocket_API,
     33                   public Resource,
     34                   public TCPSocketShared {
     35  public:
     36   TCPSocket(const HostResource& resource, uint32 socket_id);
     37   virtual ~TCPSocket();
     38 
     39   // Resource overrides.
     40   virtual thunk::PPB_TCPSocket_API* AsPPB_TCPSocket_API() OVERRIDE;
     41 
     42   // thunk::PPB_TCPSocket_API implementation.
     43   virtual int32_t Connect(PP_Resource addr,
     44                           scoped_refptr<TrackedCallback> callback) OVERRIDE;
     45   virtual PP_Resource GetLocalAddress() OVERRIDE;
     46   virtual PP_Resource GetRemoteAddress() OVERRIDE;
     47   virtual int32_t Read(char* buffer,
     48                        int32_t bytes_to_read,
     49                        scoped_refptr<TrackedCallback> callback) OVERRIDE;
     50   virtual int32_t Write(const char* buffer,
     51                         int32_t bytes_to_write,
     52                         scoped_refptr<TrackedCallback> callback) OVERRIDE;
     53   virtual void Close() OVERRIDE;
     54   virtual int32_t SetOption(PP_TCPSocket_Option name,
     55                             const PP_Var& value,
     56                             scoped_refptr<TrackedCallback> callback) OVERRIDE;
     57 
     58   // TCPSocketShared implementation.
     59   virtual void SendConnect(const std::string& host, uint16_t port) OVERRIDE;
     60   virtual void SendConnectWithNetAddress(
     61       const PP_NetAddress_Private& addr) OVERRIDE;
     62   virtual void SendSSLHandshake(
     63       const std::string& server_name,
     64       uint16_t server_port,
     65       const std::vector<std::vector<char> >& trusted_certs,
     66       const std::vector<std::vector<char> >& untrusted_certs) OVERRIDE;
     67   virtual void SendRead(int32_t bytes_to_read) OVERRIDE;
     68   virtual void SendWrite(const std::string& buffer) OVERRIDE;
     69   virtual void SendDisconnect() OVERRIDE;
     70   virtual void SendSetOption(PP_TCPSocket_Option name,
     71                              const SocketOptionData& value) OVERRIDE;
     72   virtual Resource* GetOwnerResource() OVERRIDE;
     73 
     74  private:
     75   void SendToBrowser(IPC::Message* msg);
     76 
     77   DISALLOW_COPY_AND_ASSIGN(TCPSocket);
     78 };
     79 
     80 TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id)
     81     : Resource(OBJECT_IS_PROXY, resource),
     82       TCPSocketShared(OBJECT_IS_PROXY, socket_id) {
     83   if (!g_id_to_socket)
     84     g_id_to_socket = new IDToSocketMap();
     85   DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end());
     86   (*g_id_to_socket)[socket_id] = this;
     87 }
     88 
     89 TCPSocket::~TCPSocket() {
     90   DisconnectImpl();
     91 }
     92 
     93 thunk::PPB_TCPSocket_API* TCPSocket::AsPPB_TCPSocket_API() {
     94   return this;
     95 }
     96 
     97 int32_t TCPSocket::Connect(PP_Resource addr,
     98                            scoped_refptr<TrackedCallback> callback) {
     99   EnterNetAddressNoLock enter(addr, true);
    100   if (enter.failed())
    101     return PP_ERROR_BADARGUMENT;
    102 
    103   return ConnectWithNetAddressImpl(&enter.object()->GetNetAddressPrivate(),
    104                                    callback);
    105 }
    106 
    107 PP_Resource TCPSocket::GetLocalAddress() {
    108   PP_NetAddress_Private addr_private;
    109   if (!GetLocalAddressImpl(&addr_private))
    110     return 0;
    111 
    112   thunk::EnterResourceCreationNoLock enter(pp_instance());
    113   if (enter.failed())
    114     return 0;
    115   return enter.functions()->CreateNetAddressFromNetAddressPrivate(
    116       pp_instance(), addr_private);
    117 }
    118 
    119 PP_Resource TCPSocket::GetRemoteAddress() {
    120   PP_NetAddress_Private addr_private;
    121   if (!GetRemoteAddressImpl(&addr_private))
    122     return 0;
    123 
    124   thunk::EnterResourceCreationNoLock enter(pp_instance());
    125   if (enter.failed())
    126     return 0;
    127   return enter.functions()->CreateNetAddressFromNetAddressPrivate(
    128       pp_instance(), addr_private);
    129 }
    130 
    131 int32_t TCPSocket::Read(char* buffer,
    132                         int32_t bytes_to_read,
    133                         scoped_refptr<TrackedCallback> callback) {
    134   return ReadImpl(buffer, bytes_to_read, callback);
    135 }
    136 
    137 int32_t TCPSocket::Write(const char* buffer,
    138                          int32_t bytes_to_write,
    139                          scoped_refptr<TrackedCallback> callback) {
    140   return WriteImpl(buffer, bytes_to_write, callback);
    141 }
    142 
    143 void TCPSocket::Close() {
    144   DisconnectImpl();
    145 }
    146 
    147 int32_t TCPSocket::SetOption(PP_TCPSocket_Option name,
    148                              const PP_Var& value,
    149                              scoped_refptr<TrackedCallback> callback) {
    150   return SetOptionImpl(name, value, callback);
    151 }
    152 
    153 void TCPSocket::SendConnect(const std::string& host, uint16_t port) {
    154   NOTREACHED();
    155 }
    156 
    157 void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private& addr) {
    158   SendToBrowser(new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(
    159       API_ID_PPB_TCPSOCKET, socket_id_, addr));
    160 }
    161 
    162 void TCPSocket::SendSSLHandshake(
    163     const std::string& server_name,
    164     uint16_t server_port,
    165     const std::vector<std::vector<char> >& trusted_certs,
    166     const std::vector<std::vector<char> >& untrusted_certs) {
    167   NOTREACHED();
    168 }
    169 
    170 void TCPSocket::SendRead(int32_t bytes_to_read) {
    171   SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read));
    172 }
    173 
    174 void TCPSocket::SendWrite(const std::string& buffer) {
    175   SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_, buffer));
    176 }
    177 
    178 void TCPSocket::SendDisconnect() {
    179   // After removed from the mapping, this object won't receive any notifications
    180   // from the proxy.
    181   DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end());
    182   g_id_to_socket->erase(socket_id_);
    183   SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_));
    184 }
    185 
    186 void TCPSocket::SendSetOption(PP_TCPSocket_Option name,
    187                               const SocketOptionData& value) {
    188   SendToBrowser(
    189       new PpapiHostMsg_PPBTCPSocket_SetOption(socket_id_, name, value));
    190 }
    191 
    192 Resource* TCPSocket::GetOwnerResource() {
    193   return this;
    194 }
    195 
    196 void TCPSocket::SendToBrowser(IPC::Message* msg) {
    197   PluginGlobals::Get()->GetBrowserSender()->Send(msg);
    198 }
    199 
    200 }  // namespace
    201 
    202 //------------------------------------------------------------------------------
    203 
    204 PPB_TCPSocket_Proxy::PPB_TCPSocket_Proxy(Dispatcher* dispatcher)
    205     : InterfaceProxy(dispatcher) {
    206 }
    207 
    208 PPB_TCPSocket_Proxy::~PPB_TCPSocket_Proxy() {
    209 }
    210 
    211 // static
    212 PP_Resource PPB_TCPSocket_Proxy::CreateProxyResource(PP_Instance instance) {
    213   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
    214   if (!dispatcher)
    215     return 0;
    216 
    217   uint32 socket_id = 0;
    218   PluginGlobals::Get()->GetBrowserSender()->Send(
    219       new PpapiHostMsg_PPBTCPSocket_Create(
    220           API_ID_PPB_TCPSOCKET, dispatcher->plugin_dispatcher_id(),
    221           &socket_id));
    222   if (socket_id == 0)
    223     return 0;
    224   return (new TCPSocket(HostResource::MakeInstanceOnly(instance),
    225                         socket_id))->GetReference();
    226 }
    227 
    228 bool PPB_TCPSocket_Proxy::OnMessageReceived(const IPC::Message& msg) {
    229   bool handled = true;
    230   IPC_BEGIN_MESSAGE_MAP(PPB_TCPSocket_Proxy, msg)
    231     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ConnectACK,
    232                         OnMsgConnectACK)
    233     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_ReadACK, OnMsgReadACK)
    234     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_WriteACK, OnMsgWriteACK)
    235     IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPSocket_SetOptionACK,
    236                         OnMsgSetOptionACK)
    237     IPC_MESSAGE_UNHANDLED(handled = false)
    238   IPC_END_MESSAGE_MAP()
    239   return handled;
    240 }
    241 
    242 void PPB_TCPSocket_Proxy::OnMsgConnectACK(
    243     uint32 /* plugin_dispatcher_id */,
    244     uint32 socket_id,
    245     int32_t result,
    246     const PP_NetAddress_Private& local_addr,
    247     const PP_NetAddress_Private& remote_addr) {
    248   if (!g_id_to_socket) {
    249     NOTREACHED();
    250     return;
    251   }
    252   IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
    253   if (iter == g_id_to_socket->end())
    254     return;
    255   iter->second->OnConnectCompleted(result, local_addr, remote_addr);
    256 }
    257 
    258 void PPB_TCPSocket_Proxy::OnMsgReadACK(uint32 /* plugin_dispatcher_id */,
    259                                        uint32 socket_id,
    260                                        int32_t result,
    261                                        const std::string& data) {
    262   if (!g_id_to_socket) {
    263     NOTREACHED();
    264     return;
    265   }
    266   IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
    267   if (iter == g_id_to_socket->end())
    268     return;
    269   iter->second->OnReadCompleted(result, data);
    270 }
    271 
    272 void PPB_TCPSocket_Proxy::OnMsgWriteACK(uint32 /* plugin_dispatcher_id */,
    273                                         uint32 socket_id,
    274                                         int32_t result) {
    275   if (!g_id_to_socket) {
    276     NOTREACHED();
    277     return;
    278   }
    279   IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
    280   if (iter == g_id_to_socket->end())
    281     return;
    282   iter->second->OnWriteCompleted(result);
    283 }
    284 
    285 void PPB_TCPSocket_Proxy::OnMsgSetOptionACK(uint32 /* plugin_dispatcher_id */,
    286                                             uint32 socket_id,
    287                                             int32_t result) {
    288   if (!g_id_to_socket) {
    289     NOTREACHED();
    290     return;
    291   }
    292   IDToSocketMap::iterator iter = g_id_to_socket->find(socket_id);
    293   if (iter == g_id_to_socket->end())
    294     return;
    295   iter->second->OnSetOptionCompleted(result);
    296 }
    297 
    298 }  // namespace proxy
    299 }  // namespace ppapi
    300