Index: content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc |
diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc |
index dd915b85ea377e2c152c0a4329dd53c99e2f394f..8213bb4f8e9446c923a587e3767b4e18719a8617 100644 |
--- a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc |
+++ b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc |
@@ -16,7 +16,8 @@ |
#include "ipc/ipc_message_macros.h" |
#include "net/base/io_buffer.h" |
#include "net/base/net_errors.h" |
-#include "net/udp/udp_server_socket.h" |
+#include "net/base/rand_callback.h" |
+#include "net/udp/udp_socket.h" |
#include "ppapi/c/pp_errors.h" |
#include "ppapi/c/private/ppb_net_address_private.h" |
#include "ppapi/host/dispatch_host_message.h" |
@@ -44,8 +45,9 @@ PepperUDPSocketMessageFilter::PepperUDPSocketMessageFilter( |
BrowserPpapiHostImpl* host, |
PP_Instance instance, |
bool private_api) |
- : allow_address_reuse_(false), |
- allow_broadcast_(false), |
+ : socket_options_(0), |
+ rcvbuf_size_(0), |
+ sndbuf_size_(0), |
closed_(false), |
remaining_recv_slots_( |
ppapi::proxy::UDPSocketResourceBase::kPluginReceiveBufferSlots), |
@@ -114,10 +116,11 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( |
return PP_ERROR_FAILED; |
switch (name) { |
- case PP_UDPSOCKET_OPTION_ADDRESS_REUSE: |
- case PP_UDPSOCKET_OPTION_BROADCAST: { |
+ case PP_UDPSOCKET_OPTION_ADDRESS_REUSE: { |
if (socket_.get()) { |
- // They only take effect before the socket is bound. |
+ // AllowReuseAddress is only effective before Bind(). |
+ // Note that this limitation originally comes from Windows, but |
+ // PPAPI tries to provide platform independent APIs. |
return PP_ERROR_FAILED; |
} |
@@ -125,38 +128,67 @@ int32_t PepperUDPSocketMessageFilter::OnMsgSetOption( |
if (!value.GetBool(&boolean_value)) |
return PP_ERROR_BADARGUMENT; |
- if (name == PP_UDPSOCKET_OPTION_ADDRESS_REUSE) |
- allow_address_reuse_ = boolean_value; |
- else |
- allow_broadcast_ = boolean_value; |
+ if (boolean_value) { |
+ socket_options_ |= SOCKET_OPTION_ADDRESS_REUSE; |
+ } else { |
+ socket_options_ &= ~SOCKET_OPTION_ADDRESS_REUSE; |
+ } |
return PP_OK; |
} |
- case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: |
- case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: { |
- if (!socket_.get()) { |
- // They only take effect after the socket is bound. |
- return PP_ERROR_FAILED; |
+ case PP_UDPSOCKET_OPTION_BROADCAST: { |
+ bool boolean_value = false; |
+ if (!value.GetBool(&boolean_value)) |
+ return PP_ERROR_BADARGUMENT; |
+ |
+ // If the socket is already connected, proxy the value to TCPSocket. |
+ if (socket_.get()) |
+ return NetErrorToPepperError(socket_->SetBroadcast(boolean_value)); |
+ |
+ // UDPSocket instance is not yet created, so remember the value here. |
+ if (boolean_value) { |
+ socket_options_ |= SOCKET_OPTION_BROADCAST; |
+ } else { |
+ socket_options_ &= ~SOCKET_OPTION_BROADCAST; |
} |
+ return PP_OK; |
+ } |
+ case PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE: { |
int32_t integer_value = 0; |
- if (!value.GetInt32(&integer_value) || integer_value <= 0) |
+ if (!value.GetInt32(&integer_value) || |
+ integer_value <= 0 || |
+ integer_value > |
+ ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) |
return PP_ERROR_BADARGUMENT; |
- int net_result = net::ERR_UNEXPECTED; |
- if (name == PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE) { |
- if (integer_value > |
- ppapi::proxy::UDPSocketResourceBase::kMaxSendBufferSize) { |
- return PP_ERROR_BADARGUMENT; |
- } |
- net_result = socket_->SetSendBufferSize(integer_value); |
- } else { |
- if (integer_value > |
- ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) { |
- return PP_ERROR_BADARGUMENT; |
- } |
- net_result = socket_->SetReceiveBufferSize(integer_value); |
+ // If the socket is already connected, proxy the value to UDPSocket. |
+ if (socket_.get()) { |
+ return NetErrorToPepperError( |
+ socket_->SetSendBufferSize(integer_value)); |
} |
- // TODO(wtc): Add error mapping code. |
- return (net_result == net::OK) ? PP_OK : PP_ERROR_FAILED; |
+ |
+ // UDPSocket instance is not yet created, so remember the value here. |
+ socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE; |
+ sndbuf_size_ = integer_value; |
+ return PP_OK; |
+ } |
+ case PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE: { |
+ int32_t integer_value = 0; |
+ if (!value.GetInt32(&integer_value) || |
+ integer_value <= 0 || |
+ integer_value > |
+ ppapi::proxy::UDPSocketResourceBase::kMaxReceiveBufferSize) |
+ return PP_ERROR_BADARGUMENT; |
+ |
+ // If the socket is already connected, proxy the value to UDPSocket. |
+ if (socket_.get()) { |
+ return NetErrorToPepperError( |
+ socket_->SetReceiveBufferSize(integer_value)); |
+ } |
+ |
+ // UDPSocket instance is not yet created, so remember the value here. |
+ socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE; |
+ rcvbuf_size_ = integer_value; |
+ return PP_OK; |
} |
default: { |
NOTREACHED(); |
@@ -253,8 +285,9 @@ void PepperUDPSocketMessageFilter::DoBind( |
return; |
} |
- scoped_ptr<net::UDPServerSocket> socket( |
- new net::UDPServerSocket(NULL, net::NetLog::Source())); |
+ scoped_ptr<net::UDPSocket> socket(new net::UDPSocket( |
+ net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), |
+ NULL, net::NetLog::Source())); |
net::IPAddressNumber address; |
uint16 port; |
@@ -262,24 +295,59 @@ void PepperUDPSocketMessageFilter::DoBind( |
SendBindError(context, PP_ERROR_ADDRESS_INVALID); |
return; |
} |
+ net::IPEndPoint end_point(address, port); |
+ { |
+ int net_result = socket->Open(end_point.GetFamily()); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
+ } |
- if (allow_address_reuse_) |
- socket->AllowAddressReuse(); |
- if (allow_broadcast_) |
- socket->AllowBroadcast(); |
+ if (socket_options_ & SOCKET_OPTION_ADDRESS_REUSE) { |
+ int net_result = socket->AllowAddressReuse(); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
+ } |
+ if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
+ int net_result = socket->SetBroadcast(true); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
+ } |
+ if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE) { |
+ int net_result = socket->SetSendBufferSize(sndbuf_size_); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
+ } |
+ if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) { |
+ int net_result = socket->SetReceiveBufferSize(rcvbuf_size_); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
+ } |
- int32_t pp_result = |
- NetErrorToPepperError(socket->Listen(net::IPEndPoint(address, port))); |
- if (pp_result != PP_OK) { |
- SendBindError(context, pp_result); |
- return; |
+ { |
+ int net_result = socket->Bind(end_point); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
} |
net::IPEndPoint bound_address; |
- pp_result = NetErrorToPepperError(socket->GetLocalAddress(&bound_address)); |
- if (pp_result != PP_OK) { |
- SendBindError(context, pp_result); |
- return; |
+ { |
+ int net_result = socket->GetLocalAddress(&bound_address); |
+ if (net_result != net::OK) { |
+ SendBindError(context, NetErrorToPepperError(net_result)); |
+ return; |
+ } |
} |
PP_NetAddress_Private net_address = NetAddressPrivateImpl::kInvalidNetAddress; |
@@ -289,8 +357,6 @@ void PepperUDPSocketMessageFilter::DoBind( |
return; |
} |
- allow_address_reuse_ = false; |
- allow_broadcast_ = false; |
socket_.swap(socket); |
SendBindReply(context, PP_OK, net_address); |