Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter. h" | 5 #include "content/browser/renderer_host/pepper/pepper_udp_socket_message_filter. h" |
| 6 | 6 |
| 7 #include <cstring> | 7 #include <cstring> |
| 8 | 8 |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "ppapi/host/host_message_context.h" | 24 #include "ppapi/host/host_message_context.h" |
| 25 #include "ppapi/host/ppapi_host.h" | 25 #include "ppapi/host/ppapi_host.h" |
| 26 #include "ppapi/host/resource_host.h" | 26 #include "ppapi/host/resource_host.h" |
| 27 #include "ppapi/proxy/ppapi_messages.h" | 27 #include "ppapi/proxy/ppapi_messages.h" |
| 28 #include "ppapi/proxy/udp_socket_resource_base.h" | 28 #include "ppapi/proxy/udp_socket_resource_base.h" |
| 29 #include "ppapi/shared_impl/private/net_address_private_impl.h" | 29 #include "ppapi/shared_impl/private/net_address_private_impl.h" |
| 30 #include "ppapi/shared_impl/socket_option_data.h" | 30 #include "ppapi/shared_impl/socket_option_data.h" |
| 31 | 31 |
| 32 using ppapi::NetAddressPrivateImpl; | 32 using ppapi::NetAddressPrivateImpl; |
| 33 using ppapi::host::NetErrorToPepperError; | 33 using ppapi::host::NetErrorToPepperError; |
| 34 using ppapi::proxy::UDPSocketResourceBase; | |
| 34 | 35 |
| 35 namespace { | 36 namespace { |
| 36 | 37 |
| 37 size_t g_num_instances = 0; | 38 size_t g_num_instances = 0; |
| 38 | 39 |
| 39 } // namespace | 40 } // namespace |
| 40 | 41 |
| 41 namespace content { | 42 namespace content { |
| 42 | 43 |
| 44 PepperUDPSocketMessageFilter::PendingSend::PendingSend( | |
| 45 const net::IPAddressNumber& address, | |
| 46 int port, | |
| 47 const scoped_refptr<net::IOBufferWithSize>& buffer, | |
| 48 const ppapi::host::ReplyMessageContext& context) | |
| 49 : address(address), port(port), buffer(buffer), context(context) { | |
| 50 } | |
| 51 | |
| 52 PepperUDPSocketMessageFilter::PendingSend::~PendingSend() { | |
| 53 } | |
| 54 | |
| 43 PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter( | 55 PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter( |
| 44 BrowserPpapiHostImpl* host, | 56 BrowserPpapiHostImpl* host, |
| 45 PP_Instance instance, | 57 PP_Instance instance, |
| 46 bool private_api) | 58 bool private_api) |
| 47 : allow_address_reuse_(false), | 59 : allow_address_reuse_(false), |
| 48 allow_broadcast_(false), | 60 allow_broadcast_(false), |
| 49 closed_(false), | 61 closed_(false), |
| 50 remaining_recv_slots_( | 62 remaining_recv_slots_(UDPSocketResourceBase::kPluginReceiveBufferSlots), |
| 51 ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots), | 63 send_in_progress_(false), |
| 52 external_plugin_(host->external_plugin()), | 64 external_plugin_(host->external_plugin()), |
| 53 private_api_(private_api), | 65 private_api_(private_api), |
| 54 render_process_id_(0), | 66 render_process_id_(0), |
| 55 render_frame_id_(0) { | 67 render_frame_id_(0) { |
| 56 ++g_num_instances; | 68 ++g_num_instances; |
| 57 DCHECK(host); | 69 DCHECK(host); |
| 58 | 70 |
| 59 if (!host->GetRenderFrameIDsForInstance( | 71 if (!host->GetRenderFrameIDsForInstance( |
| 60 instance, &render_process_id_, &render_frame_id_)) { | 72 instance, &render_process_id_, &render_frame_id_)) { |
| 61 NOTREACHED(); | 73 NOTREACHED(); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 if (!socket_.get()) { | 148 if (!socket_.get()) { |
| 137 // They only take effect after the socket is bound. | 149 // They only take effect after the socket is bound. |
| 138 return PP_ERROR_FAILED; | 150 return PP_ERROR_FAILED; |
| 139 } | 151 } |
| 140 int32_t integer_value = 0; | 152 int32_t integer_value = 0; |
| 141 if (!value.GetInt32(&integer_value) || integer_value <= 0) | 153 if (!value.GetInt32(&integer_value) || integer_value <= 0) |
| 142 return PP_ERROR_BADARGUMENT; | 154 return PP_ERROR_BADARGUMENT; |
| 143 | 155 |
| 144 int net_result = net::ERR_UNEXPECTED; | 156 int net_result = net::ERR_UNEXPECTED; |
| 145 if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) { | 157 if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) { |
| 146 if (integer_value > | 158 if (integer_value > UDPSocketResourceBase::kMaxSendBufferSize) { |
| 147 ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) { | |
| 148 return PP_ERROR_BADARGUMENT; | 159 return PP_ERROR_BADARGUMENT; |
| 149 } | 160 } |
| 150 net_result = socket_->SetSendBufferSize(integer_value); | 161 net_result = socket_->SetSendBufferSize(integer_value); |
| 151 } else { | 162 } else { |
| 152 if (integer_value > | 163 if (integer_value > UDPSocketResourceBase::kMaxReceiveBufferSize) { |
| 153 ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) { | |
| 154 return PP_ERROR_BADARGUMENT; | 164 return PP_ERROR_BADARGUMENT; |
| 155 } | 165 } |
| 156 net_result = socket_->SetReceiveBufferSize(integer_value); | 166 net_result = socket_->SetReceiveBufferSize(integer_value); |
| 157 } | 167 } |
| 158 // TODO(wtc): Add error mapping code. | 168 // TODO(wtc): Add error mapping code. |
| 159 return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED; | 169 return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED; |
| 160 } | 170 } |
| 161 default: { | 171 default: { |
| 162 NOTREACHED(); | 172 NOTREACHED(); |
| 163 return PP_ERROR_BADARGUMENT; | 173 return PP_ERROR_BADARGUMENT; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 234 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 225 Close(); | 235 Close(); |
| 226 return PP_OK; | 236 return PP_OK; |
| 227 } | 237 } |
| 228 | 238 |
| 229 int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable( | 239 int32_t PepperUDPSocketMessageFilter::OnMsgRecvSlotAvailable( |
| 230 const ppapi::host::HostMessageContext* context) { | 240 const ppapi::host::HostMessageContext* context) { |
| 231 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 241 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 232 | 242 |
| 233 if (remaining_recv_slots_ < | 243 if (remaining_recv_slots_ < |
| 234 ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots) { | 244 UDPSocketResourceBase::kPluginReceiveBufferSlots) { |
| 235 remaining_recv_slots_++; | 245 remaining_recv_slots_++; |
| 236 } | 246 } |
| 237 | 247 |
| 238 if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) { | 248 if (!recvfrom_buffer_.get() && !closed_ && socket_.get()) { |
| 239 DCHECK_EQ(1u, remaining_recv_slots_); | 249 DCHECK_EQ(1u, remaining_recv_slots_); |
| 240 DoRecvFrom(); | 250 DoRecvFrom(); |
| 241 } | 251 } |
| 242 | 252 |
| 243 return PP_OK; | 253 return PP_OK; |
| 244 } | 254 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 DoRecvFrom(); | 307 DoRecvFrom(); |
| 298 } | 308 } |
| 299 | 309 |
| 300 void PepperUDPSocketMessageFilter::DoRecvFrom() { | 310 void PepperUDPSocketMessageFilter::DoRecvFrom() { |
| 301 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 311 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 302 DCHECK(!closed_); | 312 DCHECK(!closed_); |
| 303 DCHECK(socket_.get()); | 313 DCHECK(socket_.get()); |
| 304 DCHECK(!recvfrom_buffer_.get()); | 314 DCHECK(!recvfrom_buffer_.get()); |
| 305 DCHECK_GT(remaining_recv_slots_, 0u); | 315 DCHECK_GT(remaining_recv_slots_, 0u); |
| 306 | 316 |
| 307 recvfrom_buffer_ = new net::IOBuffer( | 317 recvfrom_buffer_ = new net::IOBuffer(UDPSocketResourceBase::kMaxReadSize); |
| 308 ppapi::proxy::UDPSocketResourceBase::kMaxReadSize); | |
| 309 | 318 |
| 310 // Use base::Unretained(this), so that the lifespan of this object doesn't | 319 // Use base::Unretained(this), so that the lifespan of this object doesn't |
| 311 // have to last until the callback is called. | 320 // have to last until the callback is called. |
| 312 // It is safe to do so because |socket_| is owned by this object. If this | 321 // It is safe to do so because |socket_| is owned by this object. If this |
| 313 // object gets destroyed (and so does |socket_|), the callback won't be | 322 // object gets destroyed (and so does |socket_|), the callback won't be |
| 314 // called. | 323 // called. |
| 315 int net_result = socket_->RecvFrom( | 324 int net_result = socket_->RecvFrom( |
| 316 recvfrom_buffer_.get(), | 325 recvfrom_buffer_.get(), |
| 317 ppapi::proxy::UDPSocketResourceBase::kMaxReadSize, | 326 UDPSocketResourceBase::kMaxReadSize, |
| 318 &recvfrom_address_, | 327 &recvfrom_address_, |
| 319 base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted, | 328 base::Bind(&PepperUDPSocketMessageFilter::OnRecvFromCompleted, |
| 320 base::Unretained(this))); | 329 base::Unretained(this))); |
| 321 if (net_result != net::ERR_IO_PENDING) | 330 if (net_result != net::ERR_IO_PENDING) |
| 322 OnRecvFromCompleted(net_result); | 331 OnRecvFromCompleted(net_result); |
| 323 } | 332 } |
| 324 | 333 |
| 325 void PepperUDPSocketMessageFilter::DoSendTo( | 334 void PepperUDPSocketMessageFilter::DoSendTo( |
| 326 const ppapi::host::ReplyMessageContext& context, | 335 const ppapi::host::ReplyMessageContext& context, |
| 327 const std::string& data, | 336 const std::string& data, |
| 328 const PP_NetAddress_Private& addr) { | 337 const PP_NetAddress_Private& addr) { |
| 329 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 338 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 330 DCHECK(socket_.get()); | 339 DCHECK(socket_.get()); |
| 331 | 340 |
| 332 if (closed_ || !socket_.get()) { | 341 if (closed_ || !socket_.get()) { |
| 333 SendSendToError(context, PP_ERROR_FAILED); | 342 SendSendToError(context, PP_ERROR_FAILED); |
| 334 return; | 343 return; |
| 335 } | 344 } |
| 336 | 345 |
| 337 if (sendto_buffer_.get()) { | |
| 338 SendSendToError(context, PP_ERROR_INPROGRESS); | |
| 339 return; | |
| 340 } | |
| 341 | |
| 342 size_t num_bytes = data.size(); | 346 size_t num_bytes = data.size(); |
| 343 if (num_bytes == 0 || | 347 if (num_bytes == 0 || |
| 344 num_bytes > static_cast<size_t>( | 348 num_bytes > static_cast<size_t>(UDPSocketResourceBase::kMaxWriteSize)) { |
| 345 ppapi::proxy::UDPSocketResourceBase::kMaxWriteSize)) { | |
| 346 // Size of |data| is checked on the plugin side. | 349 // Size of |data| is checked on the plugin side. |
| 347 NOTREACHED(); | 350 NOTREACHED(); |
| 348 SendSendToError(context, PP_ERROR_BADARGUMENT); | 351 SendSendToError(context, PP_ERROR_BADARGUMENT); |
| 349 return; | 352 return; |
| 350 } | 353 } |
| 351 | 354 |
| 352 sendto_buffer_ = new net::IOBufferWithSize(num_bytes); | |
| 353 memcpy(sendto_buffer_->data(), data.data(), num_bytes); | |
| 354 | |
| 355 net::IPAddressNumber address; | 355 net::IPAddressNumber address; |
| 356 int port; | 356 int port; |
| 357 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { | 357 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { |
| 358 SendSendToError(context, PP_ERROR_ADDRESS_INVALID); | 358 SendSendToError(context, PP_ERROR_ADDRESS_INVALID); |
| 359 return; | 359 return; |
| 360 } | 360 } |
| 361 | 361 |
| 362 // Please see OnMsgRecvFrom() for the reason why we use base::Unretained(this) | 362 scoped_refptr<net::IOBufferWithSize> buffer( |
| 363 new net::IOBufferWithSize(num_bytes)); | |
| 364 memcpy(buffer->data(), data.data(), num_bytes); | |
| 365 | |
| 366 // Make sure a malicious plugin can't queue up an unlimited number of buffers. | |
| 367 if (pending_sends_.size() == | |
| 368 UDPSocketResourceBase::kPluginSendBufferSlots) { | |
| 369 SendSendToError(context, PP_ERROR_FAILED); | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 pending_sends_.push(PendingSend(address, port, buffer, context)); | |
| 374 if (!send_in_progress_) | |
| 375 DoPendingSend(); | |
|
dmichael (off chromium)
2014/10/08 22:42:40
I think you can get rid of the if and just always
bbudge
2014/10/09 00:18:26
Done.
| |
| 376 } | |
| 377 | |
| 378 void PepperUDPSocketMessageFilter::DoPendingSend() { | |
| 379 PendingSend pending_send = pending_sends_.front(); | |
| 380 pending_sends_.pop(); | |
|
dmichael (off chromium)
2014/10/08 22:42:40
...but to do my suggestion, you'd want to not pop
bbudge
2014/10/09 00:18:26
Done.
| |
| 381 // See OnMsgRecvFrom() for the reason why we use base::Unretained(this) | |
| 363 // when calling |socket_| methods. | 382 // when calling |socket_| methods. |
| 364 int net_result = socket_->SendTo( | 383 int net_result = socket_->SendTo( |
| 365 sendto_buffer_.get(), | 384 pending_send.buffer.get(), |
| 366 sendto_buffer_->size(), | 385 pending_send.buffer->size(), |
| 367 net::IPEndPoint(address, port), | 386 net::IPEndPoint(pending_send.address, pending_send.port), |
| 368 base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted, | 387 base::Bind(&PepperUDPSocketMessageFilter::OnSendToCompleted, |
| 369 base::Unretained(this), | 388 base::Unretained(this), |
| 370 context)); | 389 pending_send.buffer, |
| 390 pending_send.context)); | |
| 371 if (net_result != net::ERR_IO_PENDING) | 391 if (net_result != net::ERR_IO_PENDING) |
| 372 OnSendToCompleted(context, net_result); | 392 OnSendToCompleted(pending_send.buffer, pending_send.context, net_result); |
| 393 else | |
| 394 send_in_progress_ = true; | |
| 373 } | 395 } |
| 374 | 396 |
| 375 void PepperUDPSocketMessageFilter::Close() { | 397 void PepperUDPSocketMessageFilter::Close() { |
| 376 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 398 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 377 if (socket_.get() && !closed_) | 399 if (socket_.get() && !closed_) |
| 378 socket_->Close(); | 400 socket_->Close(); |
| 379 closed_ = true; | 401 closed_ = true; |
| 380 } | 402 } |
| 381 | 403 |
| 382 void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) { | 404 void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 404 recvfrom_buffer_ = NULL; | 426 recvfrom_buffer_ = NULL; |
| 405 | 427 |
| 406 DCHECK_GT(remaining_recv_slots_, 0u); | 428 DCHECK_GT(remaining_recv_slots_, 0u); |
| 407 remaining_recv_slots_--; | 429 remaining_recv_slots_--; |
| 408 | 430 |
| 409 if (remaining_recv_slots_ > 0 && !closed_ && socket_.get()) | 431 if (remaining_recv_slots_ > 0 && !closed_ && socket_.get()) |
| 410 DoRecvFrom(); | 432 DoRecvFrom(); |
| 411 } | 433 } |
| 412 | 434 |
| 413 void PepperUDPSocketMessageFilter::OnSendToCompleted( | 435 void PepperUDPSocketMessageFilter::OnSendToCompleted( |
| 436 scoped_refptr<net::IOBufferWithSize> buffer, | |
|
dmichael (off chromium)
2014/10/08 22:42:40
I think you won't need this anymore because the he
bbudge
2014/10/09 00:18:26
Done.
| |
| 414 const ppapi::host::ReplyMessageContext& context, | 437 const ppapi::host::ReplyMessageContext& context, |
| 415 int net_result) { | 438 int net_result) { |
| 416 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 439 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 417 DCHECK(sendto_buffer_.get()); | |
| 418 | 440 |
| 419 int32_t pp_result = NetErrorToPepperError(net_result); | 441 int32_t pp_result = NetErrorToPepperError(net_result); |
| 420 if (pp_result < 0) | 442 if (pp_result < 0) |
| 421 SendSendToError(context, pp_result); | 443 SendSendToError(context, pp_result); |
| 422 else | 444 else |
| 423 SendSendToReply(context, PP_OK, pp_result); | 445 SendSendToReply(context, PP_OK, pp_result); |
| 424 sendto_buffer_ = NULL; | 446 |
| 447 send_in_progress_ = false; | |
| 448 | |
| 449 if (!pending_sends_.empty()) | |
| 450 DoPendingSend(); | |
|
dmichael (off chromium)
2014/10/08 22:42:40
And you'll want to pop() right before calling this
bbudge
2014/10/09 00:18:26
Done. Very nice simplification. Thanks!
| |
| 425 } | 451 } |
| 426 | 452 |
| 427 void PepperUDPSocketMessageFilter::SendBindReply( | 453 void PepperUDPSocketMessageFilter::SendBindReply( |
| 428 const ppapi::host::ReplyMessageContext& context, | 454 const ppapi::host::ReplyMessageContext& context, |
| 429 int32_t result, | 455 int32_t result, |
| 430 const PP_NetAddress_Private& addr) { | 456 const PP_NetAddress_Private& addr) { |
| 431 ppapi::host::ReplyMessageContext reply_context(context); | 457 ppapi::host::ReplyMessageContext reply_context(context); |
| 432 reply_context.params.set_result(result); | 458 reply_context.params.set_result(result); |
| 433 SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr)); | 459 SendReply(reply_context, PpapiPluginMsg_UDPSocket_BindReply(addr)); |
| 434 } | 460 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 463 NetAddressPrivateImpl::kInvalidNetAddress); | 489 NetAddressPrivateImpl::kInvalidNetAddress); |
| 464 } | 490 } |
| 465 | 491 |
| 466 void PepperUDPSocketMessageFilter::SendSendToError( | 492 void PepperUDPSocketMessageFilter::SendSendToError( |
| 467 const ppapi::host::ReplyMessageContext& context, | 493 const ppapi::host::ReplyMessageContext& context, |
| 468 int32_t result) { | 494 int32_t result) { |
| 469 SendSendToReply(context, result, 0); | 495 SendSendToReply(context, result, 0); |
| 470 } | 496 } |
| 471 | 497 |
| 472 } // namespace content | 498 } // namespace content |
| OLD | NEW |