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 2dffff3a31090eafbda962472c2840d0d3ceca2e..4570df73cf13c336ce0a2ced185450223cb864e4 100644 |
| --- a/net/udp/udp_socket_libevent.cc |
| +++ b/net/udp/udp_socket_libevent.cc |
| @@ -67,6 +67,7 @@ UDPSocketLibevent::UDPSocketLibevent( |
| const net::NetLog::Source& source) |
| : socket_(kInvalidSocket), |
| addr_family_(0), |
| + is_connected_(false), |
| socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| multicast_interface_(0), |
| multicast_time_to_live_(1), |
| @@ -89,10 +90,16 @@ UDPSocketLibevent::~UDPSocketLibevent() { |
| net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
| } |
| +int UDPSocketLibevent::Open(AddressFamily address_family) { |
| + DCHECK(CalledOnValidThread()); |
| + DCHECK(socket_ == kInvalidSocket); |
| + return CreateSocket(ConvertAddressFamily(address_family)); |
| +} |
| + |
| void UDPSocketLibevent::Close() { |
| DCHECK(CalledOnValidThread()); |
| - if (!is_connected()) |
| + if (socket_ == kInvalidSocket) |
| return; |
| // Zero out any pending read/write callback state. |
| @@ -115,6 +122,7 @@ void UDPSocketLibevent::Close() { |
| socket_ = kInvalidSocket; |
| addr_family_ = 0; |
| + is_connected_ = false; |
| } |
| int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { |
| @@ -246,9 +254,8 @@ int UDPSocketLibevent::Connect(const IPEndPoint& address) { |
| net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, |
| CreateNetLogUDPConnectCallback(&address)); |
| int rv = InternalConnect(address); |
| - if (rv != OK) |
| - Close(); |
| net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); |
| + is_connected_ = (rv == OK); |
| return rv; |
| } |
| @@ -256,16 +263,13 @@ int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { |
| DCHECK(CalledOnValidThread()); |
| DCHECK(!is_connected()); |
| DCHECK(!remote_address_.get()); |
| - int addr_family = address.GetSockAddrFamily(); |
| - int rv = CreateSocket(addr_family); |
| - if (rv < 0) |
| - return rv; |
| + int rv = 0; |
| if (bind_type_ == DatagramSocket::RANDOM_BIND) { |
| // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, |
| // representing INADDR_ANY or in6addr_any. |
| - size_t addr_size = |
| - addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; |
| + size_t addr_size = address.GetSockAddrFamily() == AF_INET ? |
| + kIPv4AddressSize : kIPv6AddressSize; |
| IPAddressNumber addr_any(addr_size); |
| rv = RandomBind(addr_any); |
| } |
| @@ -273,23 +277,16 @@ int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { |
| if (rv < 0) { |
| UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); |
| - Close(); |
| return rv; |
| } |
| SockaddrStorage storage; |
| - if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { |
| - Close(); |
| + if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| return ERR_ADDRESS_INVALID; |
| - } |
| rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len)); |
| - if (rv < 0) { |
| - // Close() may change the current errno. Map errno beforehand. |
| - int result = MapSystemError(errno); |
| - Close(); |
| - return result; |
| - } |
| + if (rv < 0) |
| + return MapSystemError(errno); |
| remote_address_.reset(new IPEndPoint(address)); |
| return rv; |
| @@ -298,20 +295,16 @@ int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { |
| int UDPSocketLibevent::Bind(const IPEndPoint& address) { |
| DCHECK(CalledOnValidThread()); |
| DCHECK(!is_connected()); |
| - int rv = CreateSocket(address.GetSockAddrFamily()); |
| + |
| + int rv = SetSocketOptions(); |
| if (rv < 0) |
| return rv; |
| - rv = SetSocketOptions(); |
| - if (rv < 0) { |
| - Close(); |
| - return rv; |
| - } |
| rv = DoBind(address); |
| - if (rv < 0) { |
| - Close(); |
| + if (rv < 0) |
| return rv; |
| - } |
| + |
| + is_connected_ = true; |
| local_address_.reset(); |
| return rv; |
| } |
| @@ -341,11 +334,21 @@ void UDPSocketLibevent::AllowAddressReuse() { |
| socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
| } |
| -void UDPSocketLibevent::AllowBroadcast() { |
| +int UDPSocketLibevent::SetBroadcast(bool broadcast) { |
| DCHECK(CalledOnValidThread()); |
| - DCHECK(!is_connected()); |
| - |
| - socket_options_ |= SOCKET_OPTION_BROADCAST; |
| + int value = broadcast ? 1 : 0; |
| + 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, &value, sizeof(value)); |
| +#else |
| + rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value)); |
| +#endif // defined(OS_MACOSX) |
| + int last_error = errno; |
| + DCHECK(!rv) << "Could not set socket broadcast option: " << last_error; |
|
rvargas (doing something else)
2014/12/02 23:28:09
Not a good idea to DCHECK the return of an operati
hidehiko
2014/12/03 17:33:27
Done.
|
| + return rv == 0 ? OK : MapSystemError(last_error); |
| } |
| void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { |
| @@ -519,25 +522,10 @@ int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, |
| } |
| int UDPSocketLibevent::SetSocketOptions() { |
| - int true_value = 1; |
| 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); |
| - } |
| - 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) |
| + int true_value = 1; |
| + int rv = setsockopt( |
| + socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value)); |
| if (rv < 0) |
| return MapSystemError(errno); |
| } |