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); |
} |