cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / ppapi / proxy / udp_socket_resource_base.cc
blob8ef3835fecabb378ce916533fcbd3f1db5561073
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/udp_socket_resource_base.h"
7 #include <algorithm>
8 #include <cstring>
10 #include "base/logging.h"
11 #include "ppapi/c/pp_bool.h"
12 #include "ppapi/c/pp_completion_callback.h"
13 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/proxy/error_conversion.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/shared_impl/socket_option_data.h"
17 #include "ppapi/thunk/enter.h"
18 #include "ppapi/thunk/resource_creation_api.h"
20 namespace ppapi {
21 namespace proxy {
23 const int32_t UDPSocketResourceBase::kMaxReadSize = 1024 * 1024;
24 const int32_t UDPSocketResourceBase::kMaxWriteSize = 1024 * 1024;
25 const int32_t UDPSocketResourceBase::kMaxSendBufferSize =
26 1024 * UDPSocketResourceBase::kMaxWriteSize;
27 const int32_t UDPSocketResourceBase::kMaxReceiveBufferSize =
28 1024 * UDPSocketResourceBase::kMaxReadSize;
31 UDPSocketResourceBase::UDPSocketResourceBase(Connection connection,
32 PP_Instance instance,
33 bool private_api)
34 : PluginResource(connection, instance),
35 private_api_(private_api),
36 bound_(false),
37 closed_(false),
38 read_buffer_(NULL),
39 bytes_to_read_(-1) {
40 recvfrom_addr_.size = 0;
41 memset(recvfrom_addr_.data, 0,
42 arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data));
43 bound_addr_.size = 0;
44 memset(bound_addr_.data, 0,
45 arraysize(bound_addr_.data) * sizeof(*bound_addr_.data));
47 if (private_api)
48 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_CreatePrivate());
49 else
50 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_Create());
53 UDPSocketResourceBase::~UDPSocketResourceBase() {
56 int32_t UDPSocketResourceBase::SetOptionImpl(
57 PP_UDPSocket_Option name,
58 const PP_Var& value,
59 scoped_refptr<TrackedCallback> callback) {
60 if (closed_)
61 return PP_ERROR_FAILED;
63 SocketOptionData option_data;
64 switch (name) {
65 case PP_UDPSOCKET_OPTION_ADDRESS_REUSE:
66 case PP_UDPSOCKET_OPTION_BROADCAST: {
67 if (bound_)
68 return PP_ERROR_FAILED;
69 if (value.type != PP_VARTYPE_BOOL)
70 return PP_ERROR_BADARGUMENT;
71 option_data.SetBool(PP_ToBool(value.value.as_bool));
72 break;
74 case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE:
75 case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: {
76 if (!bound_)
77 return PP_ERROR_FAILED;
78 if (value.type != PP_VARTYPE_INT32)
79 return PP_ERROR_BADARGUMENT;
80 option_data.SetInt32(value.value.as_int);
81 break;
83 default: {
84 NOTREACHED();
85 return PP_ERROR_BADARGUMENT;
89 Call<PpapiPluginMsg_UDPSocket_SetOptionReply>(
90 BROWSER,
91 PpapiHostMsg_UDPSocket_SetOption(name, option_data),
92 base::Bind(&UDPSocketResourceBase::OnPluginMsgSetOptionReply,
93 base::Unretained(this),
94 callback));
95 return PP_OK_COMPLETIONPENDING;
98 int32_t UDPSocketResourceBase::BindImpl(
99 const PP_NetAddress_Private* addr,
100 scoped_refptr<TrackedCallback> callback) {
101 if (!addr)
102 return PP_ERROR_BADARGUMENT;
103 if (bound_ || closed_)
104 return PP_ERROR_FAILED;
105 if (TrackedCallback::IsPending(bind_callback_))
106 return PP_ERROR_INPROGRESS;
108 bind_callback_ = callback;
110 // Send the request, the browser will call us back via BindReply.
111 Call<PpapiPluginMsg_UDPSocket_BindReply>(
112 BROWSER,
113 PpapiHostMsg_UDPSocket_Bind(*addr),
114 base::Bind(&UDPSocketResourceBase::OnPluginMsgBindReply,
115 base::Unretained(this)));
116 return PP_OK_COMPLETIONPENDING;
119 PP_Bool UDPSocketResourceBase::GetBoundAddressImpl(
120 PP_NetAddress_Private* addr) {
121 if (!addr || !bound_ || closed_)
122 return PP_FALSE;
124 *addr = bound_addr_;
125 return PP_TRUE;
128 int32_t UDPSocketResourceBase::RecvFromImpl(
129 char* buffer,
130 int32_t num_bytes,
131 PP_Resource* addr,
132 scoped_refptr<TrackedCallback> callback) {
133 if (!buffer || num_bytes <= 0)
134 return PP_ERROR_BADARGUMENT;
135 if (!bound_)
136 return PP_ERROR_FAILED;
137 if (TrackedCallback::IsPending(recvfrom_callback_))
138 return PP_ERROR_INPROGRESS;
140 read_buffer_ = buffer;
141 bytes_to_read_ = std::min(num_bytes, kMaxReadSize);
142 recvfrom_callback_ = callback;
144 // Send the request, the browser will call us back via RecvFromReply.
145 Call<PpapiPluginMsg_UDPSocket_RecvFromReply>(
146 BROWSER,
147 PpapiHostMsg_UDPSocket_RecvFrom(bytes_to_read_),
148 base::Bind(&UDPSocketResourceBase::OnPluginMsgRecvFromReply,
149 base::Unretained(this), addr));
150 return PP_OK_COMPLETIONPENDING;
153 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl(
154 PP_NetAddress_Private* addr) {
155 if (!addr)
156 return PP_FALSE;
157 *addr = recvfrom_addr_;
158 return PP_TRUE;
161 int32_t UDPSocketResourceBase::SendToImpl(
162 const char* buffer,
163 int32_t num_bytes,
164 const PP_NetAddress_Private* addr,
165 scoped_refptr<TrackedCallback> callback) {
166 if (!buffer || num_bytes <= 0 || !addr)
167 return PP_ERROR_BADARGUMENT;
168 if (!bound_)
169 return PP_ERROR_FAILED;
170 if (TrackedCallback::IsPending(sendto_callback_))
171 return PP_ERROR_INPROGRESS;
173 if (num_bytes > kMaxWriteSize)
174 num_bytes = kMaxWriteSize;
176 sendto_callback_ = callback;
178 // Send the request, the browser will call us back via SendToReply.
179 Call<PpapiPluginMsg_UDPSocket_SendToReply>(
180 BROWSER,
181 PpapiHostMsg_UDPSocket_SendTo(std::string(buffer, num_bytes), *addr),
182 base::Bind(&UDPSocketResourceBase::OnPluginMsgSendToReply,
183 base::Unretained(this)));
184 return PP_OK_COMPLETIONPENDING;
187 void UDPSocketResourceBase::CloseImpl() {
188 if(closed_)
189 return;
191 bound_ = false;
192 closed_ = true;
194 Post(BROWSER, PpapiHostMsg_UDPSocket_Close());
196 PostAbortIfNecessary(&bind_callback_);
197 PostAbortIfNecessary(&recvfrom_callback_);
198 PostAbortIfNecessary(&sendto_callback_);
200 read_buffer_ = NULL;
201 bytes_to_read_ = -1;
204 void UDPSocketResourceBase::PostAbortIfNecessary(
205 scoped_refptr<TrackedCallback>* callback) {
206 if (TrackedCallback::IsPending(*callback))
207 (*callback)->PostAbort();
210 void UDPSocketResourceBase::OnPluginMsgSetOptionReply(
211 scoped_refptr<TrackedCallback> callback,
212 const ResourceMessageReplyParams& params) {
213 if (TrackedCallback::IsPending(callback))
214 RunCallback(callback, params.result());
217 void UDPSocketResourceBase::OnPluginMsgBindReply(
218 const ResourceMessageReplyParams& params,
219 const PP_NetAddress_Private& bound_addr) {
220 // It is possible that |bind_callback_| is pending while |closed_| is true:
221 // CloseImpl() has been called, but a BindReply came earlier than the task to
222 // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_|
223 // in that case.
224 if (!TrackedCallback::IsPending(bind_callback_) || closed_)
225 return;
227 if (params.result() == PP_OK)
228 bound_ = true;
229 bound_addr_ = bound_addr;
230 RunCallback(bind_callback_, params.result());
233 void UDPSocketResourceBase::OnPluginMsgRecvFromReply(
234 PP_Resource* output_addr,
235 const ResourceMessageReplyParams& params,
236 const std::string& data,
237 const PP_NetAddress_Private& addr) {
238 // It is possible that |recvfrom_callback_| is pending while |read_buffer_| is
239 // NULL: CloseImpl() has been called, but a RecvFromReply came earlier than
240 // the task to abort |recvfrom_callback_|. We shouldn't access the buffer in
241 // that case. The user may have released it.
242 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_)
243 return;
245 int32_t result = params.result();
246 if (result == PP_OK && output_addr) {
247 thunk::EnterResourceCreationNoLock enter(pp_instance());
248 if (enter.succeeded()) {
249 *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate(
250 pp_instance(), addr);
251 } else {
252 result = PP_ERROR_FAILED;
256 if (result == PP_OK) {
257 CHECK_LE(static_cast<int32_t>(data.size()), bytes_to_read_);
258 if (!data.empty())
259 memcpy(read_buffer_, data.c_str(), data.size());
262 read_buffer_ = NULL;
263 bytes_to_read_ = -1;
264 recvfrom_addr_ = addr;
266 if (result == PP_OK)
267 RunCallback(recvfrom_callback_, static_cast<int32_t>(data.size()));
268 else
269 RunCallback(recvfrom_callback_, result);
272 void UDPSocketResourceBase::OnPluginMsgSendToReply(
273 const ResourceMessageReplyParams& params,
274 int32_t bytes_written) {
275 if (!TrackedCallback::IsPending(sendto_callback_))
276 return;
278 if (params.result() == PP_OK)
279 RunCallback(sendto_callback_, bytes_written);
280 else
281 RunCallback(sendto_callback_, params.result());
284 void UDPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback,
285 int32_t pp_result) {
286 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result,
287 private_api_));
290 } // namespace proxy
291 } // namespace ppapi