Chromium Code Reviews| Index: net/udp/udp_socket_libevent.cc |
| diff --git a/net/udp/udp_socket_libevent.cc b/net/udp/udp_socket_libevent.cc |
| index 9b1a9957189d968c3fed617ba02aa3ee7d13cb98..5fef2b9298b6161e8ecbdcb6ca16179f1d7ca2ef 100644 |
| --- a/net/udp/udp_socket_libevent.cc |
| +++ b/net/udp/udp_socket_libevent.cc |
| @@ -317,34 +317,70 @@ int UDPSocketLibevent::Bind(const IPEndPoint& address) { |
| int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { |
| DCHECK(CalledOnValidThread()); |
| - int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| - reinterpret_cast<const char*>(&size), sizeof(size)); |
| - int last_error = errno; |
| - DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; |
| - return rv == 0 ? OK : MapSystemError(last_error); |
| + if (is_connected()) { |
| + int result = SetReceiveBufferSizeInternal(size); |
| + if (result != OK) |
| + return result; |
| + } |
| + socket_options_ |= SOCKET_OPTION_RCVBUF_SIZE; |
| + rcvbuf_size_ = size; |
| + return OK; |
| } |
| int UDPSocketLibevent::SetSendBufferSize(int32 size) { |
| DCHECK(CalledOnValidThread()); |
| - int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| - reinterpret_cast<const char*>(&size), sizeof(size)); |
| - int last_error = errno; |
| - DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; |
| - return rv == 0 ? OK : MapSystemError(last_error); |
| + if (is_connected()) { |
| + int result = SetSendBufferSizeInternal(size); |
| + if (result != OK) |
| + return result; |
| + } |
| + socket_options_ |= SOCKET_OPTION_SNDBUF_SIZE; |
| + sndbuf_size_ = size; |
| + return OK; |
| } |
| -void UDPSocketLibevent::AllowAddressReuse() { |
| +int UDPSocketLibevent::AllowAddressReuse() { |
| DCHECK(CalledOnValidThread()); |
| - DCHECK(!is_connected()); |
| - |
| + if (is_connected()) { |
|
jar (doing other things)
2014/11/04 22:51:09
What are the semantics for setting AllowAddressRus
hidehiko
2014/11/05 12:48:30
It affects the behavior of other socket's for the
|
| + int result = SetAddressReuseInternal(true); |
| + if (result != OK) |
| + return result; |
| + } |
| socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
| + return OK; |
| } |
| -void UDPSocketLibevent::AllowBroadcast() { |
| +int UDPSocketLibevent::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 UDPSocketLibevent::AllowBroadcast() { |
|
jar (doing other things)
2014/11/04 22:51:09
Why don't you use a single setter method, taking a
hidehiko
2014/11/05 12:48:30
I just kept the current interface, as UDPSocket{Li
|
| + DCHECK(CalledOnValidThread()); |
| + if (is_connected()) { |
| + int result = SetBroadcastInternal(true); |
| + if (result != OK) |
| + return result; |
| + } |
| socket_options_ |= SOCKET_OPTION_BROADCAST; |
| + return OK; |
| +} |
| + |
| +int UDPSocketLibevent::DisallowBroadcast() { |
| + DCHECK(CalledOnValidThread()); |
| + if (is_connected()) { |
| + int result = SetBroadcastInternal(false); |
| + if (result != OK) |
| + return result; |
| + } |
| + socket_options_ &= ~SOCKET_OPTION_BROADCAST; |
| + return OK; |
| } |
| void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { |
| @@ -516,29 +552,17 @@ int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, |
| } |
| int UDPSocketLibevent::SetSocketOptions() { |
| - int true_value = 1; |
| + DCHECK(CalledOnValidThread()); |
| if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
| - int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, |
| - sizeof(true_value)); |
| - if (rv < 0) |
| - return MapSystemError(errno); |
| + int rv = SetAddressReuseInternal(true); |
| + if (rv != OK) |
| + return rv; |
| } |
| if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
| - int rv; |
| -#if defined(OS_MACOSX) |
| - // SO_REUSEPORT on OSX permits multiple processes to each receive |
| - // UDP multicast or broadcast datagrams destined for the bound |
| - // port. |
| - rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, |
| - sizeof(true_value)); |
| -#else |
| - rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, |
| - sizeof(true_value)); |
| -#endif // defined(OS_MACOSX) |
| - if (rv < 0) |
| - return MapSystemError(errno); |
| + int rv = SetBroadcastInternal(true); |
| + if (rv != OK) |
| + return rv; |
| } |
| - |
| if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
| int rv; |
| if (addr_family_ == AF_INET) { |
| @@ -553,6 +577,17 @@ int UDPSocketLibevent::SetSocketOptions() { |
| if (rv < 0) |
| return MapSystemError(errno); |
| } |
| + 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_ != IP_DEFAULT_MULTICAST_TTL) { |
| int rv; |
| if (addr_family_ == AF_INET) { |
| @@ -605,6 +640,52 @@ int UDPSocketLibevent::SetSocketOptions() { |
| return OK; |
| } |
| +int UDPSocketLibevent::SetAddressReuseInternal(bool value) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(is_connected()); |
| + int opt_value = value ? 1 : 0; |
| + int rv = setsockopt( |
| + socket_, SOL_SOCKET, SO_REUSEADDR, &opt_value, sizeof(opt_value)); |
| + return rv == 0 ? OK : MapSystemError(errno); |
| +} |
| + |
| +int UDPSocketLibevent::SetBroadcastInternal(bool value) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(is_connected()); |
| + int opt_value = value ? 1 : 0; |
| +#if defined(OS_MACOSX) |
| + // SO_REUSEPORT on OSX permits multiple processes to each receive |
| + // UDP multicast or broadcast datagrams destined for the bound |
| + // port. |
| + const int kOptName = SO_REUSEPORT; |
| +#else |
| + const int kOptName = SO_BROADCAST; |
| +#endif |
| + int rv = setsockopt( |
| + socket_, SOL_SOCKET, kOptName, &opt_value, sizeof(opt_value)); |
| + return rv == 0 ? OK : MapSystemError(errno); |
| +} |
| + |
| +int UDPSocketLibevent::SetReceiveBufferSizeInternal(int32 size) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(is_connected()); |
| + int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
| + reinterpret_cast<const char*>(&size), sizeof(size)); |
| + int last_error = errno; |
| + DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; |
| + return rv == 0 ? OK : MapSystemError(last_error); |
| +} |
| + |
| +int UDPSocketLibevent::SetSendBufferSizeInternal(int32 size) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(is_connected()); |
| + int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
| + reinterpret_cast<const char*>(&size), sizeof(size)); |
| + int last_error = errno; |
| + DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; |
| + return rv == 0 ? OK : MapSystemError(last_error); |
| +} |
| + |
| int UDPSocketLibevent::DoBind(const IPEndPoint& address) { |
| SockaddrStorage storage; |
| if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |