diff options
author | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-29 02:29:25 +0000 |
---|---|---|
committer | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-29 02:29:25 +0000 |
commit | 9f54f4310a2ed9d7c99e985d33dcb2b20714e85e (patch) | |
tree | 2e0657df9e0f3b02efe6eb02af1e24443ea81cae /content | |
parent | b5a0c01bfc6d390743d1ccdca2175e769f88efa2 (diff) | |
download | chromium_src-9f54f4310a2ed9d7c99e985d33dcb2b20714e85e.zip chromium_src-9f54f4310a2ed9d7c99e985d33dcb2b20714e85e.tar.gz chromium_src-9f54f4310a2ed9d7c99e985d33dcb2b20714e85e.tar.bz2 |
Re-land http://codereview.chromium.org/8586008/
Move PepperTCPSocket and PepperUDPSocket from pepper_message_filter to separate files
Comparing with 8586008, this change adds two more includes in pepper_message_filter if ENABLE_FLAPPER_HACKS is defined.
TBR=jam@chromium.org
BUG=None
TEST=OutOfProcessPPAPITest.TCPSocketPrivate passes.
Review URL: http://codereview.chromium.org/8664010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111841 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/renderer_host/pepper_message_filter.cc | 1140 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper_message_filter.h | 66 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper_tcp_socket.cc | 286 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper_tcp_socket.h | 99 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper_udp_socket.cc | 145 | ||||
-rw-r--r-- | content/browser/renderer_host/pepper_udp_socket.h | 66 | ||||
-rw-r--r-- | content/content_browser.gypi | 4 |
7 files changed, 868 insertions, 938 deletions
diff --git a/content/browser/renderer_host/pepper_message_filter.cc b/content/browser/renderer_host/pepper_message_filter.cc index 4aa1c47..fea3b07 100644 --- a/content/browser/renderer_host/pepper_message_filter.cc +++ b/content/browser/renderer_host/pepper_message_filter.cc @@ -4,24 +4,18 @@ #include "content/browser/renderer_host/pepper_message_filter.h" -#include <string.h> - -#include <limits> -#include <string> - -#include "base/basictypes.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/compiler_specific.h" #include "base/logging.h" -#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/process_util.h" #include "base/threading/worker_pool.h" #include "base/values.h" #include "content/browser/font_list_async.h" #include "content/browser/resource_context.h" +#include "content/browser/renderer_host/pepper_tcp_socket.h" +#include "content/browser/renderer_host/pepper_udp_socket.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/common/pepper_messages.h" #include "content/public/browser/browser_thread.h" @@ -29,896 +23,43 @@ #include "net/base/cert_verifier.h" #include "net/base/host_port_pair.h" #include "net/base/host_resolver.h" -#include "net/base/io_buffer.h" -#include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/single_request_host_resolver.h" -#include "net/base/ssl_config_service.h" -#include "net/base/sys_addrinfo.h" -#include "net/socket/client_socket_factory.h" -#include "net/socket/client_socket_handle.h" -#include "net/socket/ssl_client_socket.h" -#include "net/socket/tcp_client_socket.h" -#include "net/udp/udp_server_socket.h" -#include "net/url_request/url_request_context.h" #include "ppapi/c/private/ppb_flash_net_connector.h" #include "ppapi/proxy/ppapi_messages.h" -#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" #include "ppapi/shared_impl/private/net_address_private_impl.h" #include "webkit/plugins/ppapi/ppb_flash_net_connector_impl.h" #if defined(ENABLE_FLAPPER_HACKS) #include <sys/types.h> #include <unistd.h> + +#include "net/base/net_log.h" +#include "net/base/sys_addrinfo.h" #endif // ENABLE_FLAPPER_HACKS using content::BrowserThread; +using ppapi::NetAddressPrivateImpl; namespace { -// TODO(viettrungluu): Move (some of) these to net_address_private_impl.h. -bool SockaddrToNetAddress(const sockaddr* sa, - socklen_t sa_length, - PP_NetAddress_Private* net_addr) { - if (!sa || sa_length <= 0 || !net_addr) - return false; - - CHECK_LE(static_cast<uint32_t>(sa_length), sizeof(net_addr->data)); - net_addr->size = sa_length; - memcpy(net_addr->data, sa, net_addr->size); - return true; -} - -bool IPEndPointToNetAddress(const net::IPEndPoint& ip, - PP_NetAddress_Private* net_addr) { - sockaddr_storage storage = { 0 }; - size_t length = sizeof(storage); - - return ip.ToSockAddr(reinterpret_cast<sockaddr*>(&storage), &length) && - SockaddrToNetAddress(reinterpret_cast<const sockaddr*>(&storage), - length, net_addr); -} - -// Converts the first address to a PP_NetAddress_Private. -bool AddressListToNetAddress(const net::AddressList& address_list, - PP_NetAddress_Private* net_addr) { - const addrinfo* head = address_list.head(); - return head && - SockaddrToNetAddress(head->ai_addr, head->ai_addrlen, net_addr); -} - -bool NetAddressToIPEndPoint(const PP_NetAddress_Private& net_addr, - net::IPEndPoint* ip_end_point) { - if (!ip_end_point || - !ppapi::NetAddressPrivateImpl::ValidateNetAddress(net_addr)) - return false; - - if (!ip_end_point->FromSockAddr( - reinterpret_cast<const sockaddr*>(net_addr.data), net_addr.size)) { - return false; - } - - return true; -} - -bool NetAddressToAddressList(const PP_NetAddress_Private& net_addr, - net::AddressList* address_list) { - if (!address_list) - return false; - - net::IPEndPoint ip_end_point; - if (!NetAddressToIPEndPoint(net_addr, &ip_end_point)) - return false; - - *address_list = net::AddressList::CreateFromIPAddress(ip_end_point.address(), - ip_end_point.port()); - return true; -} +const size_t kMaxSocketsAllowed = 1024; +const uint32 kInvalidSocketID = 0; } // namespace -// This assert fails on OpenBSD for an unknown reason at the moment. -#if !defined(OS_OPENBSD) -// Make sure the storage in |PP_NetAddress_Private| is big enough. (Do it here -// since the data is opaque elsewhere.) -COMPILE_ASSERT(sizeof(reinterpret_cast<PP_NetAddress_Private*>(0)->data) >= - sizeof(sockaddr_storage), PP_NetAddress_Private_data_too_small); -#endif - -const PP_NetAddress_Private kInvalidNetAddress = { 0 }; - -class PepperMessageFilter::TCPSocket { - public: - TCPSocket(TCPSocketManager* manager, - int32 routing_id, - uint32 plugin_dispatcher_id, - uint32 socket_id); - ~TCPSocket(); - - void Connect(const std::string& host, uint16_t port); - void ConnectWithNetAddress(const PP_NetAddress_Private& net_addr); - void SSLHandshake(const std::string& server_name, uint16_t server_port); - void Read(int32 bytes_to_read); - void Write(const std::string& data); - - private: - enum ConnectionState { - // Before a connection is successfully established (including a previous - // connect request failed). - BEFORE_CONNECT, - // There is a connect request that is pending. - CONNECT_IN_PROGRESS, - // A connection has been successfully established. - CONNECTED, - // There is an SSL handshake request that is pending. - SSL_HANDSHAKE_IN_PROGRESS, - // An SSL connection has been successfully established. - SSL_CONNECTED, - // An SSL handshake has failed. - SSL_HANDSHAKE_FAILED - }; - - void StartConnect(const net::AddressList& addresses); - - void SendConnectACKError(); - void SendReadACKError(); - void SendWriteACKError(); - void SendSSLHandshakeACK(bool succeeded); - - void OnResolveCompleted(int result); - void OnConnectCompleted(int result); - void OnSSLHandshakeCompleted(int result); - void OnReadCompleted(int result); - void OnWriteCompleted(int result); - - bool IsConnected() const; - - TCPSocketManager* manager_; - int32 routing_id_; - uint32 plugin_dispatcher_id_; - uint32 socket_id_; - - ConnectionState connection_state_; - bool end_of_file_reached_; - - net::OldCompletionCallbackImpl<TCPSocket> connect_callback_; - net::OldCompletionCallbackImpl<TCPSocket> ssl_handshake_callback_; - net::OldCompletionCallbackImpl<TCPSocket> read_callback_; - net::OldCompletionCallbackImpl<TCPSocket> write_callback_; - - scoped_ptr<net::SingleRequestHostResolver> resolver_; - net::AddressList address_list_; - - scoped_ptr<net::StreamSocket> socket_; - - scoped_refptr<net::IOBuffer> read_buffer_; - scoped_refptr<net::IOBuffer> write_buffer_; - - DISALLOW_COPY_AND_ASSIGN(TCPSocket); -}; - -// Base class for TCP and UDP socket managers. -template<class SocketType> -class PepperMessageFilter::SocketManager { - public: - explicit SocketManager(PepperMessageFilter* pepper_message_filter); - - protected: - // |socket_id| will be set to 0 on failure, non-zero otherwise. - bool GenerateSocketID(uint32* socket_id); - - uint32 next_socket_id_; - PepperMessageFilter* pepper_message_filter_; - - // SocketMap can hold either TCPSocket or UDPSocket. - typedef std::map<uint32, linked_ptr<SocketType> > SocketMap; - SocketMap sockets_; -}; - -template<class SocketType> -PepperMessageFilter::SocketManager<SocketType>::SocketManager( - PepperMessageFilter* pepper_message_filter) - : next_socket_id_(1), - pepper_message_filter_(pepper_message_filter) { - DCHECK(pepper_message_filter); -} - -template<class SocketType> -bool PepperMessageFilter::SocketManager<SocketType>::GenerateSocketID( - uint32* socket_id) { - // Generate a socket ID. For each process which sends us socket requests, IDs - // of living sockets must be unique, to each socket type. TCP and UDP have - // unique managers, so the socket ID can be the same in this case. - // - // However, it is safe to generate IDs based on the internal state of a single - // SocketManager object, because for each plugin or renderer process, - // there is at most one PepperMessageFilter talking to it - - if (sockets_.size() >= std::numeric_limits<uint32>::max()) { - // All valid IDs are being used. - *socket_id = 0; - return false; - } - do { - // Although it is unlikely, make sure that we won't cause any trouble when - // the counter overflows. - *socket_id = next_socket_id_++; - } while (*socket_id == 0 || - sockets_.find(*socket_id) != sockets_.end()); - - return true; -} - -// TCPSocketManager manages the mapping from socket IDs to TCPSocket -// instances. -class PepperMessageFilter::TCPSocketManager : public SocketManager<TCPSocket> { - public: - explicit TCPSocketManager(PepperMessageFilter* pepper_message_filter); - - void OnMsgCreate(int32 routing_id, - uint32 plugin_dispatcher_id, - uint32* socket_id); - void OnMsgConnect(uint32 socket_id, - const std::string& host, - uint16_t port); - void OnMsgConnectWithNetAddress(uint32 socket_id, - const PP_NetAddress_Private& net_addr); - void OnMsgSSLHandshake(uint32 socket_id, - const std::string& server_name, - uint16_t server_port); - void OnMsgRead(uint32 socket_id, int32_t bytes_to_read); - void OnMsgWrite(uint32 socket_id, const std::string& data); - void OnMsgDisconnect(uint32 socket_id); - - // Used by TCPSocket. - bool Send(IPC::Message* message) { - return pepper_message_filter_->Send(message); - } - net::HostResolver* GetHostResolver() { - return pepper_message_filter_->GetHostResolver(); - } - const net::SSLConfig& ssl_config() { return ssl_config_; } - // The caller doesn't take ownership of the returned object. - net::CertVerifier* GetCertVerifier(); - - private: - // The default SSL configuration settings are used, as opposed to Chrome's SSL - // settings. - net::SSLConfig ssl_config_; - // This is lazily created. Users should use GetCertVerifier to retrieve it. - scoped_ptr<net::CertVerifier> cert_verifier_; - - DISALLOW_COPY_AND_ASSIGN(TCPSocketManager); -}; - -PepperMessageFilter::TCPSocket::TCPSocket( - TCPSocketManager* manager, - int32 routing_id, - uint32 plugin_dispatcher_id, - uint32 socket_id) - : manager_(manager), - routing_id_(routing_id), - plugin_dispatcher_id_(plugin_dispatcher_id), - socket_id_(socket_id), - connection_state_(BEFORE_CONNECT), - end_of_file_reached_(false), - ALLOW_THIS_IN_INITIALIZER_LIST( - connect_callback_(this, &TCPSocket::OnConnectCompleted)), - ALLOW_THIS_IN_INITIALIZER_LIST( - ssl_handshake_callback_(this, &TCPSocket::OnSSLHandshakeCompleted)), - ALLOW_THIS_IN_INITIALIZER_LIST( - read_callback_(this, &TCPSocket::OnReadCompleted)), - ALLOW_THIS_IN_INITIALIZER_LIST( - write_callback_(this, &TCPSocket::OnWriteCompleted)) { - DCHECK(manager); -} - -PepperMessageFilter::TCPSocket::~TCPSocket() { - // Make sure no further callbacks from socket_. - if (socket_.get()) - socket_->Disconnect(); -} - -void PepperMessageFilter::TCPSocket::Connect(const std::string& host, - uint16_t port) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (connection_state_ != BEFORE_CONNECT) { - SendConnectACKError(); - return; - } - - connection_state_ = CONNECT_IN_PROGRESS; - net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); - resolver_.reset(new net::SingleRequestHostResolver( - manager_->GetHostResolver())); - int result = resolver_->Resolve( - request_info, &address_list_, - base::Bind(&TCPSocket::OnResolveCompleted, base::Unretained(this)), - net::BoundNetLog()); - if (result != net::ERR_IO_PENDING) - OnResolveCompleted(result); -} - -void PepperMessageFilter::TCPSocket::ConnectWithNetAddress( - const PP_NetAddress_Private& net_addr) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (connection_state_ != BEFORE_CONNECT || - !NetAddressToAddressList(net_addr, &address_list_)) { - SendConnectACKError(); - return; - } - - connection_state_ = CONNECT_IN_PROGRESS; - StartConnect(address_list_); -} - -void PepperMessageFilter::TCPSocket::SSLHandshake( - const std::string& server_name, - uint16_t server_port) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - // Allow to do SSL handshake only if currently the socket has been connected - // and there isn't pending read or write. - // IsConnected() includes the state that SSL handshake has been finished and - // therefore isn't suitable here. - if (connection_state_ != CONNECTED || read_buffer_.get() || - write_buffer_.get()) { - SendSSLHandshakeACK(false); - return; - } - - connection_state_ = SSL_HANDSHAKE_IN_PROGRESS; - net::ClientSocketHandle* handle = new net::ClientSocketHandle(); - handle->set_socket(socket_.release()); - net::ClientSocketFactory* factory = - net::ClientSocketFactory::GetDefaultFactory(); - net::HostPortPair host_port_pair(server_name, server_port); - net::SSLClientSocketContext ssl_context; - ssl_context.cert_verifier = manager_->GetCertVerifier(); - socket_.reset(factory->CreateSSLClientSocket( - handle, host_port_pair, manager_->ssl_config(), NULL, ssl_context)); - if (!socket_.get()) { - LOG(WARNING) << "Failed to create an SSL client socket."; - OnSSLHandshakeCompleted(net::ERR_UNEXPECTED); - return; - } - - int result = socket_->Connect(&ssl_handshake_callback_); - if (result != net::ERR_IO_PENDING) - OnSSLHandshakeCompleted(result); -} - -void PepperMessageFilter::TCPSocket::Read(int32 bytes_to_read) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (!IsConnected() || end_of_file_reached_ || read_buffer_.get() || - bytes_to_read <= 0) { - SendReadACKError(); - return; - } - - if (bytes_to_read > ppapi::proxy::kTCPSocketMaxReadSize) { - NOTREACHED(); - bytes_to_read = ppapi::proxy::kTCPSocketMaxReadSize; - } - - read_buffer_ = new net::IOBuffer(bytes_to_read); - int result = socket_->Read(read_buffer_, bytes_to_read, &read_callback_); - if (result != net::ERR_IO_PENDING) - OnReadCompleted(result); -} - -void PepperMessageFilter::TCPSocket::Write(const std::string& data) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - if (!IsConnected() || write_buffer_.get() || data.empty()) { - SendWriteACKError(); - return; - } - - int data_size = data.size(); - if (data_size > ppapi::proxy::kTCPSocketMaxWriteSize) { - NOTREACHED(); - data_size = ppapi::proxy::kTCPSocketMaxWriteSize; - } - - write_buffer_ = new net::IOBuffer(data_size); - memcpy(write_buffer_->data(), data.c_str(), data_size); - int result = socket_->Write(write_buffer_, data.size(), &write_callback_); - if (result != net::ERR_IO_PENDING) - OnWriteCompleted(result); -} - -void PepperMessageFilter::TCPSocket::StartConnect( - const net::AddressList& addresses) { - DCHECK(connection_state_ == CONNECT_IN_PROGRESS); - - socket_.reset( - new net::TCPClientSocket(addresses, NULL, net::NetLog::Source())); - int result = socket_->Connect(&connect_callback_); - if (result != net::ERR_IO_PENDING) - OnConnectCompleted(result); -} - -void PepperMessageFilter::TCPSocket::SendConnectACKError() { - manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK( - routing_id_, plugin_dispatcher_id_, socket_id_, false, - kInvalidNetAddress, kInvalidNetAddress)); -} - -void PepperMessageFilter::TCPSocket::SendReadACKError() { - manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK( - routing_id_, plugin_dispatcher_id_, socket_id_, false, std::string())); -} - -void PepperMessageFilter::TCPSocket::SendWriteACKError() { - manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK( - routing_id_, plugin_dispatcher_id_, socket_id_, false, 0)); -} - -void PepperMessageFilter::TCPSocket::SendSSLHandshakeACK(bool succeeded) { - manager_->Send(new PpapiMsg_PPBTCPSocket_SSLHandshakeACK( - routing_id_, plugin_dispatcher_id_, socket_id_, succeeded)); -} - -void PepperMessageFilter::TCPSocket::OnResolveCompleted(int result) { - DCHECK(connection_state_ == CONNECT_IN_PROGRESS); - - if (result != net::OK) { - SendConnectACKError(); - connection_state_ = BEFORE_CONNECT; - return; - } - - StartConnect(address_list_); -} - -void PepperMessageFilter::TCPSocket::OnConnectCompleted(int result) { - DCHECK(connection_state_ == CONNECT_IN_PROGRESS && socket_.get()); - - if (result != net::OK) { - SendConnectACKError(); - connection_state_ = BEFORE_CONNECT; - } else { - net::IPEndPoint ip_end_point; - net::AddressList address_list; - PP_NetAddress_Private local_addr = kInvalidNetAddress; - PP_NetAddress_Private remote_addr = kInvalidNetAddress; - - if (socket_->GetLocalAddress(&ip_end_point) != net::OK || - !IPEndPointToNetAddress(ip_end_point, &local_addr) || - socket_->GetPeerAddress(&address_list) != net::OK || - !AddressListToNetAddress(address_list, &remote_addr)) { - SendConnectACKError(); - connection_state_ = BEFORE_CONNECT; - } else { - manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK( - routing_id_, plugin_dispatcher_id_, socket_id_, true, - local_addr, remote_addr)); - connection_state_ = CONNECTED; - } - } -} - -void PepperMessageFilter::TCPSocket::OnSSLHandshakeCompleted(int result) { - DCHECK(connection_state_ == SSL_HANDSHAKE_IN_PROGRESS); - - bool succeeded = result == net::OK; - SendSSLHandshakeACK(succeeded); - connection_state_ = succeeded ? SSL_CONNECTED : SSL_HANDSHAKE_FAILED; -} - -void PepperMessageFilter::TCPSocket::OnReadCompleted(int result) { - DCHECK(read_buffer_.get()); - - if (result > 0) { - manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK( - routing_id_, plugin_dispatcher_id_, socket_id_, true, - std::string(read_buffer_->data(), result))); - } else if (result == 0) { - end_of_file_reached_ = true; - manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK( - routing_id_, plugin_dispatcher_id_, socket_id_, true, std::string())); - } else { - SendReadACKError(); - } - read_buffer_ = NULL; -} - -void PepperMessageFilter::TCPSocket::OnWriteCompleted(int result) { - DCHECK(write_buffer_.get()); - - if (result >= 0) { - manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK( - routing_id_, plugin_dispatcher_id_, socket_id_, true, result)); - } else { - SendWriteACKError(); - } - write_buffer_ = NULL; -} - -bool PepperMessageFilter::TCPSocket::IsConnected() const { - return connection_state_ == CONNECTED || - connection_state_ == SSL_CONNECTED; -} - -class PepperMessageFilter::UDPSocket { - public: - UDPSocket(PepperMessageFilter* pepper_message_filter, - int32 routing_id, - uint32 plugin_dispatcher_id, - uint32 socket_id); - ~UDPSocket(); - - void Bind(const PP_NetAddress_Private& addr); - void RecvFrom(int32_t num_bytes); - void SendTo(const std::string& data, const PP_NetAddress_Private& addr); - - private: - void SendBindACK(bool result); - void SendRecvFromACKError(); - void SendSendToACKError(); - - void OnRecvFromCompleted(int result); - void OnSendToCompleted(int result); - - PepperMessageFilter* pepper_message_filter_; - int32 routing_id_; - uint32 plugin_dispatcher_id_; - uint32 socket_id_; - - net::OldCompletionCallbackImpl<UDPSocket> recvfrom_callback_; - net::OldCompletionCallbackImpl<UDPSocket> sendto_callback_; - - scoped_ptr<net::UDPServerSocket> socket_; - - scoped_refptr<net::IOBuffer> recvfrom_buffer_; - scoped_refptr<net::IOBuffer> sendto_buffer_; - - net::IPEndPoint recvfrom_address_; - - DISALLOW_COPY_AND_ASSIGN(UDPSocket); -}; - -PepperMessageFilter::UDPSocket::UDPSocket( - PepperMessageFilter* pepper_message_filter, - int32 routing_id, - uint32 plugin_dispatcher_id, - uint32 socket_id) - : pepper_message_filter_(pepper_message_filter), - routing_id_(routing_id), - plugin_dispatcher_id_(plugin_dispatcher_id), - socket_id_(socket_id), - ALLOW_THIS_IN_INITIALIZER_LIST( - recvfrom_callback_(this, &UDPSocket::OnRecvFromCompleted)), - ALLOW_THIS_IN_INITIALIZER_LIST( - sendto_callback_(this, &UDPSocket::OnSendToCompleted)) { - DCHECK(pepper_message_filter); -} - -PepperMessageFilter::UDPSocket::~UDPSocket() { - // Make sure there are no further callbacks from socket_. - if (socket_.get()) - socket_->Close(); -} - -void PepperMessageFilter::UDPSocket::Bind( - const PP_NetAddress_Private& addr) { - socket_.reset(new net::UDPServerSocket(NULL, net::NetLog::Source())); - - net::IPEndPoint address; - if (!socket_.get() || !NetAddressToIPEndPoint(addr, &address)) { - SendBindACK(false); - return; - } - - int result = socket_->Listen(address); - - SendBindACK(result == net::OK); -} - -void PepperMessageFilter::UDPSocket::RecvFrom(int32_t num_bytes) { - if (recvfrom_buffer_.get()) { - SendRecvFromACKError(); - return; - } - - recvfrom_buffer_ = new net::IOBuffer(num_bytes); - int result = socket_->RecvFrom(recvfrom_buffer_, - num_bytes, - &recvfrom_address_, - &recvfrom_callback_); - - if (result != net::ERR_IO_PENDING) - OnRecvFromCompleted(result); -} - -void PepperMessageFilter::UDPSocket::SendTo( - const std::string& data, - const PP_NetAddress_Private& addr) { - if (sendto_buffer_.get() || data.empty()) { - SendSendToACKError(); - return; - } - - net::IPEndPoint address; - if (!NetAddressToIPEndPoint(addr, &address)) { - SendSendToACKError(); - return; - } - - int data_size = data.size(); - - sendto_buffer_ = new net::IOBuffer(data_size); - memcpy(sendto_buffer_->data(), data.data(), data_size); - int result = socket_->SendTo(sendto_buffer_, - data_size, - address, - &sendto_callback_); - - if (result != net::ERR_IO_PENDING) - OnSendToCompleted(result); -} - -void PepperMessageFilter::UDPSocket::SendRecvFromACKError() { - PP_NetAddress_Private addr = kInvalidNetAddress; - pepper_message_filter_->Send( - new PpapiMsg_PPBUDPSocket_RecvFromACK( - routing_id_, plugin_dispatcher_id_, socket_id_, false, - std::string(), addr)); -} - -void PepperMessageFilter::UDPSocket::SendSendToACKError() { - pepper_message_filter_->Send( - new PpapiMsg_PPBUDPSocket_SendToACK( - routing_id_, plugin_dispatcher_id_, socket_id_, false, 0)); -} - -void PepperMessageFilter::UDPSocket::SendBindACK(bool result) { - pepper_message_filter_->Send( - new PpapiMsg_PPBUDPSocket_BindACK( - routing_id_, plugin_dispatcher_id_, socket_id_, result)); -} - -void PepperMessageFilter::UDPSocket::OnRecvFromCompleted(int result) { - DCHECK(recvfrom_buffer_.get()); - - // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private, - // to send back. - PP_NetAddress_Private addr = kInvalidNetAddress; - if (!IPEndPointToNetAddress(recvfrom_address_, &addr) || result < 0) { - SendRecvFromACKError(); - } else { - pepper_message_filter_->Send( - new PpapiMsg_PPBUDPSocket_RecvFromACK( - routing_id_, plugin_dispatcher_id_, socket_id_, true, - std::string(recvfrom_buffer_->data(), result), addr)); - } - - recvfrom_buffer_ = NULL; -} - -void PepperMessageFilter::UDPSocket::OnSendToCompleted(int result) { - DCHECK(sendto_buffer_.get()); - - pepper_message_filter_->Send( - new PpapiMsg_PPBUDPSocket_SendToACK( - routing_id_, plugin_dispatcher_id_, socket_id_, true, result)); - - sendto_buffer_ = NULL; -} - -PepperMessageFilter::TCPSocketManager::TCPSocketManager( - PepperMessageFilter* pepper_message_filter) - : SocketManager<TCPSocket>(pepper_message_filter) { -} - -void PepperMessageFilter::TCPSocketManager::OnMsgCreate( - int32 routing_id, - uint32 plugin_dispatcher_id, - uint32* socket_id) { - if (!GenerateSocketID(socket_id)) - return; - - sockets_[*socket_id] = linked_ptr<TCPSocket>( - new TCPSocket(this, routing_id, plugin_dispatcher_id, *socket_id)); -} - -void PepperMessageFilter::TCPSocketManager::OnMsgConnect( - uint32 socket_id, - const std::string& host, - uint16_t port) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->Connect(host, port); -} - -void PepperMessageFilter::TCPSocketManager::OnMsgConnectWithNetAddress( - uint32 socket_id, - const PP_NetAddress_Private& net_addr) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->ConnectWithNetAddress(net_addr); -} - -void PepperMessageFilter::TCPSocketManager::OnMsgSSLHandshake( - uint32 socket_id, - const std::string& server_name, - uint16_t server_port) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->SSLHandshake(server_name, server_port); -} - -void PepperMessageFilter::TCPSocketManager::OnMsgRead( - uint32 socket_id, - int32_t bytes_to_read) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->Read(bytes_to_read); -} - -void PepperMessageFilter::TCPSocketManager::OnMsgWrite( - uint32 socket_id, - const std::string& data) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->Write(data); -} - -void PepperMessageFilter::TCPSocketManager::OnMsgDisconnect( - uint32 socket_id) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - // Destroy the TCPSocket instance will cancel any pending completion - // callback. From this point on, there won't be any messages associated with - // this socket sent to the plugin side. - sockets_.erase(iter); -} - -net::CertVerifier* -PepperMessageFilter::TCPSocketManager::GetCertVerifier() { - if (!cert_verifier_.get()) - cert_verifier_.reset(new net::CertVerifier()); - - return cert_verifier_.get(); -} - -// UDPSocketManager manages the mapping from socket IDs to UDPSocket -// instances. -class PepperMessageFilter::UDPSocketManager - : public SocketManager<UDPSocket> { - public: - explicit UDPSocketManager(PepperMessageFilter* pepper_message_filter); - - void OnMsgCreate(int32 routing_id, - uint32 plugin_dispatcher_id, - uint32* socket_id); - void OnMsgBind(uint32 socket_id, - const PP_NetAddress_Private& addr); - void OnMsgRecvFrom(uint32 socket_id, - int32_t num_bytes); - void OnMsgSendTo(uint32 socket_id, - const std::string& data, - const PP_NetAddress_Private& addr); - void OnMsgClose(uint32 socket_id); - - private: - DISALLOW_COPY_AND_ASSIGN(UDPSocketManager); -}; - -PepperMessageFilter::UDPSocketManager::UDPSocketManager( - PepperMessageFilter* pepper_message_filter) - : SocketManager<UDPSocket>(pepper_message_filter) { -} - -void PepperMessageFilter::UDPSocketManager::OnMsgCreate( - int32 routing_id, - uint32 plugin_dispatcher_id, - uint32* socket_id) { - if (!GenerateSocketID(socket_id)) - return; - - sockets_[*socket_id] = linked_ptr<UDPSocket>( - new UDPSocket(pepper_message_filter_, routing_id, - plugin_dispatcher_id, *socket_id)); -} - -void PepperMessageFilter::UDPSocketManager::OnMsgBind( - uint32 socket_id, - const PP_NetAddress_Private& addr) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->Bind(addr); -} - -void PepperMessageFilter::UDPSocketManager::OnMsgRecvFrom( - uint32 socket_id, - int32_t num_bytes) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->RecvFrom(num_bytes); -} - -void PepperMessageFilter::UDPSocketManager::OnMsgSendTo( - uint32 socket_id, - const std::string& data, - const PP_NetAddress_Private& addr) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - iter->second->SendTo(data, addr); -} - -void PepperMessageFilter::UDPSocketManager::OnMsgClose( - uint32 socket_id) { - SocketMap::iterator iter = sockets_.find(socket_id); - if (iter == sockets_.end()) { - NOTREACHED(); - return; - } - - // Destroy the UDPSocket instance will cancel any pending completion - // callback. From this point on, there won't be any messages associated with - // this socket sent to the plugin side. - sockets_.erase(iter); -} - PepperMessageFilter::PepperMessageFilter( const content::ResourceContext* resource_context) : resource_context_(resource_context), host_resolver_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST( - socket_manager_tcp_(new TCPSocketManager(this))), - ALLOW_THIS_IN_INITIALIZER_LIST( - socket_manager_udp_(new UDPSocketManager(this))) { + next_socket_id_(1) { DCHECK(resource_context_); } PepperMessageFilter::PepperMessageFilter(net::HostResolver* host_resolver) : resource_context_(NULL), host_resolver_(host_resolver), - ALLOW_THIS_IN_INITIALIZER_LIST( - socket_manager_tcp_(new TCPSocketManager(this))), - ALLOW_THIS_IN_INITIALIZER_LIST( - socket_manager_udp_(new UDPSocketManager(this))) { + next_socket_id_(1) { DCHECK(host_resolver); } @@ -936,52 +77,41 @@ bool PepperMessageFilter::OnMessageReceived(const IPC::Message& msg, OnGetLocalTimeZoneOffset) IPC_MESSAGE_HANDLER_DELAY_REPLY(PpapiHostMsg_PPBFont_GetFontFamilies, OnGetFontFamilies) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_Create, - socket_manager_tcp_.get(), TCPSocketManager::OnMsgCreate) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_Connect, - socket_manager_tcp_.get(), TCPSocketManager::OnMsgConnect) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress, - socket_manager_tcp_.get(), - TCPSocketManager::OnMsgConnectWithNetAddress) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_SSLHandshake, - socket_manager_tcp_.get(), - TCPSocketManager::OnMsgSSLHandshake) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_Read, - socket_manager_tcp_.get(), TCPSocketManager::OnMsgRead) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_Write, - socket_manager_tcp_.get(), TCPSocketManager::OnMsgWrite) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBTCPSocket_Disconnect, - socket_manager_tcp_.get(), TCPSocketManager::OnMsgDisconnect) - - // UDP - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBUDPSocket_Create, - socket_manager_udp_.get(), UDPSocketManager::OnMsgCreate) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBUDPSocket_Bind, - socket_manager_udp_.get(), UDPSocketManager::OnMsgBind) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBUDPSocket_RecvFrom, - socket_manager_udp_.get(), UDPSocketManager::OnMsgRecvFrom) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBUDPSocket_SendTo, - socket_manager_udp_.get(), UDPSocketManager::OnMsgSendTo) - IPC_MESSAGE_FORWARD( - PpapiHostMsg_PPBUDPSocket_Close, - socket_manager_udp_.get(), UDPSocketManager::OnMsgClose) + // TCP messages. + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Create, OnTCPCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Connect, OnTCPConnect) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_ConnectWithNetAddress, + OnTCPConnectWithNetAddress) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_SSLHandshake, + OnTCPSSLHandshake) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Read, OnTCPRead) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Write, OnTCPWrite) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTCPSocket_Disconnect, OnTCPDisconnect) + + // UDP messages. + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBUDPSocket_Create, OnUDPCreate) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBUDPSocket_Bind, OnUDPBind) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBUDPSocket_RecvFrom, OnUDPRecvFrom) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBUDPSocket_SendTo, OnUDPSendTo) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBUDPSocket_Close, OnUDPClose) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() return handled; } +net::HostResolver* PepperMessageFilter::GetHostResolver() { + return resource_context_ ? + resource_context_->host_resolver() : host_resolver_; +} + +net::CertVerifier* PepperMessageFilter::GetCertVerifier() { + if (!cert_verifier_.get()) + cert_verifier_.reset(new net::CertVerifier()); + + return cert_verifier_.get(); +} + #if defined(ENABLE_FLAPPER_HACKS) namespace { @@ -989,8 +119,8 @@ namespace { int ConnectTcpSocket(const PP_NetAddress_Private& addr, PP_NetAddress_Private* local_addr_out, PP_NetAddress_Private* remote_addr_out) { - *local_addr_out = kInvalidNetAddress; - *remote_addr_out = kInvalidNetAddress; + *local_addr_out = NetAddressPrivateImpl::kInvalidNetAddress; + *remote_addr_out = NetAddressPrivateImpl::kInvalidNetAddress; const struct sockaddr* sa = reinterpret_cast<const struct sockaddr*>(addr.data); @@ -1085,7 +215,7 @@ void PepperMessageFilter::OnConnectTcpAddress( // Validate the address and then continue (doing |connect()|) on a worker // thread. - if (!ppapi::NetAddressPrivateImpl::ValidateNetAddress(addr) || + if (!NetAddressPrivateImpl::ValidateNetAddress(addr) || !base::WorkerPool::PostTask( FROM_HERE, base::Bind( @@ -1098,10 +228,10 @@ void PepperMessageFilter::OnConnectTcpAddress( bool PepperMessageFilter::SendConnectTcpACKError(int routing_id, int request_id) { - return Send( - new PepperMsg_ConnectTcpACK(routing_id, request_id, - IPC::InvalidPlatformFileForTransit(), - kInvalidNetAddress, kInvalidNetAddress)); + return Send(new PepperMsg_ConnectTcpACK( + routing_id, request_id, IPC::InvalidPlatformFileForTransit(), + NetAddressPrivateImpl::kInvalidNetAddress, + NetAddressPrivateImpl::kInvalidNetAddress)); } void PepperMessageFilter::ConnectTcpLookupFinished( @@ -1128,12 +258,13 @@ void PepperMessageFilter::ConnectTcpOnWorkerThread(int routing_id, net::AddressList addresses) { IPC::PlatformFileForTransit socket_for_transit = IPC::InvalidPlatformFileForTransit(); - PP_NetAddress_Private local_addr = kInvalidNetAddress; - PP_NetAddress_Private remote_addr = kInvalidNetAddress; - PP_NetAddress_Private addr = kInvalidNetAddress; + PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress; + PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress; + PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; for (const struct addrinfo* ai = addresses.head(); ai; ai = ai->ai_next) { - if (SockaddrToNetAddress(ai->ai_addr, ai->ai_addrlen, &addr)) { + if (NetAddressPrivateImpl::SockaddrToNetAddress(ai->ai_addr, ai->ai_addrlen, + &addr)) { int fd = ConnectTcpSocket(addr, &local_addr, &remote_addr); if (fd != -1) { socket_for_transit = base::FileDescriptor(fd, true); @@ -1161,8 +292,8 @@ void PepperMessageFilter::ConnectTcpAddressOnWorkerThread( PP_NetAddress_Private addr) { IPC::PlatformFileForTransit socket_for_transit = IPC::InvalidPlatformFileForTransit(); - PP_NetAddress_Private local_addr = kInvalidNetAddress; - PP_NetAddress_Private remote_addr = kInvalidNetAddress; + PP_NetAddress_Private local_addr = NetAddressPrivateImpl::kInvalidNetAddress; + PP_NetAddress_Private remote_addr = NetAddressPrivateImpl::kInvalidNetAddress; int fd = ConnectTcpSocket(addr, &local_addr, &remote_addr); if (fd != -1) @@ -1209,6 +340,144 @@ void PepperMessageFilter::OnGetFontFamilies(IPC::Message* reply_msg) { this, reply_msg)); } +void PepperMessageFilter::OnTCPCreate(int32 routing_id, + uint32 plugin_dispatcher_id, + uint32* socket_id) { + *socket_id = GenerateSocketID(); + if (*socket_id == kInvalidSocketID) + return; + + tcp_sockets_[*socket_id] = linked_ptr<PepperTCPSocket>( + new PepperTCPSocket(this, routing_id, plugin_dispatcher_id, *socket_id)); +} + +void PepperMessageFilter::OnTCPConnect(uint32 socket_id, + const std::string& host, + uint16_t port) { + TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); + if (iter == tcp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->Connect(host, port); +} + +void PepperMessageFilter::OnTCPConnectWithNetAddress( + uint32 socket_id, + const PP_NetAddress_Private& net_addr) { + TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); + if (iter == tcp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->ConnectWithNetAddress(net_addr); +} + +void PepperMessageFilter::OnTCPSSLHandshake(uint32 socket_id, + const std::string& server_name, + uint16_t server_port) { + TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); + if (iter == tcp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->SSLHandshake(server_name, server_port); +} + +void PepperMessageFilter::OnTCPRead(uint32 socket_id, int32_t bytes_to_read) { + TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); + if (iter == tcp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->Read(bytes_to_read); +} + +void PepperMessageFilter::OnTCPWrite(uint32 socket_id, + const std::string& data) { + TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); + if (iter == tcp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->Write(data); +} + +void PepperMessageFilter::OnTCPDisconnect(uint32 socket_id) { + TCPSocketMap::iterator iter = tcp_sockets_.find(socket_id); + if (iter == tcp_sockets_.end()) { + NOTREACHED(); + return; + } + + // Destroy the TCPSocket instance will cancel any pending completion + // callback. From this point on, there won't be any messages associated with + // this socket sent to the plugin side. + tcp_sockets_.erase(iter); +} + +void PepperMessageFilter::OnUDPCreate(int32 routing_id, + uint32 plugin_dispatcher_id, + uint32* socket_id) { + *socket_id = GenerateSocketID(); + if (*socket_id == kInvalidSocketID) + return; + + udp_sockets_[*socket_id] = linked_ptr<PepperUDPSocket>( + new PepperUDPSocket(this, routing_id, plugin_dispatcher_id, *socket_id)); +} + +void PepperMessageFilter::OnUDPBind(uint32 socket_id, + const PP_NetAddress_Private& addr) { + UDPSocketMap::iterator iter = udp_sockets_.find(socket_id); + if (iter == udp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->Bind(addr); +} + +void PepperMessageFilter::OnUDPRecvFrom(uint32 socket_id, int32_t num_bytes) { + UDPSocketMap::iterator iter = udp_sockets_.find(socket_id); + if (iter == udp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->RecvFrom(num_bytes); +} + +void PepperMessageFilter::OnUDPSendTo(uint32 socket_id, + const std::string& data, + const PP_NetAddress_Private& addr) { + UDPSocketMap::iterator iter = udp_sockets_.find(socket_id); + if (iter == udp_sockets_.end()) { + NOTREACHED(); + return; + } + + iter->second->SendTo(data, addr); +} + +void PepperMessageFilter::OnUDPClose(uint32 socket_id) { + UDPSocketMap::iterator iter = udp_sockets_.find(socket_id); + if (iter == udp_sockets_.end()) { + NOTREACHED(); + return; + } + + // Destroy the UDPSocket instance will cancel any pending completion + // callback. From this point on, there won't be any messages associated with + // this socket sent to the plugin side. + udp_sockets_.erase(iter); +} + void PepperMessageFilter::GetFontFamiliesComplete( IPC::Message* reply_msg, scoped_refptr<content::FontListResult> result) { @@ -1237,8 +506,27 @@ void PepperMessageFilter::GetFontFamiliesComplete( Send(reply_msg); } -net::HostResolver* PepperMessageFilter::GetHostResolver() { - if (resource_context_) - return resource_context_->host_resolver(); - return host_resolver_; +uint32 PepperMessageFilter::GenerateSocketID() { + // TODO(yzshen): Change to use Pepper resource ID as socket ID. + // + // Generate a socket ID. For each process which sends us socket requests, IDs + // of living sockets must be unique, to each socket type. + // + // However, it is safe to generate IDs based on the internal state of a single + // PepperSocketMessageHandler object, because for each plugin or renderer + // process, there is at most one PepperMessageFilter (in other words, at most + // one PepperSocketMessageHandler) talking to it. + if (tcp_sockets_.size() + udp_sockets_.size() >= kMaxSocketsAllowed) + return kInvalidSocketID; + + uint32 socket_id = kInvalidSocketID; + do { + // Although it is unlikely, make sure that we won't cause any trouble when + // the counter overflows. + socket_id = next_socket_id_++; + } while (socket_id == kInvalidSocketID || + tcp_sockets_.find(socket_id) != tcp_sockets_.end() || + udp_sockets_.find(socket_id) != udp_sockets_.end()); + + return socket_id; } diff --git a/content/browser/renderer_host/pepper_message_filter.h b/content/browser/renderer_host/pepper_message_filter.h index 00240db..1afcdc8 100644 --- a/content/browser/renderer_host/pepper_message_filter.h +++ b/content/browser/renderer_host/pepper_message_filter.h @@ -6,14 +6,21 @@ #define CONTENT_BROWSER_RENDERER_HOST_PEPPER_MESSAGE_FILTER_H_ #pragma once +#include <map> #include <string> #include "base/basictypes.h" +#include "base/memory/linked_ptr.h" +#include "base/memory/scoped_ptr.h" #include "base/process.h" #include "base/time.h" #include "content/browser/browser_message_filter.h" #include "content/browser/font_list_async.h" +#include "net/base/ssl_config_service.h" +#include "ppapi/c/pp_stdint.h" +class PepperTCPSocket; +class PepperUDPSocket; struct PP_NetAddress_Private; namespace content { @@ -22,6 +29,7 @@ class ResourceContext; namespace net { class AddressList; +class CertVerifier; class HostResolver; } @@ -33,7 +41,7 @@ class HostResolver; class PepperMessageFilter : public BrowserMessageFilter { public: explicit PepperMessageFilter( - const content::ResourceContext* resource_context); + const content::ResourceContext* resource_context); explicit PepperMessageFilter(net::HostResolver* host_resolver); virtual ~PepperMessageFilter(); @@ -41,13 +49,15 @@ class PepperMessageFilter : public BrowserMessageFilter { virtual bool OnMessageReceived(const IPC::Message& message, bool* message_was_ok) OVERRIDE; - private: - template<class SocketType> class SocketManager; - class TCPSocket; - class TCPSocketManager; - class UDPSocket; - class UDPSocketManager; + // Returns the host resolver (it may come from the resource context or the + // host_resolver_ member). + net::HostResolver* GetHostResolver(); + net::CertVerifier* GetCertVerifier(); + + const net::SSLConfig& ssl_config() { return ssl_config_; } + + private: #if defined(ENABLE_FLAPPER_HACKS) // Message handlers. void OnConnectTcp(int routing_id, @@ -83,13 +93,34 @@ class PepperMessageFilter : public BrowserMessageFilter { void OnGetLocalTimeZoneOffset(base::Time t, double* result); void OnGetFontFamilies(IPC::Message* reply); + void OnTCPCreate(int32 routing_id, + uint32 plugin_dispatcher_id, + uint32* socket_id); + void OnTCPConnect(uint32 socket_id, const std::string& host, uint16_t port); + void OnTCPConnectWithNetAddress(uint32 socket_id, + const PP_NetAddress_Private& net_addr); + void OnTCPSSLHandshake(uint32 socket_id, + const std::string& server_name, + uint16_t server_port); + void OnTCPRead(uint32 socket_id, int32_t bytes_to_read); + void OnTCPWrite(uint32 socket_id, const std::string& data); + void OnTCPDisconnect(uint32 socket_id); + + void OnUDPCreate(int32 routing_id, + uint32 plugin_dispatcher_id, + uint32* socket_id); + void OnUDPBind(uint32 socket_id, const PP_NetAddress_Private& addr); + void OnUDPRecvFrom(uint32 socket_id, int32_t num_bytes); + void OnUDPSendTo(uint32 socket_id, + const std::string& data, + const PP_NetAddress_Private& addr); + void OnUDPClose(uint32 socket_id); + // Callback when the font list has been retrieved on a background thread. void GetFontFamiliesComplete(IPC::Message* reply_msg, scoped_refptr<content::FontListResult> result); - // Returns the host resolver (it may come from the resource context or the - // host_resolver_ member). - net::HostResolver* GetHostResolver(); + uint32 GenerateSocketID(); // When non-NULL, this should be used instead of the host_resolver_. const content::ResourceContext* const resource_context_; @@ -98,8 +129,19 @@ class PepperMessageFilter : public BrowserMessageFilter { // GetHostResolver instead of accessing directly. net::HostResolver* host_resolver_; - scoped_ptr<TCPSocketManager> socket_manager_tcp_; - scoped_ptr<UDPSocketManager> socket_manager_udp_; + // The default SSL configuration settings are used, as opposed to Chrome's SSL + // settings. + net::SSLConfig ssl_config_; + // This is lazily created. Users should use GetCertVerifier to retrieve it. + scoped_ptr<net::CertVerifier> cert_verifier_; + + uint32 next_socket_id_; + + typedef std::map<uint32, linked_ptr<PepperTCPSocket> > TCPSocketMap; + TCPSocketMap tcp_sockets_; + + typedef std::map<uint32, linked_ptr<PepperUDPSocket> > UDPSocketMap; + UDPSocketMap udp_sockets_; DISALLOW_COPY_AND_ASSIGN(PepperMessageFilter); }; diff --git a/content/browser/renderer_host/pepper_tcp_socket.cc b/content/browser/renderer_host/pepper_tcp_socket.cc new file mode 100644 index 0000000..925a0c9 --- /dev/null +++ b/content/browser/renderer_host/pepper_tcp_socket.cc @@ -0,0 +1,286 @@ +// Copyright (c) 2011 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 "content/browser/renderer_host/pepper_tcp_socket.h" + +#include <string.h> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "content/browser/renderer_host/pepper_message_filter.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/cert_verifier.h" +#include "net/base/host_port_pair.h" +#include "net/base/host_resolver.h" +#include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" +#include "net/base/single_request_host_resolver.h" +#include "net/socket/client_socket_factory.h" +#include "net/socket/client_socket_handle.h" +#include "net/socket/ssl_client_socket.h" +#include "net/socket/tcp_client_socket.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_tcp_socket_private_proxy.h" +#include "ppapi/shared_impl/private/net_address_private_impl.h" + +using content::BrowserThread; +using ppapi::NetAddressPrivateImpl; + +PepperTCPSocket::PepperTCPSocket( + PepperMessageFilter* manager, + int32 routing_id, + uint32 plugin_dispatcher_id, + uint32 socket_id) + : manager_(manager), + routing_id_(routing_id), + plugin_dispatcher_id_(plugin_dispatcher_id), + socket_id_(socket_id), + connection_state_(BEFORE_CONNECT), + end_of_file_reached_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(connect_callback_( + this, &PepperTCPSocket::OnConnectCompleted)), + ALLOW_THIS_IN_INITIALIZER_LIST(ssl_handshake_callback_( + this, &PepperTCPSocket::OnSSLHandshakeCompleted)), + ALLOW_THIS_IN_INITIALIZER_LIST( + read_callback_(this, &PepperTCPSocket::OnReadCompleted)), + ALLOW_THIS_IN_INITIALIZER_LIST( + write_callback_(this, &PepperTCPSocket::OnWriteCompleted)) { + DCHECK(manager); +} + +PepperTCPSocket::~PepperTCPSocket() { + // Make sure no further callbacks from socket_. + if (socket_.get()) + socket_->Disconnect(); +} + +void PepperTCPSocket::Connect(const std::string& host, uint16_t port) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (connection_state_ != BEFORE_CONNECT) { + SendConnectACKError(); + return; + } + + connection_state_ = CONNECT_IN_PROGRESS; + net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); + resolver_.reset(new net::SingleRequestHostResolver( + manager_->GetHostResolver())); + int result = resolver_->Resolve( + request_info, &address_list_, + base::Bind(&PepperTCPSocket::OnResolveCompleted, base::Unretained(this)), + net::BoundNetLog()); + if (result != net::ERR_IO_PENDING) + OnResolveCompleted(result); +} + +void PepperTCPSocket::ConnectWithNetAddress( + const PP_NetAddress_Private& net_addr) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (connection_state_ != BEFORE_CONNECT || + !NetAddressPrivateImpl::NetAddressToAddressList(net_addr, + &address_list_)) { + SendConnectACKError(); + return; + } + + connection_state_ = CONNECT_IN_PROGRESS; + StartConnect(address_list_); +} + +void PepperTCPSocket::SSLHandshake(const std::string& server_name, + uint16_t server_port) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + // Allow to do SSL handshake only if currently the socket has been connected + // and there isn't pending read or write. + // IsConnected() includes the state that SSL handshake has been finished and + // therefore isn't suitable here. + if (connection_state_ != CONNECTED || read_buffer_.get() || + write_buffer_.get()) { + SendSSLHandshakeACK(false); + return; + } + + connection_state_ = SSL_HANDSHAKE_IN_PROGRESS; + net::ClientSocketHandle* handle = new net::ClientSocketHandle(); + handle->set_socket(socket_.release()); + net::ClientSocketFactory* factory = + net::ClientSocketFactory::GetDefaultFactory(); + net::HostPortPair host_port_pair(server_name, server_port); + net::SSLClientSocketContext ssl_context; + ssl_context.cert_verifier = manager_->GetCertVerifier(); + socket_.reset(factory->CreateSSLClientSocket( + handle, host_port_pair, manager_->ssl_config(), NULL, ssl_context)); + if (!socket_.get()) { + LOG(WARNING) << "Failed to create an SSL client socket."; + OnSSLHandshakeCompleted(net::ERR_UNEXPECTED); + return; + } + + int result = socket_->Connect(&ssl_handshake_callback_); + if (result != net::ERR_IO_PENDING) + OnSSLHandshakeCompleted(result); +} + +void PepperTCPSocket::Read(int32 bytes_to_read) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (!IsConnected() || end_of_file_reached_ || read_buffer_.get() || + bytes_to_read <= 0) { + SendReadACKError(); + return; + } + + if (bytes_to_read > ppapi::proxy::kTCPSocketMaxReadSize) { + NOTREACHED(); + bytes_to_read = ppapi::proxy::kTCPSocketMaxReadSize; + } + + read_buffer_ = new net::IOBuffer(bytes_to_read); + int result = socket_->Read(read_buffer_, bytes_to_read, &read_callback_); + if (result != net::ERR_IO_PENDING) + OnReadCompleted(result); +} + +void PepperTCPSocket::Write(const std::string& data) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (!IsConnected() || write_buffer_.get() || data.empty()) { + SendWriteACKError(); + return; + } + + int data_size = data.size(); + if (data_size > ppapi::proxy::kTCPSocketMaxWriteSize) { + NOTREACHED(); + data_size = ppapi::proxy::kTCPSocketMaxWriteSize; + } + + write_buffer_ = new net::IOBuffer(data_size); + memcpy(write_buffer_->data(), data.c_str(), data_size); + int result = socket_->Write(write_buffer_, data.size(), &write_callback_); + if (result != net::ERR_IO_PENDING) + OnWriteCompleted(result); +} + +void PepperTCPSocket::StartConnect(const net::AddressList& addresses) { + DCHECK(connection_state_ == CONNECT_IN_PROGRESS); + + socket_.reset( + new net::TCPClientSocket(addresses, NULL, net::NetLog::Source())); + int result = socket_->Connect(&connect_callback_); + if (result != net::ERR_IO_PENDING) + OnConnectCompleted(result); +} + +void PepperTCPSocket::SendConnectACKError() { + manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK( + routing_id_, plugin_dispatcher_id_, socket_id_, false, + NetAddressPrivateImpl::kInvalidNetAddress, + NetAddressPrivateImpl::kInvalidNetAddress)); +} + +void PepperTCPSocket::SendReadACKError() { + manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK( + routing_id_, plugin_dispatcher_id_, socket_id_, false, std::string())); +} + +void PepperTCPSocket::SendWriteACKError() { + manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK( + routing_id_, plugin_dispatcher_id_, socket_id_, false, 0)); +} + +void PepperTCPSocket::SendSSLHandshakeACK(bool succeeded) { + manager_->Send(new PpapiMsg_PPBTCPSocket_SSLHandshakeACK( + routing_id_, plugin_dispatcher_id_, socket_id_, succeeded)); +} + +void PepperTCPSocket::OnResolveCompleted(int result) { + DCHECK(connection_state_ == CONNECT_IN_PROGRESS); + + if (result != net::OK) { + SendConnectACKError(); + connection_state_ = BEFORE_CONNECT; + return; + } + + StartConnect(address_list_); +} + +void PepperTCPSocket::OnConnectCompleted(int result) { + DCHECK(connection_state_ == CONNECT_IN_PROGRESS && socket_.get()); + + if (result != net::OK) { + SendConnectACKError(); + connection_state_ = BEFORE_CONNECT; + } else { + net::IPEndPoint ip_end_point; + net::AddressList address_list; + PP_NetAddress_Private local_addr = + NetAddressPrivateImpl::kInvalidNetAddress; + PP_NetAddress_Private remote_addr = + NetAddressPrivateImpl::kInvalidNetAddress; + + if (socket_->GetLocalAddress(&ip_end_point) != net::OK || + !NetAddressPrivateImpl::IPEndPointToNetAddress(ip_end_point, + &local_addr) || + socket_->GetPeerAddress(&address_list) != net::OK || + !NetAddressPrivateImpl::AddressListToNetAddress(address_list, + &remote_addr)) { + SendConnectACKError(); + connection_state_ = BEFORE_CONNECT; + } else { + manager_->Send(new PpapiMsg_PPBTCPSocket_ConnectACK( + routing_id_, plugin_dispatcher_id_, socket_id_, true, + local_addr, remote_addr)); + connection_state_ = CONNECTED; + } + } +} + +void PepperTCPSocket::OnSSLHandshakeCompleted(int result) { + DCHECK(connection_state_ == SSL_HANDSHAKE_IN_PROGRESS); + + bool succeeded = result == net::OK; + SendSSLHandshakeACK(succeeded); + connection_state_ = succeeded ? SSL_CONNECTED : SSL_HANDSHAKE_FAILED; +} + +void PepperTCPSocket::OnReadCompleted(int result) { + DCHECK(read_buffer_.get()); + + if (result > 0) { + manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK( + routing_id_, plugin_dispatcher_id_, socket_id_, true, + std::string(read_buffer_->data(), result))); + } else if (result == 0) { + end_of_file_reached_ = true; + manager_->Send(new PpapiMsg_PPBTCPSocket_ReadACK( + routing_id_, plugin_dispatcher_id_, socket_id_, true, std::string())); + } else { + SendReadACKError(); + } + read_buffer_ = NULL; +} + +void PepperTCPSocket::OnWriteCompleted(int result) { + DCHECK(write_buffer_.get()); + + if (result >= 0) { + manager_->Send(new PpapiMsg_PPBTCPSocket_WriteACK( + routing_id_, plugin_dispatcher_id_, socket_id_, true, result)); + } else { + SendWriteACKError(); + } + write_buffer_ = NULL; +} + +bool PepperTCPSocket::IsConnected() const { + return connection_state_ == CONNECTED || connection_state_ == SSL_CONNECTED; +} diff --git a/content/browser/renderer_host/pepper_tcp_socket.h b/content/browser/renderer_host/pepper_tcp_socket.h new file mode 100644 index 0000000..882e22e --- /dev/null +++ b/content/browser/renderer_host/pepper_tcp_socket.h @@ -0,0 +1,99 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_TCP_SOCKET_H_ +#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_TCP_SOCKET_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/address_list.h" +#include "net/base/completion_callback.h" +#include "ppapi/c/pp_stdint.h" + +class PepperMessageFilter; +struct PP_NetAddress_Private; + +namespace net { +class IOBuffer; +class SingleRequestHostResolver; +class StreamSocket; +} + +// PepperTCPSocket is used by PepperMessageFilter to handle requests from +// the Pepper TCP socket API (PPB_TCPSocket_Private). +class PepperTCPSocket { + public: + PepperTCPSocket(PepperMessageFilter* manager, + int32 routing_id, + uint32 plugin_dispatcher_id, + uint32 socket_id); + ~PepperTCPSocket(); + + void Connect(const std::string& host, uint16_t port); + void ConnectWithNetAddress(const PP_NetAddress_Private& net_addr); + void SSLHandshake(const std::string& server_name, uint16_t server_port); + void Read(int32 bytes_to_read); + void Write(const std::string& data); + + private: + enum ConnectionState { + // Before a connection is successfully established (including a previous + // connect request failed). + BEFORE_CONNECT, + // There is a connect request that is pending. + CONNECT_IN_PROGRESS, + // A connection has been successfully established. + CONNECTED, + // There is an SSL handshake request that is pending. + SSL_HANDSHAKE_IN_PROGRESS, + // An SSL connection has been successfully established. + SSL_CONNECTED, + // An SSL handshake has failed. + SSL_HANDSHAKE_FAILED + }; + + void StartConnect(const net::AddressList& addresses); + + void SendConnectACKError(); + void SendReadACKError(); + void SendWriteACKError(); + void SendSSLHandshakeACK(bool succeeded); + + void OnResolveCompleted(int result); + void OnConnectCompleted(int result); + void OnSSLHandshakeCompleted(int result); + void OnReadCompleted(int result); + void OnWriteCompleted(int result); + + bool IsConnected() const; + + PepperMessageFilter* manager_; + int32 routing_id_; + uint32 plugin_dispatcher_id_; + uint32 socket_id_; + + ConnectionState connection_state_; + bool end_of_file_reached_; + + net::OldCompletionCallbackImpl<PepperTCPSocket> connect_callback_; + net::OldCompletionCallbackImpl<PepperTCPSocket> ssl_handshake_callback_; + net::OldCompletionCallbackImpl<PepperTCPSocket> read_callback_; + net::OldCompletionCallbackImpl<PepperTCPSocket> write_callback_; + + scoped_ptr<net::SingleRequestHostResolver> resolver_; + net::AddressList address_list_; + + scoped_ptr<net::StreamSocket> socket_; + + scoped_refptr<net::IOBuffer> read_buffer_; + scoped_refptr<net::IOBuffer> write_buffer_; + + DISALLOW_COPY_AND_ASSIGN(PepperTCPSocket); +}; + +#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_TCP_SOCKET_H_ diff --git a/content/browser/renderer_host/pepper_udp_socket.cc b/content/browser/renderer_host/pepper_udp_socket.cc new file mode 100644 index 0000000..680625a --- /dev/null +++ b/content/browser/renderer_host/pepper_udp_socket.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2011 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 "content/browser/renderer_host/pepper_udp_socket.h" + +#include <string.h> + +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "content/browser/renderer_host/pepper_message_filter.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/udp/udp_server_socket.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/proxy/ppb_udp_socket_private_proxy.h" +#include "ppapi/shared_impl/private/net_address_private_impl.h" + +using content::BrowserThread; +using ppapi::NetAddressPrivateImpl; + +PepperUDPSocket::PepperUDPSocket( + PepperMessageFilter* manager, + int32 routing_id, + uint32 plugin_dispatcher_id, + uint32 socket_id) + : manager_(manager), + routing_id_(routing_id), + plugin_dispatcher_id_(plugin_dispatcher_id), + socket_id_(socket_id), + ALLOW_THIS_IN_INITIALIZER_LIST( + recvfrom_callback_(this, &PepperUDPSocket::OnRecvFromCompleted)), + ALLOW_THIS_IN_INITIALIZER_LIST( + sendto_callback_(this, &PepperUDPSocket::OnSendToCompleted)) { + DCHECK(manager); +} + +PepperUDPSocket::~PepperUDPSocket() { + // Make sure there are no further callbacks from socket_. + if (socket_.get()) + socket_->Close(); +} + +void PepperUDPSocket::Bind(const PP_NetAddress_Private& addr) { + socket_.reset(new net::UDPServerSocket(NULL, net::NetLog::Source())); + + net::IPEndPoint address; + if (!socket_.get() || + !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address)) { + SendBindACK(false); + return; + } + + int result = socket_->Listen(address); + + SendBindACK(result == net::OK); +} + +void PepperUDPSocket::RecvFrom(int32_t num_bytes) { + if (recvfrom_buffer_.get()) { + SendRecvFromACKError(); + return; + } + + recvfrom_buffer_ = new net::IOBuffer(num_bytes); + int result = socket_->RecvFrom(recvfrom_buffer_, + num_bytes, + &recvfrom_address_, + &recvfrom_callback_); + + if (result != net::ERR_IO_PENDING) + OnRecvFromCompleted(result); +} + +void PepperUDPSocket::SendTo(const std::string& data, + const PP_NetAddress_Private& addr) { + if (sendto_buffer_.get() || data.empty()) { + SendSendToACKError(); + return; + } + + net::IPEndPoint address; + if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address)) { + SendSendToACKError(); + return; + } + + int data_size = data.size(); + + sendto_buffer_ = new net::IOBuffer(data_size); + memcpy(sendto_buffer_->data(), data.data(), data_size); + int result = socket_->SendTo(sendto_buffer_, + data_size, + address, + &sendto_callback_); + + if (result != net::ERR_IO_PENDING) + OnSendToCompleted(result); +} + +void PepperUDPSocket::SendRecvFromACKError() { + PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; + manager_->Send(new PpapiMsg_PPBUDPSocket_RecvFromACK( + routing_id_, plugin_dispatcher_id_, socket_id_, false, std::string(), + addr)); +} + +void PepperUDPSocket::SendSendToACKError() { + manager_->Send(new PpapiMsg_PPBUDPSocket_SendToACK( + routing_id_, plugin_dispatcher_id_, socket_id_, false, 0)); +} + +void PepperUDPSocket::SendBindACK(bool result) { + manager_->Send(new PpapiMsg_PPBUDPSocket_BindACK( + routing_id_, plugin_dispatcher_id_, socket_id_, result)); +} + +void PepperUDPSocket::OnRecvFromCompleted(int result) { + DCHECK(recvfrom_buffer_.get()); + + // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private, + // to send back. + PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; + if (result < 0 || + !NetAddressPrivateImpl::IPEndPointToNetAddress(recvfrom_address_, + &addr)) { + SendRecvFromACKError(); + } else { + manager_->Send(new PpapiMsg_PPBUDPSocket_RecvFromACK( + routing_id_, plugin_dispatcher_id_, socket_id_, true, + std::string(recvfrom_buffer_->data(), result), addr)); + } + + recvfrom_buffer_ = NULL; +} + +void PepperUDPSocket::OnSendToCompleted(int result) { + DCHECK(sendto_buffer_.get()); + + manager_->Send(new PpapiMsg_PPBUDPSocket_SendToACK( + routing_id_, plugin_dispatcher_id_, socket_id_, true, result)); + + sendto_buffer_ = NULL; +} diff --git a/content/browser/renderer_host/pepper_udp_socket.h b/content/browser/renderer_host/pepper_udp_socket.h new file mode 100644 index 0000000..83dad8c --- /dev/null +++ b/content/browser/renderer_host/pepper_udp_socket.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_PEPPER_UDP_SOCKET_H_ +#define CONTENT_BROWSER_RENDERER_HOST_PEPPER_UDP_SOCKET_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/completion_callback.h" +#include "net/base/ip_endpoint.h" +#include "ppapi/c/pp_stdint.h" + +class PepperMessageFilter; +struct PP_NetAddress_Private; + +namespace net { +class IOBuffer; +class UDPServerSocket; +} + +// PepperUDPSocket is used by PepperMessageFilter to handle requests from +// the Pepper UDP socket API (PPB_UDPSocket_Private). +class PepperUDPSocket { + public: + PepperUDPSocket(PepperMessageFilter* manager, + int32 routing_id, + uint32 plugin_dispatcher_id, + uint32 socket_id); + ~PepperUDPSocket(); + + void Bind(const PP_NetAddress_Private& addr); + void RecvFrom(int32_t num_bytes); + void SendTo(const std::string& data, const PP_NetAddress_Private& addr); + + private: + void SendBindACK(bool result); + void SendRecvFromACKError(); + void SendSendToACKError(); + + void OnRecvFromCompleted(int result); + void OnSendToCompleted(int result); + + PepperMessageFilter* manager_; + int32 routing_id_; + uint32 plugin_dispatcher_id_; + uint32 socket_id_; + + net::OldCompletionCallbackImpl<PepperUDPSocket> recvfrom_callback_; + net::OldCompletionCallbackImpl<PepperUDPSocket> sendto_callback_; + + scoped_ptr<net::UDPServerSocket> socket_; + + scoped_refptr<net::IOBuffer> recvfrom_buffer_; + scoped_refptr<net::IOBuffer> sendto_buffer_; + + net::IPEndPoint recvfrom_address_; + + DISALLOW_COPY_AND_ASSIGN(PepperUDPSocket); +}; + +#endif // CONTENT_BROWSER_RENDERER_HOST_PEPPER_UDP_SOCKET_H_ diff --git a/content/content_browser.gypi b/content/content_browser.gypi index b7bf11d..fa8203d 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -427,6 +427,10 @@ 'browser/renderer_host/pepper_file_message_filter.h', 'browser/renderer_host/pepper_message_filter.cc', 'browser/renderer_host/pepper_message_filter.h', + 'browser/renderer_host/pepper_tcp_socket.cc', + 'browser/renderer_host/pepper_tcp_socket.h', + 'browser/renderer_host/pepper_udp_socket.cc', + 'browser/renderer_host/pepper_udp_socket.h', 'browser/renderer_host/quota_dispatcher_host.cc', 'browser/renderer_host/quota_dispatcher_host.h', 'browser/renderer_host/native_web_keyboard_event_aura.cc', |