Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(747)

Side by Side Diff: ppapi/proxy/udp_socket_resource_base.cc

Issue 869883003: Never lock the Pepper proxy lock on the IO thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix size_t vs int32_t Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ppapi/proxy/udp_socket_resource_base.h ('k') | ppapi/shared_impl/callback_tracker.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ppapi/proxy/udp_socket_resource_base.h" 5 #include "ppapi/proxy/udp_socket_resource_base.h"
6 6
7 #include <algorithm>
8 #include <cstring> 7 #include <cstring>
9 8
10 #include "base/logging.h" 9 #include "base/logging.h"
11 #include "ppapi/c/pp_bool.h" 10 #include "ppapi/c/pp_bool.h"
12 #include "ppapi/c/pp_completion_callback.h"
13 #include "ppapi/c/pp_errors.h" 11 #include "ppapi/c/pp_errors.h"
14 #include "ppapi/proxy/error_conversion.h" 12 #include "ppapi/proxy/error_conversion.h"
15 #include "ppapi/proxy/plugin_globals.h" 13 #include "ppapi/proxy/plugin_globals.h"
16 #include "ppapi/proxy/ppapi_messages.h" 14 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/shared_impl/socket_option_data.h" 15 #include "ppapi/shared_impl/socket_option_data.h"
18 #include "ppapi/thunk/enter.h" 16 #include "ppapi/thunk/enter.h"
19 #include "ppapi/thunk/resource_creation_api.h"
20 17
21 namespace ppapi { 18 namespace ppapi {
22 namespace proxy { 19 namespace proxy {
23 20
24 const int32_t UDPSocketResourceBase::kMaxReadSize = 128 * 1024;
25 const int32_t UDPSocketResourceBase::kMaxWriteSize = 128 * 1024; 21 const int32_t UDPSocketResourceBase::kMaxWriteSize = 128 * 1024;
26 const int32_t UDPSocketResourceBase::kMaxSendBufferSize = 22 const int32_t UDPSocketResourceBase::kMaxSendBufferSize =
27 1024 * UDPSocketResourceBase::kMaxWriteSize; 23 1024 * UDPSocketResourceBase::kMaxWriteSize;
28 const int32_t UDPSocketResourceBase::kMaxReceiveBufferSize =
29 1024 * UDPSocketResourceBase::kMaxReadSize;
30 const size_t UDPSocketResourceBase::kPluginReceiveBufferSlots = 32u;
31 const size_t UDPSocketResourceBase::kPluginSendBufferSlots = 8u; 24 const size_t UDPSocketResourceBase::kPluginSendBufferSlots = 8u;
32 25
26 namespace {
27
28 void RunCallback(scoped_refptr<TrackedCallback> callback,
29 int32_t pp_result,
30 bool private_api) {
31 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result, private_api));
32 }
33
34 void PostAbortIfNecessary(const scoped_refptr<TrackedCallback>& callback) {
35 if (TrackedCallback::IsPending(callback))
36 callback->PostAbort();
37 }
38
39 } // namespace
40
33 UDPSocketResourceBase::UDPSocketResourceBase(Connection connection, 41 UDPSocketResourceBase::UDPSocketResourceBase(Connection connection,
34 PP_Instance instance, 42 PP_Instance instance,
35 bool private_api) 43 bool private_api)
36 : PluginResource(connection, instance), 44 : PluginResource(connection, instance),
37 private_api_(private_api), 45 private_api_(private_api),
38 bind_called_(false), 46 bind_called_(false),
39 bound_(false), 47 bound_(false),
40 closed_(false), 48 closed_(false),
41 read_buffer_(NULL), 49 recv_filter_(PluginGlobals::Get()->udp_socket_filter()),
42 bytes_to_read_(-1), 50 bound_addr_() {
43 recvfrom_addr_resource_(NULL) { 51 recv_filter_->AddUDPResource(
44 recvfrom_addr_.size = 0; 52 pp_instance(), pp_resource(), private_api,
45 memset(recvfrom_addr_.data, 0, 53 base::Bind(&UDPSocketResourceBase::SlotBecameAvailable, pp_resource()));
46 arraysize(recvfrom_addr_.data) * sizeof(*recvfrom_addr_.data));
47 bound_addr_.size = 0;
48 memset(bound_addr_.data, 0,
49 arraysize(bound_addr_.data) * sizeof(*bound_addr_.data));
50
51 if (private_api) 54 if (private_api)
52 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_CreatePrivate()); 55 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_CreatePrivate());
53 else 56 else
54 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_Create()); 57 SendCreate(BROWSER, PpapiHostMsg_UDPSocket_Create());
55
56 PluginGlobals::Get()->resource_reply_thread_registrar()->HandleOnIOThread(
57 PpapiPluginMsg_UDPSocket_PushRecvResult::ID);
58 } 58 }
59 59
60 UDPSocketResourceBase::~UDPSocketResourceBase() { 60 UDPSocketResourceBase::~UDPSocketResourceBase() {
61 CloseImpl();
61 } 62 }
62 63
63 int32_t UDPSocketResourceBase::SetOptionImpl( 64 int32_t UDPSocketResourceBase::SetOptionImpl(
64 PP_UDPSocket_Option name, 65 PP_UDPSocket_Option name,
65 const PP_Var& value, 66 const PP_Var& value,
66 bool check_bind_state, 67 bool check_bind_state,
67 scoped_refptr<TrackedCallback> callback) { 68 scoped_refptr<TrackedCallback> callback) {
68 if (closed_) 69 if (closed_)
69 return PP_ERROR_FAILED; 70 return PP_ERROR_FAILED;
70 71
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 PP_Bool UDPSocketResourceBase::GetBoundAddressImpl( 159 PP_Bool UDPSocketResourceBase::GetBoundAddressImpl(
159 PP_NetAddress_Private* addr) { 160 PP_NetAddress_Private* addr) {
160 if (!addr || !bound_ || closed_) 161 if (!addr || !bound_ || closed_)
161 return PP_FALSE; 162 return PP_FALSE;
162 163
163 *addr = bound_addr_; 164 *addr = bound_addr_;
164 return PP_TRUE; 165 return PP_TRUE;
165 } 166 }
166 167
167 int32_t UDPSocketResourceBase::RecvFromImpl( 168 int32_t UDPSocketResourceBase::RecvFromImpl(
168 char* buffer, 169 char* buffer_out,
169 int32_t num_bytes, 170 int32_t num_bytes,
170 PP_Resource* addr, 171 PP_Resource* addr,
171 scoped_refptr<TrackedCallback> callback) { 172 scoped_refptr<TrackedCallback> callback) {
172 if (!buffer || num_bytes <= 0)
173 return PP_ERROR_BADARGUMENT;
174 if (!bound_) 173 if (!bound_)
175 return PP_ERROR_FAILED; 174 return PP_ERROR_FAILED;
176 if (TrackedCallback::IsPending(recvfrom_callback_)) 175 return recv_filter_->RequestData(pp_resource(), num_bytes, buffer_out, addr,
177 return PP_ERROR_INPROGRESS; 176 callback);
178
179 if (recv_buffers_.empty()) {
180 read_buffer_ = buffer;
181 bytes_to_read_ = std::min(num_bytes, kMaxReadSize);
182 recvfrom_addr_resource_ = addr;
183 recvfrom_callback_ = callback;
184
185 return PP_OK_COMPLETIONPENDING;
186 } else {
187 RecvBuffer& front = recv_buffers_.front();
188
189 if (num_bytes < static_cast<int32_t>(front.data.size()))
190 return PP_ERROR_MESSAGE_TOO_BIG;
191
192 int32_t result = SetRecvFromOutput(front.result, front.data, front.addr,
193 buffer, num_bytes, addr);
194
195 recv_buffers_.pop();
196 Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
197
198 return result;
199 }
200 } 177 }
201 178
202 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl( 179 PP_Bool UDPSocketResourceBase::GetRecvFromAddressImpl(
203 PP_NetAddress_Private* addr) { 180 PP_NetAddress_Private* addr) {
204 if (!addr) 181 if (!addr)
205 return PP_FALSE; 182 return PP_FALSE;
206 *addr = recvfrom_addr_; 183 *addr = recv_filter_->GetLastAddrPrivate(pp_resource());
207 return PP_TRUE; 184 return PP_TRUE;
208 } 185 }
209 186
210 int32_t UDPSocketResourceBase::SendToImpl( 187 int32_t UDPSocketResourceBase::SendToImpl(
211 const char* buffer, 188 const char* buffer,
212 int32_t num_bytes, 189 int32_t num_bytes,
213 const PP_NetAddress_Private* addr, 190 const PP_NetAddress_Private* addr,
214 scoped_refptr<TrackedCallback> callback) { 191 scoped_refptr<TrackedCallback> callback) {
215 if (!buffer || num_bytes <= 0 || !addr) 192 if (!buffer || num_bytes <= 0 || !addr)
216 return PP_ERROR_BADARGUMENT; 193 return PP_ERROR_BADARGUMENT;
(...skipping 19 matching lines...) Expand all
236 213
237 void UDPSocketResourceBase::CloseImpl() { 214 void UDPSocketResourceBase::CloseImpl() {
238 if(closed_) 215 if(closed_)
239 return; 216 return;
240 217
241 bound_ = false; 218 bound_ = false;
242 closed_ = true; 219 closed_ = true;
243 220
244 Post(BROWSER, PpapiHostMsg_UDPSocket_Close()); 221 Post(BROWSER, PpapiHostMsg_UDPSocket_Close());
245 222
246 PostAbortIfNecessary(&bind_callback_); 223 PostAbortIfNecessary(bind_callback_);
247 PostAbortIfNecessary(&recvfrom_callback_);
248 while (!sendto_callbacks_.empty()) { 224 while (!sendto_callbacks_.empty()) {
249 scoped_refptr<TrackedCallback> callback = sendto_callbacks_.front(); 225 scoped_refptr<TrackedCallback> callback = sendto_callbacks_.front();
250 sendto_callbacks_.pop(); 226 sendto_callbacks_.pop();
251 PostAbortIfNecessary(&callback); 227 PostAbortIfNecessary(callback);
252 } 228 }
253 229 recv_filter_->RemoveUDPResource(pp_resource());
254 read_buffer_ = NULL;
255 bytes_to_read_ = -1;
256 } 230 }
257 231
258 int32_t UDPSocketResourceBase::JoinGroupImpl( 232 int32_t UDPSocketResourceBase::JoinGroupImpl(
259 const PP_NetAddress_Private *group, 233 const PP_NetAddress_Private *group,
260 scoped_refptr<TrackedCallback> callback) { 234 scoped_refptr<TrackedCallback> callback) {
261 DCHECK(group); 235 DCHECK(group);
262 236
263 Call<PpapiPluginMsg_UDPSocket_JoinGroupReply>( 237 Call<PpapiPluginMsg_UDPSocket_JoinGroupReply>(
264 BROWSER, 238 BROWSER,
265 PpapiHostMsg_UDPSocket_JoinGroup(*group), 239 PpapiHostMsg_UDPSocket_JoinGroup(*group),
(...skipping 12 matching lines...) Expand all
278 Call<PpapiPluginMsg_UDPSocket_LeaveGroupReply>( 252 Call<PpapiPluginMsg_UDPSocket_LeaveGroupReply>(
279 BROWSER, 253 BROWSER,
280 PpapiHostMsg_UDPSocket_LeaveGroup(*group), 254 PpapiHostMsg_UDPSocket_LeaveGroup(*group),
281 base::Bind(&UDPSocketResourceBase::OnPluginMsgGeneralReply, 255 base::Bind(&UDPSocketResourceBase::OnPluginMsgGeneralReply,
282 base::Unretained(this), 256 base::Unretained(this),
283 callback), 257 callback),
284 callback); 258 callback);
285 return PP_OK_COMPLETIONPENDING; 259 return PP_OK_COMPLETIONPENDING;
286 } 260 }
287 261
288 void UDPSocketResourceBase::OnReplyReceived(
289 const ResourceMessageReplyParams& params,
290 const IPC::Message& msg) {
291 PPAPI_BEGIN_MESSAGE_MAP(UDPSocketResourceBase, msg)
292 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
293 PpapiPluginMsg_UDPSocket_PushRecvResult,
294 OnPluginMsgPushRecvResult)
295 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(
296 PluginResource::OnReplyReceived(params, msg))
297 PPAPI_END_MESSAGE_MAP()
298 }
299
300 void UDPSocketResourceBase::PostAbortIfNecessary(
301 scoped_refptr<TrackedCallback>* callback) {
302 if (TrackedCallback::IsPending(*callback))
303 (*callback)->PostAbort();
304 }
305
306 void UDPSocketResourceBase::OnPluginMsgGeneralReply( 262 void UDPSocketResourceBase::OnPluginMsgGeneralReply(
307 scoped_refptr<TrackedCallback> callback, 263 scoped_refptr<TrackedCallback> callback,
308 const ResourceMessageReplyParams& params) { 264 const ResourceMessageReplyParams& params) {
309 if (TrackedCallback::IsPending(callback)) 265 if (TrackedCallback::IsPending(callback))
310 RunCallback(callback, params.result()); 266 RunCallback(callback, params.result(), private_api_);
311 } 267 }
312 268
313 void UDPSocketResourceBase::OnPluginMsgBindReply( 269 void UDPSocketResourceBase::OnPluginMsgBindReply(
314 const ResourceMessageReplyParams& params, 270 const ResourceMessageReplyParams& params,
315 const PP_NetAddress_Private& bound_addr) { 271 const PP_NetAddress_Private& bound_addr) {
316 // It is possible that |bind_callback_| is pending while |closed_| is true: 272 // It is possible that |bind_callback_| is pending while |closed_| is true:
317 // CloseImpl() has been called, but a BindReply came earlier than the task to 273 // CloseImpl() has been called, but a BindReply came earlier than the task to
318 // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_| 274 // abort |bind_callback_|. We don't want to update |bound_| or |bound_addr_|
319 // in that case. 275 // in that case.
320 if (!TrackedCallback::IsPending(bind_callback_) || closed_) 276 if (!TrackedCallback::IsPending(bind_callback_) || closed_)
321 return; 277 return;
322 278
323 if (params.result() == PP_OK) 279 if (params.result() == PP_OK)
324 bound_ = true; 280 bound_ = true;
325 bound_addr_ = bound_addr; 281 bound_addr_ = bound_addr;
326 RunCallback(bind_callback_, params.result()); 282 RunCallback(bind_callback_, params.result(), private_api_);
327 }
328
329 void UDPSocketResourceBase::OnPluginMsgPushRecvResult(
330 const ResourceMessageReplyParams& params,
331 int32_t result,
332 const std::string& data,
333 const PP_NetAddress_Private& addr) {
334 // TODO(yzshen): Support passing in a non-const string ref, so that we can
335 // eliminate one copy when storing the data in the buffer.
336
337 DCHECK_LT(recv_buffers_.size(), kPluginReceiveBufferSlots);
338
339 if (!TrackedCallback::IsPending(recvfrom_callback_) || !read_buffer_) {
340 recv_buffers_.push(RecvBuffer());
341 RecvBuffer& back = recv_buffers_.back();
342 back.result = result;
343 back.data = data;
344 back.addr = addr;
345
346 return;
347 }
348
349 DCHECK_EQ(recv_buffers_.size(), 0u);
350
351 if (bytes_to_read_ < static_cast<int32_t>(data.size())) {
352 recv_buffers_.push(RecvBuffer());
353 RecvBuffer& back = recv_buffers_.back();
354 back.result = result;
355 back.data = data;
356 back.addr = addr;
357
358 result = PP_ERROR_MESSAGE_TOO_BIG;
359 } else {
360 result = SetRecvFromOutput(result, data, addr, read_buffer_, bytes_to_read_,
361 recvfrom_addr_resource_);
362 Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
363 }
364
365 read_buffer_ = NULL;
366 bytes_to_read_ = -1;
367 recvfrom_addr_resource_ = NULL;
368
369 RunCallback(recvfrom_callback_, result);
370 } 283 }
371 284
372 void UDPSocketResourceBase::OnPluginMsgSendToReply( 285 void UDPSocketResourceBase::OnPluginMsgSendToReply(
373 const ResourceMessageReplyParams& params, 286 const ResourceMessageReplyParams& params,
374 int32_t bytes_written) { 287 int32_t bytes_written) {
375 // This can be empty if the socket was closed, but there are still tasks 288 // This can be empty if the socket was closed, but there are still tasks
376 // to be posted for this resource. 289 // to be posted for this resource.
377 if (sendto_callbacks_.empty()) 290 if (sendto_callbacks_.empty())
378 return; 291 return;
379 292
380 scoped_refptr<TrackedCallback> callback = sendto_callbacks_.front(); 293 scoped_refptr<TrackedCallback> callback = sendto_callbacks_.front();
381 sendto_callbacks_.pop(); 294 sendto_callbacks_.pop();
382 if (!TrackedCallback::IsPending(callback)) 295 if (!TrackedCallback::IsPending(callback))
383 return; 296 return;
384 297
385 if (params.result() == PP_OK) 298 if (params.result() == PP_OK)
386 RunCallback(callback, bytes_written); 299 RunCallback(callback, bytes_written, private_api_);
387 else 300 else
388 RunCallback(callback, params.result()); 301 RunCallback(callback, params.result(), private_api_);
389 } 302 }
390 303
391 void UDPSocketResourceBase::RunCallback(scoped_refptr<TrackedCallback> callback, 304 // static
392 int32_t pp_result) { 305 void UDPSocketResourceBase::SlotBecameAvailable(PP_Resource resource) {
393 callback->Run(ConvertNetworkAPIErrorForCompatibility(pp_result, 306 ProxyLock::AssertAcquired();
394 private_api_)); 307 thunk::EnterResourceNoLock<thunk::PPB_UDPSocket_API> enter(resource, false);
395 } 308 if (enter.failed())
309 return;
310 auto thiz(static_cast<UDPSocketResourceBase*>(enter.resource()));
396 311
397 int32_t UDPSocketResourceBase::SetRecvFromOutput( 312 if (!thiz->closed_)
398 int32_t browser_result, 313 thiz->Post(BROWSER, PpapiHostMsg_UDPSocket_RecvSlotAvailable());
399 const std::string& data,
400 const PP_NetAddress_Private& addr,
401 char* output_buffer,
402 int32_t num_bytes,
403 PP_Resource* output_addr) {
404 DCHECK_GE(num_bytes, static_cast<int32_t>(data.size()));
405
406 int32_t result = browser_result;
407 if (result == PP_OK && output_addr) {
408 thunk::EnterResourceCreationNoLock enter(pp_instance());
409 if (enter.succeeded()) {
410 *output_addr = enter.functions()->CreateNetAddressFromNetAddressPrivate(
411 pp_instance(), addr);
412 } else {
413 result = PP_ERROR_FAILED;
414 }
415 }
416
417 if (result == PP_OK && !data.empty())
418 memcpy(output_buffer, data.c_str(), data.size());
419
420 recvfrom_addr_ = addr;
421
422 return result == PP_OK ? static_cast<int32_t>(data.size()) : result;
423 } 314 }
424 315
425 } // namespace proxy 316 } // namespace proxy
426 } // namespace ppapi 317 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/udp_socket_resource_base.h ('k') | ppapi/shared_impl/callback_tracker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698