Chromium Code Reviews| 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..1383236423fb65121b84026905faf7f76976b2ec 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; |
| + } |
|
jar (doing other things)
2014/11/04 22:51:09
Note that you have changed the semantics here, as
jar (doing other things)
2014/11/05 01:18:31
<doh>... My mistake... please ignore this comment.
hidehiko
2014/11/05 12:48:30
Acknowledged.
|
| + 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 value) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(is_connected()); |
| + |
| + int opt_value = value ? 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 value) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(is_connected()); |
| + |
| + int opt_value = value ? 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)) |