// Copyright 2015 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 PPAPI_PROXY_UDP_SOCKET_FILTER_H_ #define PPAPI_PROXY_UDP_SOCKET_FILTER_H_ #include #include #include #include #include "base/compiler_specific.h" #include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/ref_counted.h" #include "ppapi/c/ppb_udp_socket.h" #include "ppapi/c/private/ppb_net_address_private.h" #include "ppapi/proxy/plugin_resource.h" #include "ppapi/proxy/ppapi_proxy_export.h" #include "ppapi/proxy/resource_message_filter.h" #include "ppapi/shared_impl/tracked_callback.h" namespace ppapi { namespace proxy { class ResourceMessageReplyParams; // Handles receiving UDP packets on the IO thread so that when the recipient is // not on the main thread, we can post directly to the appropriate thread. class PPAPI_PROXY_EXPORT UDPSocketFilter : public ResourceMessageFilter { public: UDPSocketFilter(); // All these are called on whatever thread the plugin wants, while already // holding the ppapi::ProxyLock. The "slot_available_callback" will be invoked // whenever we detect that a slot is now available, so that the client can // take appropriate action (like informing the host we can receive another // buffer). It will always be run with the ProxyLock. void AddUDPResource(PP_Instance instance, PP_Resource resource, bool private_api, const base::Closure& slot_available_callback); void RemoveUDPResource(PP_Resource resource); // Note, the slot_available_callback that was provided to AddUDPResource may // be invoked during the RequestData call; this gives the client the // opportunity to post a message to the host immediately. int32_t RequestData(PP_Resource resource, int32_t num_bytes, char* buffer, PP_Resource* addr, const scoped_refptr& callback); // ResourceMessageFilter implementation. bool OnResourceReplyReceived(const ResourceMessageReplyParams& reply_params, const IPC::Message& nested_msg) override; PP_NetAddress_Private GetLastAddrPrivate(PP_Resource resource) const; // The maximum number of bytes that each // PpapiPluginMsg_PPBUDPSocket_PushRecvResult message is allowed to carry. static const int32_t kMaxReadSize; // The maximum number that we allow for setting // PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE. This number is only for input // argument sanity check, it doesn't mean the browser guarantees to support // such a buffer size. static const int32_t kMaxReceiveBufferSize; // The maximum number of received packets that we allow instances of this // class to buffer. static const size_t kPluginReceiveBufferSlots; private: // The queue of received data intended for 1 UDPSocketResourceBase. All usage // must be protected by UDPSocketFilter::lock_. class RecvQueue { public: explicit RecvQueue(PP_Instance instance, bool private_api, const base::Closure& slot_available_callback); ~RecvQueue(); // Called on the IO thread when data is received. It will post |callback_| // if it's valid, otherwise push the data on buffers_. // The ppapi::ProxyLock should *not* be held, and won't be acquired. void DataReceivedOnIOThread(int32_t result, const std::string& d, const PP_NetAddress_Private& addr); // Called on whatever thread the plugin chooses. Must already hold the // PpapiProxyLock. Returns a code from pp_errors.h, or a positive number. // // Note, the out-params are owned by the plugin, and if the request can't be // handled immediately, they will be written later just before the callback // is invoked. int32_t RequestData(int32_t num_bytes, char* buffer_out, PP_Resource* addr_out, const scoped_refptr& callback); PP_NetAddress_Private GetLastAddrPrivate() const; private: struct RecvBuffer { int32_t result; std::string data; PP_NetAddress_Private addr; }; std::queue recv_buffers_; PP_Instance pp_instance_; scoped_refptr recvfrom_callback_; char* read_buffer_; int32_t bytes_to_read_; PP_Resource* recvfrom_addr_resource_; PP_NetAddress_Private last_recvfrom_addr_; bool private_api_; // Callback to invoke when a UDP receive slot is available. base::Closure slot_available_callback_; }; private: // This is deleted via RefCountedThreadSafe (see ResourceMessageFilter). ~UDPSocketFilter(); void OnPluginMsgPushRecvResult(const ResourceMessageReplyParams& params, int32_t result, const std::string& data, const PP_NetAddress_Private& addr); // lock_ protects queues_. // // Lock order (if >1 acquired): // 1 ppapi::ProxyLock // \-->2 Filter lock_ mutable base::Lock lock_; base::ScopedPtrHashMap> queues_; }; } // namespace proxy } // namespace ppapi #endif // PPAPI_PROXY_UDP_SOCKET_FILTER_H_