Chromium Code Reviews| 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 <netdb.h> | 10 #include <netdb.h> |
| 10 #include <net/if.h> | |
| 11 #include <netinet/in.h> | 11 #include <netinet/in.h> |
| 12 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
| 13 #include <sys/socket.h> | 13 #include <sys/socket.h> |
| 14 | 14 |
| 15 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/debug/alias.h" | 16 #include "base/debug/alias.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
| 19 #include "base/metrics/sparse_histogram.h" | 19 #include "base/metrics/sparse_histogram.h" |
| 20 #include "base/posix/eintr_wrapper.h" | 20 #include "base/posix/eintr_wrapper.h" |
| 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_log.h" | 25 #include "net/base/net_log.h" |
| 26 #include "net/base/net_util.h" | 26 #include "net/base/net_util.h" |
| 27 #include "net/base/network_activity_monitor.h" | 27 #include "net/base/network_activity_monitor.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) | |
| 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) | |
| 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) |
| 41 | 47 |
| 42 // Returns IPv4 address in network order. | 48 // Returns IPv4 address in network order. |
| 43 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address){ | 49 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address){ |
| 44 if (!index) { | 50 if (!index) { |
| 45 *address = htonl(INADDR_ANY); | 51 *address = htonl(INADDR_ANY); |
| 46 return OK; | 52 return OK; |
| 47 } | 53 } |
| 48 ifreq ifr; | 54 ifreq ifr; |
| 49 ifr.ifr_addr.sa_family = AF_INET; | 55 ifr.ifr_addr.sa_family = AF_INET; |
| 50 if (!if_indextoname(index, ifr.ifr_name)) | 56 if (!if_indextoname(index, ifr.ifr_name)) |
| 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 |
| 65 // On OSX the file descriptor is guarded to detect the cause of | |
| 66 // crbug.com/461246. sys/guarded.h is not included in the SDK, so the API needs | |
| 67 // to be defined here. | |
| 68 // TODO(sergeyu): Removed this code once the bug is resolved. | |
| 69 | |
| 70 typedef uint64_t guardid_t; | |
| 71 | |
| 72 typedef int (*GuardedCloseNpFunction)(int fd, const guardid_t* guard); | |
| 73 typedef int (*ChangeFdguardNpFunction)(int fd, | |
| 74 const guardid_t* guard, | |
| 75 u_int flags, | |
| 76 const guardid_t* nguard, | |
| 77 u_int nflags, | |
| 78 int* fdflagsp); | |
| 79 | |
| 80 void* g_libsystem_handle = nullptr; | |
|
Mark Mentovai
2015/04/02 18:21:57
This is only used in InitGuardedFunctions, make it
Sergey Ulanov
2015/04/02 18:28:19
Done. It doesn't need to be static.
| |
| 81 GuardedCloseNpFunction g_guarded_close_np = nullptr; | |
| 82 ChangeFdguardNpFunction g_change_fdguard_np = nullptr; | |
| 83 | |
| 84 static pthread_once_t g_guarded_functions_once = PTHREAD_ONCE_INIT; | |
|
Mark Mentovai
2015/04/02 18:21:57
You’re in an unnamed namespace, you shouldn’t have
Sergey Ulanov
2015/04/02 18:28:18
Done.
| |
| 85 | |
| 86 static void InitGuardedFunctions() { | |
| 87 g_libsystem_handle = dlopen("/usr/lib/libSystem.dylib", 0); | |
|
Mark Mentovai
2015/04/02 18:21:57
Use RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD, not 0.
Sergey Ulanov
2015/04/02 18:28:18
Done.
| |
| 88 if (g_libsystem_handle) { | |
| 89 g_guarded_close_np = reinterpret_cast<GuardedCloseNpFunction>( | |
| 90 dlsym(g_libsystem_handle, "guarded_close_np")); | |
| 91 g_change_fdguard_np = reinterpret_cast<ChangeFdguardNpFunction>( | |
| 92 dlsym(g_libsystem_handle, "change_fdguard_np")); | |
| 93 | |
| 94 // If for any reason only one of the functions is found, set both of them to | |
| 95 // nullptr. | |
| 96 if (!g_guarded_close_np || !g_change_fdguard_np) { | |
| 97 g_guarded_close_np = nullptr; | |
| 98 g_change_fdguard_np = nullptr; | |
| 99 } | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 int change_fdguard_np(int fd, const guardid_t* guard, u_int flags, | |
| 104 const guardid_t* nguard, u_int nflags, int* fdflagsp) { | |
| 105 CHECK_EQ(pthread_once(&g_guarded_functions_once, InitGuardedFunctions), 0); | |
| 106 // Older version of OSX may not support guarded API. | |
| 107 if (!g_change_fdguard_np) | |
| 108 return 0; | |
| 109 return g_change_fdguard_np(fd, guard, flags, nguard, nflags, fdflagsp); | |
| 110 } | |
| 111 | |
| 112 int guarded_close_np(int fd, const guardid_t* guard) { | |
| 113 // Older version of OSX may not support guarded API. | |
| 114 if (!g_guarded_close_np) | |
| 115 return close(fd); | |
| 116 | |
| 117 return g_guarded_close_np(fd, guard); | |
| 118 } | |
| 119 | |
| 120 const unsigned int GUARD_CLOSE = 1u << 0; | |
| 121 const unsigned int GUARD_DUP = 1u << 1; | |
| 122 | |
| 123 const guardid_t kSocketFdGuard = 0xD712BC0BC9A4EAD4; | |
| 124 | |
| 59 #endif // OS_MACOSX | 125 #endif // OS_MACOSX |
| 60 | 126 |
| 61 } // namespace | 127 } // namespace |
| 62 | 128 |
| 63 UDPSocketLibevent::UDPSocketLibevent( | 129 UDPSocketLibevent::UDPSocketLibevent( |
| 64 DatagramSocket::BindType bind_type, | 130 DatagramSocket::BindType bind_type, |
| 65 const RandIntCallback& rand_int_cb, | 131 const RandIntCallback& rand_int_cb, |
| 66 net::NetLog* net_log, | 132 net::NetLog* net_log, |
| 67 const net::NetLog::Source& source) | 133 const net::NetLog::Source& source) |
| 68 : socket_(kInvalidSocket), | 134 : socket_(kInvalidSocket), |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 91 } | 157 } |
| 92 | 158 |
| 93 int UDPSocketLibevent::Open(AddressFamily address_family) { | 159 int UDPSocketLibevent::Open(AddressFamily address_family) { |
| 94 DCHECK(CalledOnValidThread()); | 160 DCHECK(CalledOnValidThread()); |
| 95 DCHECK_EQ(socket_, kInvalidSocket); | 161 DCHECK_EQ(socket_, kInvalidSocket); |
| 96 | 162 |
| 97 addr_family_ = ConvertAddressFamily(address_family); | 163 addr_family_ = ConvertAddressFamily(address_family); |
| 98 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); | 164 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); |
| 99 if (socket_ == kInvalidSocket) | 165 if (socket_ == kInvalidSocket) |
| 100 return MapSystemError(errno); | 166 return MapSystemError(errno); |
| 167 #if defined(OS_MACOSX) | |
| 168 PCHECK(change_fdguard_np(socket_, NULL, 0, &kSocketFdGuard, | |
| 169 GUARD_CLOSE | GUARD_DUP, NULL) == 0); | |
| 170 #endif // OS_MACOSX | |
| 101 if (SetNonBlocking(socket_)) { | 171 if (SetNonBlocking(socket_)) { |
| 102 const int err = MapSystemError(errno); | 172 const int err = MapSystemError(errno); |
| 103 Close(); | 173 Close(); |
| 104 return err; | 174 return err; |
| 105 } | 175 } |
| 106 return OK; | 176 return OK; |
| 107 } | 177 } |
| 108 | 178 |
| 109 void UDPSocketLibevent::Close() { | 179 void UDPSocketLibevent::Close() { |
| 110 DCHECK(CalledOnValidThread()); | 180 DCHECK(CalledOnValidThread()); |
| 111 | 181 |
| 112 if (socket_ == kInvalidSocket) | 182 if (socket_ == kInvalidSocket) |
| 113 return; | 183 return; |
| 114 | 184 |
| 115 // Zero out any pending read/write callback state. | 185 // Zero out any pending read/write callback state. |
| 116 read_buf_ = NULL; | 186 read_buf_ = NULL; |
| 117 read_buf_len_ = 0; | 187 read_buf_len_ = 0; |
| 118 read_callback_.Reset(); | 188 read_callback_.Reset(); |
| 119 recv_from_address_ = NULL; | 189 recv_from_address_ = NULL; |
| 120 write_buf_ = NULL; | 190 write_buf_ = NULL; |
| 121 write_buf_len_ = 0; | 191 write_buf_len_ = 0; |
| 122 write_callback_.Reset(); | 192 write_callback_.Reset(); |
| 123 send_to_address_.reset(); | 193 send_to_address_.reset(); |
| 124 | 194 |
| 125 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 195 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
| 126 DCHECK(ok); | 196 DCHECK(ok); |
| 127 ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 197 ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
| 128 DCHECK(ok); | 198 DCHECK(ok); |
| 129 | 199 |
| 200 #if defined(OS_MACOSX) | |
| 201 PCHECK(IGNORE_EINTR(guarded_close_np(socket_, &kSocketFdGuard)) == 0); | |
| 202 #else | |
| 130 PCHECK(IGNORE_EINTR(close(socket_)) == 0); | 203 PCHECK(IGNORE_EINTR(close(socket_)) == 0); |
| 204 #endif // OS_MACOSX | |
| 131 | 205 |
| 132 socket_ = kInvalidSocket; | 206 socket_ = kInvalidSocket; |
| 133 addr_family_ = 0; | 207 addr_family_ = 0; |
| 134 is_connected_ = false; | 208 is_connected_ = false; |
| 135 } | 209 } |
| 136 | 210 |
| 137 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { | 211 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { |
| 138 DCHECK(CalledOnValidThread()); | 212 DCHECK(CalledOnValidThread()); |
| 139 DCHECK(address); | 213 DCHECK(address); |
| 140 if (!is_connected()) | 214 if (!is_connected()) |
| (...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 744 return MapSystemError(errno); | 818 return MapSystemError(errno); |
| 745 | 819 |
| 746 return OK; | 820 return OK; |
| 747 } | 821 } |
| 748 | 822 |
| 749 void UDPSocketLibevent::DetachFromThread() { | 823 void UDPSocketLibevent::DetachFromThread() { |
| 750 base::NonThreadSafe::DetachFromThread(); | 824 base::NonThreadSafe::DetachFromThread(); |
| 751 } | 825 } |
| 752 | 826 |
| 753 } // namespace net | 827 } // namespace net |
| OLD | NEW |