| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/udp/udp_socket_libevent.h" | 5 #include "net/udp/udp_socket_libevent.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <net/if.h> | 9 #include <net/if.h> |
| 10 #include <netdb.h> | 10 #include <netdb.h> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "base/rand_util.h" | 21 #include "base/rand_util.h" |
| 22 #include "net/base/io_buffer.h" | 22 #include "net/base/io_buffer.h" |
| 23 #include "net/base/ip_endpoint.h" | 23 #include "net/base/ip_endpoint.h" |
| 24 #include "net/base/net_errors.h" | 24 #include "net/base/net_errors.h" |
| 25 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
| 26 #include "net/base/network_activity_monitor.h" | 26 #include "net/base/network_activity_monitor.h" |
| 27 #include "net/log/net_log.h" | 27 #include "net/log/net_log.h" |
| 28 #include "net/socket/socket_descriptor.h" | 28 #include "net/socket/socket_descriptor.h" |
| 29 #include "net/udp/udp_net_log_parameters.h" | 29 #include "net/udp/udp_net_log_parameters.h" |
| 30 | 30 |
| 31 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 32 // Needed temporarily to debug crbug.com/461246. |
| 33 // TODO(sergeyu): Remove once the bug is resolved. |
| 34 #include <dlfcn.h> |
| 35 #include <pthread.h> |
| 36 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 31 | 37 |
| 32 namespace net { | 38 namespace net { |
| 33 | 39 |
| 34 namespace { | 40 namespace { |
| 35 | 41 |
| 36 const int kBindRetries = 10; | 42 const int kBindRetries = 10; |
| 37 const int kPortStart = 1024; | 43 const int kPortStart = 1024; |
| 38 const int kPortEnd = 65535; | 44 const int kPortEnd = 65535; |
| 39 | 45 |
| 40 #if defined(OS_MACOSX) | 46 #if defined(OS_MACOSX) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 51 return MapSystemError(errno); | 57 return MapSystemError(errno); |
| 52 int rv = ioctl(socket, SIOCGIFADDR, &ifr); | 58 int rv = ioctl(socket, SIOCGIFADDR, &ifr); |
| 53 if (rv == -1) | 59 if (rv == -1) |
| 54 return MapSystemError(errno); | 60 return MapSystemError(errno); |
| 55 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; | 61 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; |
| 56 return OK; | 62 return OK; |
| 57 } | 63 } |
| 58 | 64 |
| 59 #endif // OS_MACOSX | 65 #endif // OS_MACOSX |
| 60 | 66 |
| 67 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 68 |
| 69 // On OSX the file descriptor is guarded to detect the cause of |
| 70 // crbug.com/461246. guarded API is supported only on newer versions of OSX, |
| 71 // so the symbols need to be resolved dynamically. |
| 72 // TODO(sergeyu): Removed this code once the bug is resolved. |
| 73 |
| 74 typedef uint64_t guardid_t; |
| 75 |
| 76 typedef int (*GuardedCloseNpFunction)(int fd, const guardid_t* guard); |
| 77 typedef int (*ChangeFdguardNpFunction)(int fd, |
| 78 const guardid_t* guard, |
| 79 u_int flags, |
| 80 const guardid_t* nguard, |
| 81 u_int nflags, |
| 82 int* fdflagsp); |
| 83 |
| 84 GuardedCloseNpFunction g_guarded_close_np = nullptr; |
| 85 ChangeFdguardNpFunction g_change_fdguard_np = nullptr; |
| 86 |
| 87 pthread_once_t g_guarded_functions_once = PTHREAD_ONCE_INIT; |
| 88 |
| 89 void InitGuardedFunctions() { |
| 90 void* libsystem_handle = |
| 91 dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); |
| 92 if (libsystem_handle) { |
| 93 g_guarded_close_np = reinterpret_cast<GuardedCloseNpFunction>( |
| 94 dlsym(libsystem_handle, "guarded_close_np")); |
| 95 g_change_fdguard_np = reinterpret_cast<ChangeFdguardNpFunction>( |
| 96 dlsym(libsystem_handle, "change_fdguard_np")); |
| 97 |
| 98 // If for any reason only one of the functions is found, set both of them to |
| 99 // nullptr. |
| 100 if (!g_guarded_close_np || !g_change_fdguard_np) { |
| 101 g_guarded_close_np = nullptr; |
| 102 g_change_fdguard_np = nullptr; |
| 103 } |
| 104 } |
| 105 } |
| 106 |
| 107 int change_fdguard_np(int fd, |
| 108 const guardid_t* guard, |
| 109 u_int flags, |
| 110 const guardid_t* nguard, |
| 111 u_int nflags, |
| 112 int* fdflagsp) { |
| 113 CHECK_EQ(pthread_once(&g_guarded_functions_once, InitGuardedFunctions), 0); |
| 114 // Older version of OSX may not support guarded API. |
| 115 if (!g_change_fdguard_np) |
| 116 return 0; |
| 117 return g_change_fdguard_np(fd, guard, flags, nguard, nflags, fdflagsp); |
| 118 } |
| 119 |
| 120 int guarded_close_np(int fd, const guardid_t* guard) { |
| 121 // Older version of OSX may not support guarded API. |
| 122 if (!g_guarded_close_np) |
| 123 return close(fd); |
| 124 |
| 125 return g_guarded_close_np(fd, guard); |
| 126 } |
| 127 |
| 128 const unsigned int GUARD_CLOSE = 1u << 0; |
| 129 const unsigned int GUARD_DUP = 1u << 1; |
| 130 |
| 131 const guardid_t kSocketFdGuard = 0xD712BC0BC9A4EAD4; |
| 132 |
| 133 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 134 |
| 61 } // namespace | 135 } // namespace |
| 62 | 136 |
| 63 UDPSocketLibevent::UDPSocketLibevent( | 137 UDPSocketLibevent::UDPSocketLibevent( |
| 64 DatagramSocket::BindType bind_type, | 138 DatagramSocket::BindType bind_type, |
| 65 const RandIntCallback& rand_int_cb, | 139 const RandIntCallback& rand_int_cb, |
| 66 net::NetLog* net_log, | 140 net::NetLog* net_log, |
| 67 const net::NetLog::Source& source) | 141 const net::NetLog::Source& source) |
| 68 : socket_(kInvalidSocket), | 142 : socket_(kInvalidSocket), |
| 69 addr_family_(0), | 143 addr_family_(0), |
| 70 is_connected_(false), | 144 is_connected_(false), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 91 } | 165 } |
| 92 | 166 |
| 93 int UDPSocketLibevent::Open(AddressFamily address_family) { | 167 int UDPSocketLibevent::Open(AddressFamily address_family) { |
| 94 DCHECK(CalledOnValidThread()); | 168 DCHECK(CalledOnValidThread()); |
| 95 DCHECK_EQ(socket_, kInvalidSocket); | 169 DCHECK_EQ(socket_, kInvalidSocket); |
| 96 | 170 |
| 97 addr_family_ = ConvertAddressFamily(address_family); | 171 addr_family_ = ConvertAddressFamily(address_family); |
| 98 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); | 172 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); |
| 99 if (socket_ == kInvalidSocket) | 173 if (socket_ == kInvalidSocket) |
| 100 return MapSystemError(errno); | 174 return MapSystemError(errno); |
| 175 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 176 PCHECK(change_fdguard_np(socket_, NULL, 0, &kSocketFdGuard, |
| 177 GUARD_CLOSE | GUARD_DUP, NULL) == 0); |
| 178 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 101 if (SetNonBlocking(socket_)) { | 179 if (SetNonBlocking(socket_)) { |
| 102 const int err = MapSystemError(errno); | 180 const int err = MapSystemError(errno); |
| 103 Close(); | 181 Close(); |
| 104 return err; | 182 return err; |
| 105 } | 183 } |
| 106 return OK; | 184 return OK; |
| 107 } | 185 } |
| 108 | 186 |
| 109 void UDPSocketLibevent::Close() { | 187 void UDPSocketLibevent::Close() { |
| 110 DCHECK(CalledOnValidThread()); | 188 DCHECK(CalledOnValidThread()); |
| 111 | 189 |
| 112 if (socket_ == kInvalidSocket) | 190 if (socket_ == kInvalidSocket) |
| 113 return; | 191 return; |
| 114 | 192 |
| 115 // Zero out any pending read/write callback state. | 193 // Zero out any pending read/write callback state. |
| 116 read_buf_ = NULL; | 194 read_buf_ = NULL; |
| 117 read_buf_len_ = 0; | 195 read_buf_len_ = 0; |
| 118 read_callback_.Reset(); | 196 read_callback_.Reset(); |
| 119 recv_from_address_ = NULL; | 197 recv_from_address_ = NULL; |
| 120 write_buf_ = NULL; | 198 write_buf_ = NULL; |
| 121 write_buf_len_ = 0; | 199 write_buf_len_ = 0; |
| 122 write_callback_.Reset(); | 200 write_callback_.Reset(); |
| 123 send_to_address_.reset(); | 201 send_to_address_.reset(); |
| 124 | 202 |
| 125 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 203 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
| 126 DCHECK(ok); | 204 DCHECK(ok); |
| 127 ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 205 ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
| 128 DCHECK(ok); | 206 DCHECK(ok); |
| 129 | 207 |
| 208 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 209 PCHECK(IGNORE_EINTR(guarded_close_np(socket_, &kSocketFdGuard)) == 0); |
| 210 #else |
| 130 PCHECK(IGNORE_EINTR(close(socket_)) == 0); | 211 PCHECK(IGNORE_EINTR(close(socket_)) == 0); |
| 212 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 131 | 213 |
| 132 socket_ = kInvalidSocket; | 214 socket_ = kInvalidSocket; |
| 133 addr_family_ = 0; | 215 addr_family_ = 0; |
| 134 is_connected_ = false; | 216 is_connected_ = false; |
| 135 } | 217 } |
| 136 | 218 |
| 137 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { | 219 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { |
| 138 DCHECK(CalledOnValidThread()); | 220 DCHECK(CalledOnValidThread()); |
| 139 DCHECK(address); | 221 DCHECK(address); |
| 140 if (!is_connected()) | 222 if (!is_connected()) |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 return MapSystemError(errno); | 826 return MapSystemError(errno); |
| 745 | 827 |
| 746 return OK; | 828 return OK; |
| 747 } | 829 } |
| 748 | 830 |
| 749 void UDPSocketLibevent::DetachFromThread() { | 831 void UDPSocketLibevent::DetachFromThread() { |
| 750 base::NonThreadSafe::DetachFromThread(); | 832 base::NonThreadSafe::DetachFromThread(); |
| 751 } | 833 } |
| 752 | 834 |
| 753 } // namespace net | 835 } // namespace net |
| OLD | NEW |