| 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..0d645e905d0bc4e0a8620a3f021b04808db5a638 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()) {
|
| + 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() {
|
| + 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 address_reuse) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(is_connected());
|
| + int opt_value = address_reuse ? 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 broadcast) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(is_connected());
|
| + int opt_value = broadcast ? 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))
|
|
|