| 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..8dd102a8a77a47e9e71e8bd1b01c271bded104a7 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,26 @@ UDPSocketLibevent::~UDPSocketLibevent() {
|
| net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
|
| }
|
|
|
| +int UDPSocketLibevent::Open(AddressFamily address_family) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK_EQ(socket_, kInvalidSocket);
|
| +
|
| + addr_family_ = ConvertAddressFamily(address_family);
|
| + socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
|
| + if (socket_ == kInvalidSocket)
|
| + return MapSystemError(errno);
|
| + if (SetNonBlocking(socket_)) {
|
| + const int err = MapSystemError(errno);
|
| + Close();
|
| + return err;
|
| + }
|
| + return OK;
|
| +}
|
| +
|
| void UDPSocketLibevent::Close() {
|
| DCHECK(CalledOnValidThread());
|
|
|
| - if (!is_connected())
|
| + if (socket_ == kInvalidSocket)
|
| return;
|
|
|
| // Zero out any pending read/write callback state.
|
| @@ -115,6 +132,7 @@ void UDPSocketLibevent::Close() {
|
|
|
| socket_ = kInvalidSocket;
|
| addr_family_ = 0;
|
| + is_connected_ = false;
|
| }
|
|
|
| int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
|
| @@ -243,12 +261,12 @@ int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf,
|
| }
|
|
|
| int UDPSocketLibevent::Connect(const IPEndPoint& address) {
|
| + DCHECK_NE(socket_, kInvalidSocket);
|
| 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 +274,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,79 +288,79 @@ 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;
|
| }
|
|
|
| int UDPSocketLibevent::Bind(const IPEndPoint& address) {
|
| + DCHECK_NE(socket_, kInvalidSocket);
|
| DCHECK(CalledOnValidThread());
|
| DCHECK(!is_connected());
|
| - int rv = CreateSocket(address.GetSockAddrFamily());
|
| +
|
| + int rv = SetMulticastOptions();
|
| 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;
|
| }
|
|
|
| int UDPSocketLibevent::SetReceiveBufferSize(int32 size) {
|
| + DCHECK_NE(socket_, kInvalidSocket);
|
| 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);
|
| + return rv == 0 ? OK : MapSystemError(errno);
|
| }
|
|
|
| int UDPSocketLibevent::SetSendBufferSize(int32 size) {
|
| + DCHECK_NE(socket_, kInvalidSocket);
|
| 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);
|
| + return rv == 0 ? OK : MapSystemError(errno);
|
| }
|
|
|
| -void UDPSocketLibevent::AllowAddressReuse() {
|
| +int UDPSocketLibevent::AllowAddressReuse() {
|
| + DCHECK_NE(socket_, kInvalidSocket);
|
| DCHECK(CalledOnValidThread());
|
| DCHECK(!is_connected());
|
| -
|
| - socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
|
| + int true_value = 1;
|
| + int rv = setsockopt(
|
| + socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value));
|
| + return rv == 0 ? OK : MapSystemError(errno);
|
| }
|
|
|
| -void UDPSocketLibevent::AllowBroadcast() {
|
| +int UDPSocketLibevent::SetBroadcast(bool broadcast) {
|
| + DCHECK_NE(socket_, kInvalidSocket);
|
| 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)
|
| + return rv == 0 ? OK : MapSystemError(errno);
|
| }
|
|
|
| void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
|
| @@ -418,19 +433,6 @@ void UDPSocketLibevent::LogRead(int result,
|
| NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
|
| }
|
|
|
| -int UDPSocketLibevent::CreateSocket(int addr_family) {
|
| - addr_family_ = addr_family;
|
| - socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
|
| - if (socket_ == kInvalidSocket)
|
| - return MapSystemError(errno);
|
| - if (SetNonBlocking(socket_)) {
|
| - const int err = MapSystemError(errno);
|
| - Close();
|
| - return err;
|
| - }
|
| - return OK;
|
| -}
|
| -
|
| void UDPSocketLibevent::DidCompleteWrite() {
|
| int result =
|
| InternalSendTo(write_buf_.get(), write_buf_len_, send_to_address_.get());
|
| @@ -518,30 +520,7 @@ int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len,
|
| return result;
|
| }
|
|
|
| -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)
|
| - if (rv < 0)
|
| - return MapSystemError(errno);
|
| - }
|
| -
|
| +int UDPSocketLibevent::SetMulticastOptions() {
|
| if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
|
| int rv;
|
| if (addr_family_ == AF_INET) {
|
|
|