diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-02 19:22:08 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-02 19:22:08 +0000 |
commit | c761a5fda8cda6efd9e56cb5580e7da37d31dc69 (patch) | |
tree | 2b8e49647ee84096572ee8b75e6767c39e1cffda /ppapi/proxy | |
parent | f659c69514aceb0ea27c598c305bf6ead6cf5e34 (diff) | |
download | chromium_src-c761a5fda8cda6efd9e56cb5580e7da37d31dc69.zip chromium_src-c761a5fda8cda6efd9e56cb5580e7da37d31dc69.tar.gz chromium_src-c761a5fda8cda6efd9e56cb5580e7da37d31dc69.tar.bz2 |
Revert 112693 - committed before review was done - Landing 8688002: PPB_TCPSocket_Private/PPB_UDPSocket_Private are exposed to Browser
Review URL: http://codereview.chromium.org/8688002
Patch from Yuri Gorshenin <ygorshenin@chromium.org>.
TBR=dpolukhin@chromium.org
Review URL: http://codereview.chromium.org/8775063
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112754 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/proxy')
-rw-r--r-- | ppapi/proxy/ppb_tcp_socket_private_proxy.cc | 353 | ||||
-rw-r--r-- | ppapi/proxy/ppb_tcp_socket_private_proxy.h | 7 | ||||
-rw-r--r-- | ppapi/proxy/ppb_udp_socket_private_proxy.cc | 243 | ||||
-rw-r--r-- | ppapi/proxy/ppb_udp_socket_private_proxy.h | 8 |
4 files changed, 555 insertions, 56 deletions
diff --git a/ppapi/proxy/ppb_tcp_socket_private_proxy.cc b/ppapi/proxy/ppb_tcp_socket_private_proxy.cc index b943889..4613784 100644 --- a/ppapi/proxy/ppb_tcp_socket_private_proxy.cc +++ b/ppapi/proxy/ppb_tcp_socket_private_proxy.cc @@ -4,46 +4,143 @@ #include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" +#include <algorithm> +#include <cstring> #include <map> +#include "base/bind.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/task.h" +#include "ppapi/c/pp_errors.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/shared_impl/private/tcp_socket_private_impl.h" #include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_tcp_socket_private_api.h" #include "ppapi/thunk/thunk.h" +using ppapi::thunk::PPB_TCPSocket_Private_API; + namespace ppapi { namespace proxy { +const int32_t kTCPSocketMaxReadSize = 1024 * 1024; +const int32_t kTCPSocketMaxWriteSize = 1024 * 1024; + +class TCPSocket; + namespace { -typedef std::map<uint32, TCPSocketPrivateImpl*> IDToSocketMap; +typedef std::map<uint32, TCPSocket*> IDToSocketMap; IDToSocketMap* g_id_to_socket = NULL; -class TCPSocket : public TCPSocketPrivateImpl { +void AbortCallback(PP_CompletionCallback callback) { + if (callback.func) + PP_RunCompletionCallback(&callback, PP_ERROR_ABORTED); +} + +} // namespace + +class TCPSocket : public PPB_TCPSocket_Private_API, + public Resource { public: TCPSocket(const HostResource& resource, uint32 socket_id); virtual ~TCPSocket(); - virtual void SendConnect(const std::string& host, uint16_t port) OVERRIDE; - virtual void SendConnectWithNetAddress( - const PP_NetAddress_Private& addr) OVERRIDE; - virtual void SendSSLHandshake(const std::string& server_name, - uint16_t server_port) OVERRIDE; - virtual void SendRead(int32_t bytes_to_read) OVERRIDE; - virtual void SendWrite(const std::string& buffer) OVERRIDE; - virtual void SendDisconnect() OVERRIDE; + // Resource overrides. + virtual PPB_TCPSocket_Private_API* AsPPB_TCPSocket_Private_API() OVERRIDE; + + // PPB_TCPSocket_Private_API implementation. + virtual int32_t Connect(const char* host, + uint16_t port, + PP_CompletionCallback callback) OVERRIDE; + virtual int32_t ConnectWithNetAddress( + const PP_NetAddress_Private* addr, + PP_CompletionCallback callback) OVERRIDE; + virtual PP_Bool GetLocalAddress(PP_NetAddress_Private* local_addr) OVERRIDE; + virtual PP_Bool GetRemoteAddress(PP_NetAddress_Private* remote_addr) OVERRIDE; + virtual int32_t SSLHandshake(const char* server_name, + uint16_t server_port, + PP_CompletionCallback callback) OVERRIDE; + virtual int32_t Read(char* buffer, + int32_t bytes_to_read, + PP_CompletionCallback callback) OVERRIDE; + virtual int32_t Write(const char* buffer, + int32_t bytes_to_write, + PP_CompletionCallback callback) OVERRIDE; + virtual void Disconnect() OVERRIDE; + + // Notifications from the proxy. + void OnConnectCompleted(bool succeeded, + const PP_NetAddress_Private& local_addr, + const PP_NetAddress_Private& remote_addr); + void OnSSLHandshakeCompleted(bool succeeded); + void OnReadCompleted(bool succeeded, const std::string& data); + void OnWriteCompleted(bool succeeded, int32_t bytes_written); private: - void SendToBrowser(IPC::Message* msg); + enum ConnectionState { + // Before a connection is successfully established (including a connect + // request is pending or a previous connect request failed). + BEFORE_CONNECT, + // A connection has been successfully established (including a request of + // initiating SSL is pending). + CONNECTED, + // An SSL connection has been successfully established. + SSL_CONNECTED, + // The connection has been ended. + DISCONNECTED + }; + + bool IsConnected() const; + + PluginDispatcher* GetDispatcher() const { + return PluginDispatcher::GetForResource(this); + } + + // Backend for both Connect() and ConnectWithNetAddress(). To keep things + // generic, the message is passed in (on error, it's deleted). + int32_t ConnectWithMessage(IPC::Message* msg, + PP_CompletionCallback callback); + + void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback); + + uint32 socket_id_; + ConnectionState connection_state_; + + PP_CompletionCallback connect_callback_; + PP_CompletionCallback ssl_handshake_callback_; + PP_CompletionCallback read_callback_; + PP_CompletionCallback write_callback_; + + char* read_buffer_; + int32_t bytes_to_read_; + + PP_NetAddress_Private local_addr_; + PP_NetAddress_Private remote_addr_; DISALLOW_COPY_AND_ASSIGN(TCPSocket); }; TCPSocket::TCPSocket(const HostResource& resource, uint32 socket_id) - : TCPSocketPrivateImpl(resource, socket_id) { + : Resource(resource), + socket_id_(socket_id), + connection_state_(BEFORE_CONNECT), + connect_callback_(PP_BlockUntilComplete()), + ssl_handshake_callback_(PP_BlockUntilComplete()), + read_callback_(PP_BlockUntilComplete()), + write_callback_(PP_BlockUntilComplete()), + read_buffer_(NULL), + bytes_to_read_(-1) { + DCHECK(socket_id != 0); + + local_addr_.size = 0; + memset(local_addr_.data, 0, sizeof(local_addr_.data)); + remote_addr_.size = 0; + memset(remote_addr_.data, 0, sizeof(remote_addr_.data)); + if (!g_id_to_socket) g_id_to_socket = new IDToSocketMap(); DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); @@ -54,44 +151,236 @@ TCPSocket::~TCPSocket() { Disconnect(); } -void TCPSocket::SendConnect(const std::string& host, uint16_t port) { - SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Connect(socket_id_, host, port)); +PPB_TCPSocket_Private_API* TCPSocket::AsPPB_TCPSocket_Private_API() { + return this; } -void TCPSocket::SendConnectWithNetAddress(const PP_NetAddress_Private& addr) { - SendToBrowser( - new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress(socket_id_, addr)); +int32_t TCPSocket::Connect(const char* host, + uint16_t port, + PP_CompletionCallback callback) { + if (!host) + return PP_ERROR_BADARGUMENT; + + return ConnectWithMessage( + new PpapiHostMsg_PPBTCPSocket_Connect(socket_id_, host, port), + callback); } -void TCPSocket::SendSSLHandshake(const std::string& server_name, - uint16_t server_port) { - SendToBrowser(new PpapiHostMsg_PPBTCPSocket_SSLHandshake( - socket_id_, server_name, server_port)); +int32_t TCPSocket::ConnectWithNetAddress( + const PP_NetAddress_Private* addr, + PP_CompletionCallback callback) { + if (!addr) + return PP_ERROR_BADARGUMENT; + + return ConnectWithMessage( + new PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress( + socket_id_, *addr), + callback); +} + +PP_Bool TCPSocket::GetLocalAddress(PP_NetAddress_Private* local_addr) { + if (!IsConnected() || !local_addr) + return PP_FALSE; + + *local_addr = local_addr_; + return PP_TRUE; +} + +PP_Bool TCPSocket::GetRemoteAddress(PP_NetAddress_Private* remote_addr) { + if (!IsConnected() || !remote_addr) + return PP_FALSE; + + *remote_addr = remote_addr_; + return PP_TRUE; +} + +int32_t TCPSocket::SSLHandshake(const char* server_name, + uint16_t server_port, + PP_CompletionCallback callback) { + if (!server_name) + return PP_ERROR_BADARGUMENT; + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + + if (connection_state_ != CONNECTED) + return PP_ERROR_FAILED; + if (ssl_handshake_callback_.func || read_callback_.func || + write_callback_.func) + return PP_ERROR_INPROGRESS; + + ssl_handshake_callback_ = callback; + + // Send the request, the browser will call us back via SSLHandshakeACK. + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBTCPSocket_SSLHandshake( + socket_id_, std::string(server_name), server_port)); + return PP_OK_COMPLETIONPENDING; } -void TCPSocket::SendRead(int32_t bytes_to_read) { - SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read)); +int32_t TCPSocket::Read(char* buffer, + int32_t bytes_to_read, + PP_CompletionCallback callback) { + if (!buffer || bytes_to_read <= 0) + return PP_ERROR_BADARGUMENT; + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + + if (!IsConnected()) + return PP_ERROR_FAILED; + if (read_callback_.func || ssl_handshake_callback_.func) + return PP_ERROR_INPROGRESS; + + read_buffer_ = buffer; + bytes_to_read_ = std::min(bytes_to_read, kTCPSocketMaxReadSize); + read_callback_ = callback; + + // Send the request, the browser will call us back via ReadACK. + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBTCPSocket_Read(socket_id_, bytes_to_read_)); + return PP_OK_COMPLETIONPENDING; } -void TCPSocket::SendWrite(const std::string& buffer) { - SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Write(socket_id_, buffer)); +int32_t TCPSocket::Write(const char* buffer, + int32_t bytes_to_write, + PP_CompletionCallback callback) { + if (!buffer || bytes_to_write <= 0) + return PP_ERROR_BADARGUMENT; + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + + if (!IsConnected()) + return PP_ERROR_FAILED; + if (write_callback_.func || ssl_handshake_callback_.func) + return PP_ERROR_INPROGRESS; + + if (bytes_to_write > kTCPSocketMaxWriteSize) + bytes_to_write = kTCPSocketMaxWriteSize; + + write_callback_ = callback; + + // Send the request, the browser will call us back via WriteACK. + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBTCPSocket_Write( + socket_id_, std::string(buffer, bytes_to_write))); + return PP_OK_COMPLETIONPENDING; } -void TCPSocket::SendDisconnect() { +void TCPSocket::Disconnect() { + if (connection_state_ == DISCONNECTED) + return; + + connection_state_ = DISCONNECTED; // After removed from the mapping, this object won't receive any notifications // from the proxy. DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); g_id_to_socket->erase(socket_id_); - SendToBrowser(new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_)); + + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBTCPSocket_Disconnect(socket_id_)); + socket_id_ = 0; + + PostAbortAndClearIfNecessary(&connect_callback_); + PostAbortAndClearIfNecessary(&ssl_handshake_callback_); + PostAbortAndClearIfNecessary(&read_callback_); + PostAbortAndClearIfNecessary(&write_callback_); + read_buffer_ = NULL; + bytes_to_read_ = -1; +} + +void TCPSocket::OnConnectCompleted( + bool succeeded, + const PP_NetAddress_Private& local_addr, + const PP_NetAddress_Private& remote_addr) { + if (connection_state_ != BEFORE_CONNECT || !connect_callback_.func) { + NOTREACHED(); + return; + } + + if (succeeded) { + local_addr_ = local_addr; + remote_addr_ = remote_addr; + connection_state_ = CONNECTED; + } + PP_RunAndClearCompletionCallback(&connect_callback_, + succeeded ? PP_OK : PP_ERROR_FAILED); } -void TCPSocket::SendToBrowser(IPC::Message* msg) { - PluginDispatcher::GetForResource(this)->SendToBrowser(msg); +void TCPSocket::OnSSLHandshakeCompleted(bool succeeded) { + if (connection_state_ != CONNECTED || !ssl_handshake_callback_.func) { + NOTREACHED(); + return; + } + + if (succeeded) { + connection_state_ = SSL_CONNECTED; + PP_RunAndClearCompletionCallback(&ssl_handshake_callback_, PP_OK); + } else { + PP_RunAndClearCompletionCallback(&ssl_handshake_callback_, PP_ERROR_FAILED); + Disconnect(); + } } -} // namespace +void TCPSocket::OnReadCompleted(bool succeeded, const std::string& data) { + if (!read_callback_.func || !read_buffer_) { + NOTREACHED(); + return; + } + + if (succeeded) { + CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); + if (!data.empty()) + memcpy(read_buffer_, data.c_str(), data.size()); + } + read_buffer_ = NULL; + bytes_to_read_ = -1; + + PP_RunAndClearCompletionCallback( + &read_callback_, + succeeded ? static_cast<int32_t>(data.size()) : + static_cast<int32_t>(PP_ERROR_FAILED)); +} + +void TCPSocket::OnWriteCompleted(bool succeeded, int32_t bytes_written) { + if (!write_callback_.func || (succeeded && bytes_written < 0)) { + NOTREACHED(); + return; + } -//------------------------------------------------------------------------------ + PP_RunAndClearCompletionCallback( + &write_callback_, + succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED)); +} + +bool TCPSocket::IsConnected() const { + return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED; +} + +int32_t TCPSocket::ConnectWithMessage(IPC::Message* msg, + PP_CompletionCallback callback) { + scoped_ptr<IPC::Message> msg_deletor(msg); + if (!callback.func) + return PP_ERROR_BLOCKS_MAIN_THREAD; + if (connection_state_ != BEFORE_CONNECT) + return PP_ERROR_FAILED; + if (connect_callback_.func) + return PP_ERROR_INPROGRESS; // Can only have one pending request. + + connect_callback_ = callback; + // Send the request, the browser will call us back via ConnectACK. + GetDispatcher()->SendToBrowser(msg_deletor.release()); + return PP_OK_COMPLETIONPENDING; +} + +void TCPSocket::PostAbortAndClearIfNecessary( + PP_CompletionCallback* callback) { + DCHECK(callback); + + if (callback->func) { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&AbortCallback, *callback)); + *callback = PP_BlockUntilComplete(); + } +} PPB_TCPSocket_Private_Proxy::PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher) : InterfaceProxy(dispatcher) { diff --git a/ppapi/proxy/ppb_tcp_socket_private_proxy.h b/ppapi/proxy/ppb_tcp_socket_private_proxy.h index 3e50b9f..ec89fe2 100644 --- a/ppapi/proxy/ppb_tcp_socket_private_proxy.h +++ b/ppapi/proxy/ppb_tcp_socket_private_proxy.h @@ -17,6 +17,13 @@ namespace ppapi { namespace proxy { +// The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Read +// message is allowed to request. +PPAPI_PROXY_EXPORT extern const int32_t kTCPSocketMaxReadSize; +// The maximum number of bytes that each PpapiHostMsg_PPBTCPSocket_Write +// message is allowed to carry. +PPAPI_PROXY_EXPORT extern const int32_t kTCPSocketMaxWriteSize; + class PPB_TCPSocket_Private_Proxy : public InterfaceProxy { public: PPB_TCPSocket_Private_Proxy(Dispatcher* dispatcher); diff --git a/ppapi/proxy/ppb_udp_socket_private_proxy.cc b/ppapi/proxy/ppb_udp_socket_private_proxy.cc index 444a7da..1347049 100644 --- a/ppapi/proxy/ppb_udp_socket_private_proxy.cc +++ b/ppapi/proxy/ppb_udp_socket_private_proxy.cc @@ -4,43 +4,113 @@ #include "ppapi/proxy/ppb_udp_socket_private_proxy.h" +#include <algorithm> +#include <cstring> #include <map> +#include "base/bind.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/task.h" +#include "ppapi/c/pp_errors.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/shared_impl/private/udp_socket_private_impl.h" #include "ppapi/shared_impl/resource.h" +#include "ppapi/thunk/ppb_udp_socket_private_api.h" #include "ppapi/thunk/thunk.h" +using ppapi::thunk::PPB_UDPSocket_Private_API; + namespace ppapi { namespace proxy { +const int32_t kUDPSocketMaxReadSize = 1024 * 1024; +const int32_t kUDPSocketMaxWriteSize = 1024 * 1024; + namespace { -typedef std::map<uint32, UDPSocketPrivateImpl*> IDToSocketMap; +class UDPSocket; + +typedef std::map<uint32, UDPSocket*> IDToSocketMap; IDToSocketMap* g_id_to_socket = NULL; -class UDPSocket : public UDPSocketPrivateImpl { +void AbortCallback(PP_CompletionCallback callback) { + if (callback.func) + PP_RunCompletionCallback(&callback, PP_ERROR_ABORTED); +} + +class UDPSocket : public PPB_UDPSocket_Private_API, + public Resource { public: UDPSocket(const HostResource& resource, uint32 socket_id); virtual ~UDPSocket(); - virtual void SendBind(const PP_NetAddress_Private& addr) OVERRIDE; - virtual void SendRecvFrom(int32_t num_bytes) OVERRIDE; - virtual void SendSendTo(const std::string& data, - const PP_NetAddress_Private& addr) OVERRIDE; - virtual void SendClose() OVERRIDE; + // ResourceObjectBase overrides. + virtual PPB_UDPSocket_Private_API* AsPPB_UDPSocket_Private_API() OVERRIDE; + + // PPB_UDPSocket_Private_API implementation. + virtual int32_t Bind(const PP_NetAddress_Private* addr, + PP_CompletionCallback callback) OVERRIDE; + virtual int32_t RecvFrom(char* buffer, + int32_t num_bytes, + PP_CompletionCallback callback) OVERRIDE; + virtual PP_Bool GetRecvFromAddress(PP_NetAddress_Private* addr) OVERRIDE; + + virtual int32_t SendTo(const char* buffer, + int32_t num_bytes, + const PP_NetAddress_Private* addr, + PP_CompletionCallback callback) OVERRIDE; + virtual void Close() OVERRIDE; + + // Notifications from the proxy. + void OnBindCompleted(bool succeeded); + void OnRecvFromCompleted(bool succeeded, + const std::string& data, + const PP_NetAddress_Private& addr); + void OnSendToCompleted(bool succeeded, + int32_t bytes_written); private: - void SendToBrowser(IPC::Message* msg); + void PostAbortAndClearIfNecessary(PP_CompletionCallback* callback); + + PluginDispatcher* GetDispatcher() const { + return PluginDispatcher::GetForResource(this); + } + + uint32 socket_id_; + + bool binded_; + bool closed_; + + PP_CompletionCallback bind_callback_; + PP_CompletionCallback recvfrom_callback_; + PP_CompletionCallback sendto_callback_; + + char* read_buffer_; + int32_t bytes_to_read_; + + PP_NetAddress_Private recvfrom_addr_; DISALLOW_COPY_AND_ASSIGN(UDPSocket); }; UDPSocket::UDPSocket(const HostResource& resource, uint32 socket_id) - : UDPSocketPrivateImpl(resource, socket_id) { + : Resource(resource), + socket_id_(socket_id), + binded_(false), + closed_(false), + bind_callback_(PP_BlockUntilComplete()), + recvfrom_callback_(PP_BlockUntilComplete()), + sendto_callback_(PP_BlockUntilComplete()), + read_buffer_(NULL), + bytes_to_read_(-1) { + DCHECK(socket_id != 0); + + recvfrom_addr_.size = 0; + memset(recvfrom_addr_.data, 0, sizeof(recvfrom_addr_.data)); + if (!g_id_to_socket) g_id_to_socket = new IDToSocketMap(); DCHECK(g_id_to_socket->find(socket_id) == g_id_to_socket->end()); @@ -51,34 +121,159 @@ UDPSocket::~UDPSocket() { Close(); } -void UDPSocket::SendBind(const PP_NetAddress_Private& addr) { - SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Bind(socket_id_, addr)); +PPB_UDPSocket_Private_API* UDPSocket::AsPPB_UDPSocket_Private_API() { + return this; } -void UDPSocket::SendRecvFrom(int32_t num_bytes) { - SendToBrowser(new PpapiHostMsg_PPBUDPSocket_RecvFrom(socket_id_, num_bytes)); +int32_t UDPSocket::Bind(const PP_NetAddress_Private* addr, + PP_CompletionCallback callback) { + if (!addr || !callback.func) + return PP_ERROR_BADARGUMENT; + if (binded_ || closed_) + return PP_ERROR_FAILED; + if (bind_callback_.func) + return PP_ERROR_INPROGRESS; + + bind_callback_ = callback; + + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBUDPSocket_Bind(socket_id_, *addr)); + + return PP_OK_COMPLETIONPENDING; } -void UDPSocket::SendSendTo(const std::string& data, - const PP_NetAddress_Private& addr) { - SendToBrowser(new PpapiHostMsg_PPBUDPSocket_SendTo(socket_id_, data, addr)); +int32_t UDPSocket::RecvFrom(char* buffer, + int32_t num_bytes, + PP_CompletionCallback callback) { + if (!buffer || num_bytes <= 0 || !callback.func) + return PP_ERROR_BADARGUMENT; + if (!binded_) + return PP_ERROR_FAILED; + if (recvfrom_callback_.func) + return PP_ERROR_INPROGRESS; + + read_buffer_ = buffer; + bytes_to_read_ = std::min(num_bytes, kUDPSocketMaxReadSize); + recvfrom_callback_ = callback; + + // Send the request, the browser will call us back via RecvFromACK. + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBUDPSocket_RecvFrom( + socket_id_, num_bytes)); + return PP_OK_COMPLETIONPENDING; } -void UDPSocket::SendClose() { - // After removed from the mapping, this object won't receive any notifications +PP_Bool UDPSocket::GetRecvFromAddress(PP_NetAddress_Private* addr) { + if (!addr) + return PP_FALSE; + + *addr = recvfrom_addr_; + return PP_TRUE; +} + +int32_t UDPSocket::SendTo(const char* buffer, + int32_t num_bytes, + const PP_NetAddress_Private* addr, + PP_CompletionCallback callback) { + if (!buffer || num_bytes <= 0 || !addr || !callback.func) + return PP_ERROR_BADARGUMENT; + if (!binded_) + return PP_ERROR_FAILED; + if (sendto_callback_.func) + return PP_ERROR_INPROGRESS; + + if (num_bytes > kUDPSocketMaxWriteSize) + num_bytes = kUDPSocketMaxWriteSize; + + sendto_callback_ = callback; + + // Send the request, the browser will call us back via SendToACK. + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBUDPSocket_SendTo( + socket_id_, std::string(buffer, num_bytes), *addr)); + + return PP_OK_COMPLETIONPENDING; +} + +void UDPSocket::Close() { + if(closed_) + return; + + binded_ = false; + closed_ = true; + + // After removed from the mapping, this object won't receive any notfications // from the proxy. DCHECK(g_id_to_socket->find(socket_id_) != g_id_to_socket->end()); g_id_to_socket->erase(socket_id_); - SendToBrowser(new PpapiHostMsg_PPBUDPSocket_Close(socket_id_)); + + GetDispatcher()->SendToBrowser( + new PpapiHostMsg_PPBUDPSocket_Close(socket_id_)); + socket_id_ = 0; + + PostAbortAndClearIfNecessary(&bind_callback_); + PostAbortAndClearIfNecessary(&recvfrom_callback_); + PostAbortAndClearIfNecessary(&sendto_callback_); } -void UDPSocket::SendToBrowser(IPC::Message* msg) { - PluginDispatcher::GetForResource(this)->SendToBrowser(msg); +void UDPSocket::OnBindCompleted(bool succeeded) { + if (!bind_callback_.func) { + NOTREACHED(); + return; + } + + if (succeeded) + binded_ = true; + + PP_RunAndClearCompletionCallback(&bind_callback_, + succeeded ? PP_OK : PP_ERROR_FAILED); } -} // namespace +void UDPSocket::OnRecvFromCompleted(bool succeeded, + const std::string& data, + const PP_NetAddress_Private& addr) { + if (!recvfrom_callback_.func || !read_buffer_) { + NOTREACHED(); + return; + } -//------------------------------------------------------------------------------ + if (succeeded) { + CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_); + if (!data.empty()) + memcpy(read_buffer_, data.c_str(), data.size()); + } + read_buffer_ = NULL; + bytes_to_read_ = -1; + recvfrom_addr_ = addr; + + PP_RunAndClearCompletionCallback( + &recvfrom_callback_, + succeeded ? static_cast<int32_t>(data.size()) : + static_cast<int32_t>(PP_ERROR_FAILED)); +} + +void UDPSocket::OnSendToCompleted(bool succeeded, int32_t bytes_written) { + if (!sendto_callback_.func) { + NOTREACHED(); + return; + } + + PP_RunAndClearCompletionCallback( + &sendto_callback_, + succeeded ? bytes_written : static_cast<int32_t>(PP_ERROR_FAILED)); +} + +void UDPSocket::PostAbortAndClearIfNecessary( + PP_CompletionCallback* callback) { + DCHECK(callback); + + if (callback->func) { + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&AbortCallback, *callback)); + *callback = PP_BlockUntilComplete(); + } +} +} // namespace PPB_UDPSocket_Private_Proxy::PPB_UDPSocket_Private_Proxy(Dispatcher* dispatcher) : InterfaceProxy(dispatcher) { diff --git a/ppapi/proxy/ppb_udp_socket_private_proxy.h b/ppapi/proxy/ppb_udp_socket_private_proxy.h index c6c9e68..337cf6b 100644 --- a/ppapi/proxy/ppb_udp_socket_private_proxy.h +++ b/ppapi/proxy/ppb_udp_socket_private_proxy.h @@ -16,6 +16,13 @@ namespace ppapi { namespace proxy { +// The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_RecvFrom +// message is allowed to request. +extern const int32_t kUDPSocketMaxReadSize; +// The maximum number of bytes that each PpapiHostMsg_PPBUDPSocket_SendTo +// message is allowed to carry. +extern const int32_t kUDPSocketMaxWriteSize; + class PPB_UDPSocket_Private_Proxy : public InterfaceProxy { public: PPB_UDPSocket_Private_Proxy(Dispatcher* dispatcher); @@ -50,3 +57,4 @@ class PPB_UDPSocket_Private_Proxy : public InterfaceProxy { } // namespace ppapi #endif // PPAPI_PROXY_PPB_UDP_SOCKET_PRIVATE_PROXY_H_ + |