1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
// Copyright 2015 The Chromium Authors
// 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 <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <unordered_map>
#include "base/compiler_specific.h"
#include "base/containers/queue.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,
base::RepeatingClosure 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<TrackedCallback>& 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,
base::RepeatingClosure 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<TrackedCallback>& callback);
PP_NetAddress_Private GetLastAddrPrivate() const;
private:
struct RecvBuffer {
int32_t result;
std::string data;
PP_NetAddress_Private addr;
};
base::queue<RecvBuffer> recv_buffers_;
PP_Instance pp_instance_;
scoped_refptr<ppapi::TrackedCallback> 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::RepeatingClosure 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_;
std::unordered_map<PP_Resource, std::unique_ptr<RecvQueue>> queues_;
};
} // namespace proxy
} // namespace ppapi
#endif // PPAPI_PROXY_UDP_SOCKET_FILTER_H_
|