diff options
author | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-15 09:39:56 +0000 |
---|---|---|
committer | ygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-15 09:39:56 +0000 |
commit | 2d011e88f4d4106c1a3a2b4fae4ce2e46bb7d8b3 (patch) | |
tree | a1721b6061e1f4cc64350d6d6b61613ec7fe1118 /ppapi/proxy/ppb_tcp_server_socket_private_proxy.cc | |
parent | c1c32c85357f14756247b04b8b5ae41b05bf2e16 (diff) | |
download | chromium_src-2d011e88f4d4106c1a3a2b4fae4ce2e46bb7d8b3.zip chromium_src-2d011e88f4d4106c1a3a2b4fae4ce2e46bb7d8b3.tar.gz chromium_src-2d011e88f4d4106c1a3a2b4fae4ce2e46bb7d8b3.tar.bz2 |
Added out-of-process support for server sockets.
BUG=108277
TEST=OutOfProcessPPAPITest.TCPServerSocketPrivate
Review URL: http://codereview.chromium.org/9669038
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126873 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy/ppb_tcp_server_socket_private_proxy.cc')
-rw-r--r-- | ppapi/proxy/ppb_tcp_server_socket_private_proxy.cc | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/ppapi/proxy/ppb_tcp_server_socket_private_proxy.cc b/ppapi/proxy/ppb_tcp_server_socket_private_proxy.cc new file mode 100644 index 0000000..ed5d5ad --- /dev/null +++ b/ppapi/proxy/ppb_tcp_server_socket_private_proxy.cc @@ -0,0 +1,202 @@ +// Copyright (c) 2012 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 "ppapi/proxy/ppb_tcp_server_socket_private_proxy.h" + +#include <cstddef> + +#include "base/logging.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/proxy/plugin_dispatcher.h" +#include "ppapi/proxy/plugin_globals.h" +#include "ppapi/proxy/plugin_proxy_delegate.h" +#include "ppapi/proxy/plugin_resource_tracker.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" +#include "ppapi/shared_impl/private/ppb_tcp_server_socket_shared.h" +#include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/enter.h" +#include "ppapi/thunk/thunk.h" + +namespace ppapi { +namespace proxy { + +typedef thunk::EnterResource<thunk::PPB_TCPServerSocket_Private_API> + EnterTCPServerSocket; + +namespace { + +class TCPServerSocket : public PPB_TCPServerSocket_Shared { + public: + TCPServerSocket(const HostResource& resource, uint32 plugin_dispatcher_id); + virtual ~TCPServerSocket(); + + virtual void OnAcceptCompleted( + bool succeeded, + uint32 tcp_socket_id, + const PP_NetAddress_Private& local_addr, + const PP_NetAddress_Private& remote_addr) OVERRIDE; + + virtual void SendListen(const PP_NetAddress_Private& addr, + int32_t backlog) OVERRIDE; + virtual void SendAccept() OVERRIDE; + virtual void SendStopListening() OVERRIDE; + + private: + void SendToBrowser(IPC::Message* msg); + + uint32 plugin_dispatcher_id_; + + DISALLOW_COPY_AND_ASSIGN(TCPServerSocket); +}; + +TCPServerSocket::TCPServerSocket(const HostResource& resource, + uint32 plugin_dispatcher_id) + : PPB_TCPServerSocket_Shared(resource), + plugin_dispatcher_id_(plugin_dispatcher_id) { +} + +TCPServerSocket::~TCPServerSocket() { + StopListening(); +} + +void TCPServerSocket::OnAcceptCompleted( + bool succeeded, + uint32 accepted_socket_id, + const PP_NetAddress_Private& local_addr, + const PP_NetAddress_Private& remote_addr) { + if (!TrackedCallback::IsPending(accept_callback_) || !tcp_socket_buffer_) { + NOTREACHED(); + return; + } + + if (succeeded) { + *tcp_socket_buffer_ = + PPB_TCPSocket_Private_Proxy::CreateProxyResourceForConnectedSocket( + pp_instance(), + accepted_socket_id, + local_addr, + remote_addr); + } + tcp_socket_buffer_ = NULL; + + TrackedCallback::ClearAndRun(&accept_callback_, + succeeded ? PP_OK : PP_ERROR_FAILED); +} + +void TCPServerSocket::SendListen(const PP_NetAddress_Private& addr, + int32_t backlog) { + SendToBrowser(new PpapiHostMsg_PPBTCPServerSocket_Listen( + API_ID_PPB_TCPSERVERSOCKET_PRIVATE, + plugin_dispatcher_id_, + pp_resource(), + addr, + backlog)); +} + +void TCPServerSocket::SendAccept() { + SendToBrowser(new PpapiHostMsg_PPBTCPServerSocket_Accept( + API_ID_PPB_TCPSOCKET_PRIVATE, socket_id_)); +} + +void TCPServerSocket::SendStopListening() { + if (socket_id_ != 0) { + SendToBrowser(new PpapiHostMsg_PPBTCPServerSocket_Destroy(socket_id_)); + + PluginDispatcher* dispatcher = + PluginDispatcher::GetForInstance(host_resource().instance()); + if (dispatcher) { + InterfaceProxy* proxy = + dispatcher->GetInterfaceProxy(API_ID_PPB_TCPSERVERSOCKET_PRIVATE); + PPB_TCPServerSocket_Private_Proxy* server_socket_proxy = + static_cast<PPB_TCPServerSocket_Private_Proxy*>(proxy); + server_socket_proxy->ObjectDestroyed(socket_id_); + } + } +} + +void TCPServerSocket::SendToBrowser(IPC::Message* msg) { + PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(msg); +} + +} // namespace + +//------------------------------------------------------------------------------ + +PPB_TCPServerSocket_Private_Proxy::PPB_TCPServerSocket_Private_Proxy( + Dispatcher* dispatcher) + : InterfaceProxy(dispatcher) { +} + +PPB_TCPServerSocket_Private_Proxy::~PPB_TCPServerSocket_Private_Proxy() { +} + +PP_Resource PPB_TCPServerSocket_Private_Proxy::CreateProxyResource( + PP_Instance instance) { + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); + if (!dispatcher) + return 0; + + TCPServerSocket* server_socket = + new TCPServerSocket(HostResource::MakeInstanceOnly(instance), + dispatcher->plugin_dispatcher_id()); + return server_socket->GetReference(); +} + +void PPB_TCPServerSocket_Private_Proxy::ObjectDestroyed(uint32 socket_id) { + id_to_server_socket_.erase(socket_id); +} + +bool PPB_TCPServerSocket_Private_Proxy::OnMessageReceived( + const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPB_TCPServerSocket_Private_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_ListenACK, OnMsgListenACK) + IPC_MESSAGE_HANDLER(PpapiMsg_PPBTCPServerSocket_AcceptACK, OnMsgAcceptACK) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void PPB_TCPServerSocket_Private_Proxy::OnMsgListenACK( + uint32 plugin_dispatcher_id, + PP_Resource socket_resource, + uint32 socket_id, + int32_t status) { + EnterTCPServerSocket enter(socket_resource, true); + if (enter.succeeded()) { + PPB_TCPServerSocket_Shared* server_socket = + static_cast<PPB_TCPServerSocket_Shared*>(enter.object()); + if (status == PP_OK) + id_to_server_socket_[socket_id] = server_socket; + server_socket->OnListenCompleted(socket_id, status); + } else if (socket_id != 0 && status == PP_OK) { + IPC::Message* msg = + new PpapiHostMsg_PPBTCPServerSocket_Destroy(socket_id); + PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser(msg); + } +} + +void PPB_TCPServerSocket_Private_Proxy::OnMsgAcceptACK( + uint32 plugin_dispatcher_id, + uint32 server_socket_id, + uint32 accepted_socket_id, + const PP_NetAddress_Private& local_addr, + const PP_NetAddress_Private& remote_addr) { + IDToServerSocketMap::iterator it = + id_to_server_socket_.find(server_socket_id); + if (it != id_to_server_socket_.end()) { + bool succeeded = (accepted_socket_id != 0); + it->second->OnAcceptCompleted(succeeded, + accepted_socket_id, + local_addr, + remote_addr); + } else if (accepted_socket_id != 0) { + PluginGlobals::Get()->plugin_proxy_delegate()->SendToBrowser( + new PpapiHostMsg_PPBTCPSocket_Disconnect(accepted_socket_id)); + } +} + +} // namespace proxy +} // namespace ppapi |