Index: net/udp/udp_socket_win.cc |
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc |
index b18aa0a53693403d727acee938022bb7b7012239..35885a82c8fbeaad39c98d073c247e3643c8848f 100644 |
--- a/net/udp/udp_socket_win.cc |
+++ b/net/udp/udp_socket_win.cc |
@@ -484,59 +484,70 @@ int UDPSocketWin::CreateSocket(int addr_family) { |
int UDPSocketWin::SetReceiveBufferSize(int32 size) { |
DCHECK(CalledOnValidThread()); |
- int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
- reinterpret_cast<const char*>(&size), sizeof(size)); |
- if (rv != 0) |
- return MapSystemError(WSAGetLastError()); |
- |
- // According to documentation, setsockopt may succeed, but we need to check |
- // the results via getsockopt to be sure it works on Windows. |
- int32 actual_size = 0; |
- int option_size = sizeof(actual_size); |
- rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
- reinterpret_cast<char*>(&actual_size), &option_size); |
- if (rv != 0) |
- return MapSystemError(WSAGetLastError()); |
- if (actual_size >= size) |
- return OK; |
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", |
- actual_size, 1000, 1000000, 50); |
- return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; |
+ if (is_connected()) { |
+ int result = SetReceiveBufferSizeInternal(size); |
+ if (result != OK) |
+ return result; |
+ } |
+ socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE; |
+ rcvbuf_size_ = size; |
+ return OK; |
} |
int UDPSocketWin::SetSendBufferSize(int32 size) { |
DCHECK(CalledOnValidThread()); |
- int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
- reinterpret_cast<const char*>(&size), sizeof(size)); |
- if (rv != 0) |
- return MapSystemError(WSAGetLastError()); |
- // According to documentation, setsockopt may succeed, but we need to check |
- // the results via getsockopt to be sure it works on Windows. |
- int32 actual_size = 0; |
- int option_size = sizeof(actual_size); |
- rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
- reinterpret_cast<char*>(&actual_size), &option_size); |
- if (rv != 0) |
- return MapSystemError(WSAGetLastError()); |
- if (actual_size >= size) |
- return OK; |
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", |
- actual_size, 1000, 1000000, 50); |
- return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; |
+ if (is_connected()) { |
+ int result = SetReceiveBufferSizeInternal(size); |
+ if (result != OK) |
+ return result; |
+ } |
+ socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE; |
+ sndbuf_size_ = size; |
+ return OK; |
} |
-void UDPSocketWin::AllowAddressReuse() { |
+int UDPSocketWin::AllowAddressReuse() { |
DCHECK(CalledOnValidThread()); |
- DCHECK(!is_connected()); |
- |
+ if (is_connected()) { |
+ int result = SetAddressReuseInternal(true); |
+ if (result != OK) |
+ return result; |
+ } |
socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
+ return OK; |
} |
-void UDPSocketWin::AllowBroadcast() { |
+int UDPSocketWin::DisallowAddressReuse() { |
DCHECK(CalledOnValidThread()); |
- DCHECK(!is_connected()); |
+ if (is_connected()) { |
+ int result = SetAddressReuseInternal(false); |
+ if (result != OK) |
+ return result; |
+ } |
+ socket_options_ &= ~SOCKET_OPTION_REUSE_ADDRESS; |
+ return OK; |
+} |
+int UDPSocketWin::AllowBroadcast() { |
+ DCHECK(CalledOnValidThread()); |
+ if (is_connected()) { |
+ int result = SetBroadcastInternal(true); |
+ if (result != OK) |
+ return result; |
+ } |
socket_options_ |= SOCKET_OPTION_BROADCAST; |
+ return OK; |
+} |
+ |
+int UDPSocketWin::DisallowBroadcast() { |
+ DCHECK(CalledOnValidThread()); |
+ if (is_connected()) { |
+ int result = SetBroadcastInternal(false); |
+ if (result != OK) |
+ return result; |
+ } |
+ socket_options_ &= ~SOCKET_OPTION_BROADCAST; |
+ return OK; |
} |
void UDPSocketWin::DoReadCallback(int rv) { |
@@ -715,20 +726,18 @@ int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, |
} |
int UDPSocketWin::SetSocketOptions() { |
- BOOL true_value = 1; |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(is_connected()); |
+ |
if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
- int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, |
- reinterpret_cast<const char*>(&true_value), |
- sizeof(true_value)); |
- if (rv < 0) |
- return MapSystemError(WSAGetLastError()); |
+ int rv = SetAddressReuseInternal(true); |
+ if (rv != OK) |
+ return rv; |
} |
if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
- int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, |
- reinterpret_cast<const char*>(&true_value), |
- sizeof(true_value)); |
- if (rv < 0) |
- return MapSystemError(WSAGetLastError()); |
+ int rv = SetBroadcastInternal(true); |
+ if (rv != OK) |
+ return rv; |
} |
if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
DWORD loop = 0; |
@@ -741,6 +750,16 @@ int UDPSocketWin::SetSocketOptions() { |
if (rv < 0) |
return MapSystemError(WSAGetLastError()); |
} |
+ if (socket_options_ & SOCKET_OPTION_RCVBUF_SIZE) { |
+ int rv = SetReceiveBufferSizeInternal(rcvbuf_size_); |
+ if (rv != OK) |
+ return rv; |
+ } |
+ if (socket_options_ & SOCKET_OPTION_SNDBUF_SIZE) { |
+ int rv = SetSendBufferSizeInternal(sndbuf_size_); |
+ if (rv != OK) |
+ return rv; |
+ } |
if (multicast_time_to_live_ != 1) { |
DWORD hops = multicast_time_to_live_; |
int protocol_level = |
@@ -781,6 +800,75 @@ int UDPSocketWin::SetSocketOptions() { |
return OK; |
} |
+int UDPSocketWin::SetAddressReuseInternal(bool address_reuse) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(is_connected()); |
+ |
+ int opt_value = address_reuse ? 1 : 0; |
+ int rv = setsockopt( |
+ socket_, SOL_SOCKET, SO_REUSEADDR, |
+ reinterpret_cast<const char*>(&opt_value), sizeof(opt_value)); |
+ return rv == 0 ? OK : MapSystemError(WSAGetLastError()); |
+} |
+ |
+int UDPSocketWin::SetBroadcastInternal(bool broadcast) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(is_connected()); |
+ |
+ int opt_value = broadcast ? 1 : 0; |
+ int rv = setsockopt( |
+ socket_, SOL_SOCKET, SO_BROADCAST, |
+ reinterpret_cast<const char*>(&opt_value), sizeof(opt_value)); |
+ return rv == 0 ? OK : MapSystemError(WSAGetLastError()); |
+} |
+ |
+int UDPSocketWin::SetReceiveBufferSizeInternal(int32 size) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(is_connected()); |
+ |
+ int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
+ reinterpret_cast<const char*>(&size), sizeof(size)); |
+ if (rv != 0) |
+ return MapSystemError(WSAGetLastError()); |
+ |
+ // According to documentation, setsockopt may succeed, but we need to check |
+ // the results via getsockopt to be sure it works on Windows. |
+ int32 actual_size = 0; |
+ int option_size = sizeof(actual_size); |
+ rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
+ reinterpret_cast<char*>(&actual_size), &option_size); |
+ if (rv != 0) |
+ return MapSystemError(WSAGetLastError()); |
+ if (actual_size >= size) |
+ return OK; |
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", |
+ actual_size, 1000, 1000000, 50); |
+ return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; |
+} |
+ |
+int UDPSocketWin::SetSendBufferSizeInternal(int32 size) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(is_connected()); |
+ |
+ int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
+ reinterpret_cast<const char*>(&size), sizeof(size)); |
+ if (rv != 0) |
+ return MapSystemError(WSAGetLastError()); |
+ // According to documentation, setsockopt may succeed, but we need to check |
+ // the results via getsockopt to be sure it works on Windows. |
+ int32 actual_size = 0; |
+ int option_size = sizeof(actual_size); |
+ rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
+ reinterpret_cast<char*>(&actual_size), &option_size); |
+ if (rv != 0) |
+ return MapSystemError(WSAGetLastError()); |
+ if (actual_size >= size) |
+ return OK; |
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", |
+ actual_size, 1000, 1000000, 50); |
+ return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; |
+} |
+ |
int UDPSocketWin::DoBind(const IPEndPoint& address) { |
SockaddrStorage storage; |
if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |