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 <netdb.h> | 9 #include <netdb.h> |
10 #include <net/if.h> | 10 #include <net/if.h> |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 | 60 |
61 } // namespace | 61 } // namespace |
62 | 62 |
63 UDPSocketLibevent::UDPSocketLibevent( | 63 UDPSocketLibevent::UDPSocketLibevent( |
64 DatagramSocket::BindType bind_type, | 64 DatagramSocket::BindType bind_type, |
65 const RandIntCallback& rand_int_cb, | 65 const RandIntCallback& rand_int_cb, |
66 net::NetLog* net_log, | 66 net::NetLog* net_log, |
67 const net::NetLog::Source& source) | 67 const net::NetLog::Source& source) |
68 : socket_(kInvalidSocket), | 68 : socket_(kInvalidSocket), |
69 addr_family_(0), | 69 addr_family_(0), |
70 is_connected_(false), | |
70 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 71 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
71 multicast_interface_(0), | 72 multicast_interface_(0), |
72 multicast_time_to_live_(1), | 73 multicast_time_to_live_(1), |
73 bind_type_(bind_type), | 74 bind_type_(bind_type), |
74 rand_int_cb_(rand_int_cb), | 75 rand_int_cb_(rand_int_cb), |
75 read_watcher_(this), | 76 read_watcher_(this), |
76 write_watcher_(this), | 77 write_watcher_(this), |
77 read_buf_len_(0), | 78 read_buf_len_(0), |
78 recv_from_address_(NULL), | 79 recv_from_address_(NULL), |
79 write_buf_len_(0), | 80 write_buf_len_(0), |
80 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 81 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
81 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 82 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
82 source.ToEventParametersCallback()); | 83 source.ToEventParametersCallback()); |
83 if (bind_type == DatagramSocket::RANDOM_BIND) | 84 if (bind_type == DatagramSocket::RANDOM_BIND) |
84 DCHECK(!rand_int_cb.is_null()); | 85 DCHECK(!rand_int_cb.is_null()); |
85 } | 86 } |
86 | 87 |
87 UDPSocketLibevent::~UDPSocketLibevent() { | 88 UDPSocketLibevent::~UDPSocketLibevent() { |
88 Close(); | 89 Close(); |
89 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 90 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
90 } | 91 } |
91 | 92 |
93 int UDPSocketLibevent::Open(AddressFamily address_family) { | |
94 DCHECK(CalledOnValidThread()); | |
95 DCHECK(socket_ == kInvalidSocket); | |
96 return CreateSocket(ConvertAddressFamily(address_family)); | |
97 } | |
98 | |
92 void UDPSocketLibevent::Close() { | 99 void UDPSocketLibevent::Close() { |
93 DCHECK(CalledOnValidThread()); | 100 DCHECK(CalledOnValidThread()); |
94 | 101 |
95 if (!is_connected()) | 102 if (socket_ == kInvalidSocket) |
96 return; | 103 return; |
97 | 104 |
98 // Zero out any pending read/write callback state. | 105 // Zero out any pending read/write callback state. |
99 read_buf_ = NULL; | 106 read_buf_ = NULL; |
100 read_buf_len_ = 0; | 107 read_buf_len_ = 0; |
101 read_callback_.Reset(); | 108 read_callback_.Reset(); |
102 recv_from_address_ = NULL; | 109 recv_from_address_ = NULL; |
103 write_buf_ = NULL; | 110 write_buf_ = NULL; |
104 write_buf_len_ = 0; | 111 write_buf_len_ = 0; |
105 write_callback_.Reset(); | 112 write_callback_.Reset(); |
106 send_to_address_.reset(); | 113 send_to_address_.reset(); |
107 | 114 |
108 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 115 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
109 DCHECK(ok); | 116 DCHECK(ok); |
110 ok = write_socket_watcher_.StopWatchingFileDescriptor(); | 117 ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
111 DCHECK(ok); | 118 DCHECK(ok); |
112 | 119 |
113 if (IGNORE_EINTR(close(socket_)) < 0) | 120 if (IGNORE_EINTR(close(socket_)) < 0) |
114 PLOG(ERROR) << "close"; | 121 PLOG(ERROR) << "close"; |
115 | 122 |
116 socket_ = kInvalidSocket; | 123 socket_ = kInvalidSocket; |
117 addr_family_ = 0; | 124 addr_family_ = 0; |
125 is_connected_ = false; | |
118 } | 126 } |
119 | 127 |
120 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { | 128 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { |
121 DCHECK(CalledOnValidThread()); | 129 DCHECK(CalledOnValidThread()); |
122 DCHECK(address); | 130 DCHECK(address); |
123 if (!is_connected()) | 131 if (!is_connected()) |
124 return ERR_SOCKET_NOT_CONNECTED; | 132 return ERR_SOCKET_NOT_CONNECTED; |
125 | 133 |
126 if (!remote_address_.get()) { | 134 if (!remote_address_.get()) { |
127 SockaddrStorage storage; | 135 SockaddrStorage storage; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 send_to_address_.reset(new IPEndPoint(*address)); | 247 send_to_address_.reset(new IPEndPoint(*address)); |
240 } | 248 } |
241 write_callback_ = callback; | 249 write_callback_ = callback; |
242 return ERR_IO_PENDING; | 250 return ERR_IO_PENDING; |
243 } | 251 } |
244 | 252 |
245 int UDPSocketLibevent::Connect(const IPEndPoint& address) { | 253 int UDPSocketLibevent::Connect(const IPEndPoint& address) { |
246 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, | 254 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, |
247 CreateNetLogUDPConnectCallback(&address)); | 255 CreateNetLogUDPConnectCallback(&address)); |
248 int rv = InternalConnect(address); | 256 int rv = InternalConnect(address); |
249 if (rv != OK) | |
250 Close(); | |
251 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); | 257 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); |
258 is_connected_ = (rv == OK); | |
252 return rv; | 259 return rv; |
253 } | 260 } |
254 | 261 |
255 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { | 262 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { |
256 DCHECK(CalledOnValidThread()); | 263 DCHECK(CalledOnValidThread()); |
257 DCHECK(!is_connected()); | 264 DCHECK(!is_connected()); |
258 DCHECK(!remote_address_.get()); | 265 DCHECK(!remote_address_.get()); |
259 int addr_family = address.GetSockAddrFamily(); | |
260 int rv = CreateSocket(addr_family); | |
261 if (rv < 0) | |
262 return rv; | |
263 | 266 |
267 int rv = 0; | |
264 if (bind_type_ == DatagramSocket::RANDOM_BIND) { | 268 if (bind_type_ == DatagramSocket::RANDOM_BIND) { |
265 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, | 269 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s, |
266 // representing INADDR_ANY or in6addr_any. | 270 // representing INADDR_ANY or in6addr_any. |
267 size_t addr_size = | 271 size_t addr_size = address.GetSockAddrFamily() == AF_INET ? |
268 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; | 272 kIPv4AddressSize : kIPv6AddressSize; |
269 IPAddressNumber addr_any(addr_size); | 273 IPAddressNumber addr_any(addr_size); |
270 rv = RandomBind(addr_any); | 274 rv = RandomBind(addr_any); |
271 } | 275 } |
272 // else connect() does the DatagramSocket::DEFAULT_BIND | 276 // else connect() does the DatagramSocket::DEFAULT_BIND |
273 | 277 |
274 if (rv < 0) { | 278 if (rv < 0) { |
275 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); | 279 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); |
276 Close(); | |
277 return rv; | 280 return rv; |
278 } | 281 } |
279 | 282 |
280 SockaddrStorage storage; | 283 SockaddrStorage storage; |
281 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) { | 284 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
282 Close(); | |
283 return ERR_ADDRESS_INVALID; | 285 return ERR_ADDRESS_INVALID; |
284 } | |
285 | 286 |
286 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len)); | 287 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len)); |
287 if (rv < 0) { | 288 if (rv < 0) |
288 // Close() may change the current errno. Map errno beforehand. | 289 return MapSystemError(errno); |
289 int result = MapSystemError(errno); | |
290 Close(); | |
291 return result; | |
292 } | |
293 | 290 |
294 remote_address_.reset(new IPEndPoint(address)); | 291 remote_address_.reset(new IPEndPoint(address)); |
295 return rv; | 292 return rv; |
296 } | 293 } |
297 | 294 |
298 int UDPSocketLibevent::Bind(const IPEndPoint& address) { | 295 int UDPSocketLibevent::Bind(const IPEndPoint& address) { |
299 DCHECK(CalledOnValidThread()); | 296 DCHECK(CalledOnValidThread()); |
300 DCHECK(!is_connected()); | 297 DCHECK(!is_connected()); |
301 int rv = CreateSocket(address.GetSockAddrFamily()); | 298 |
299 int rv = SetSocketOptions(); | |
302 if (rv < 0) | 300 if (rv < 0) |
303 return rv; | 301 return rv; |
304 | 302 |
305 rv = SetSocketOptions(); | 303 rv = DoBind(address); |
306 if (rv < 0) { | 304 if (rv < 0) |
307 Close(); | |
308 return rv; | 305 return rv; |
309 } | 306 |
310 rv = DoBind(address); | 307 is_connected_ = true; |
311 if (rv < 0) { | |
312 Close(); | |
313 return rv; | |
314 } | |
315 local_address_.reset(); | 308 local_address_.reset(); |
316 return rv; | 309 return rv; |
317 } | 310 } |
318 | 311 |
319 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { | 312 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { |
320 DCHECK(CalledOnValidThread()); | 313 DCHECK(CalledOnValidThread()); |
321 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 314 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, |
322 reinterpret_cast<const char*>(&size), sizeof(size)); | 315 reinterpret_cast<const char*>(&size), sizeof(size)); |
323 int last_error = errno; | 316 int last_error = errno; |
324 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; | 317 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; |
325 return rv == 0 ? OK : MapSystemError(last_error); | 318 return rv == 0 ? OK : MapSystemError(last_error); |
326 } | 319 } |
327 | 320 |
328 int UDPSocketLibevent::SetSendBufferSize(int32 size) { | 321 int UDPSocketLibevent::SetSendBufferSize(int32 size) { |
329 DCHECK(CalledOnValidThread()); | 322 DCHECK(CalledOnValidThread()); |
330 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 323 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, |
331 reinterpret_cast<const char*>(&size), sizeof(size)); | 324 reinterpret_cast<const char*>(&size), sizeof(size)); |
332 int last_error = errno; | 325 int last_error = errno; |
333 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; | 326 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; |
334 return rv == 0 ? OK : MapSystemError(last_error); | 327 return rv == 0 ? OK : MapSystemError(last_error); |
335 } | 328 } |
336 | 329 |
337 void UDPSocketLibevent::AllowAddressReuse() { | 330 void UDPSocketLibevent::AllowAddressReuse() { |
338 DCHECK(CalledOnValidThread()); | 331 DCHECK(CalledOnValidThread()); |
339 DCHECK(!is_connected()); | 332 DCHECK(!is_connected()); |
340 | 333 |
341 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | 334 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
342 } | 335 } |
343 | 336 |
344 void UDPSocketLibevent::AllowBroadcast() { | 337 int UDPSocketLibevent::SetBroadcast(bool broadcast) { |
345 DCHECK(CalledOnValidThread()); | 338 DCHECK(CalledOnValidThread()); |
346 DCHECK(!is_connected()); | 339 int value = broadcast ? 1 : 0; |
347 | 340 int rv; |
348 socket_options_ |= SOCKET_OPTION_BROADCAST; | 341 #if defined(OS_MACOSX) |
342 // SO_REUSEPORT on OSX permits multiple processes to each receive | |
343 // UDP multicast or broadcast datagrams destined for the bound | |
344 // port. | |
345 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)); | |
346 #else | |
347 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value)); | |
348 #endif // defined(OS_MACOSX) | |
349 int last_error = errno; | |
350 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.
| |
351 return rv == 0 ? OK : MapSystemError(last_error); | |
349 } | 352 } |
350 | 353 |
351 void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { | 354 void UDPSocketLibevent::ReadWatcher::OnFileCanReadWithoutBlocking(int) { |
352 if (!socket_->read_callback_.is_null()) | 355 if (!socket_->read_callback_.is_null()) |
353 socket_->DidCompleteRead(); | 356 socket_->DidCompleteRead(); |
354 } | 357 } |
355 | 358 |
356 void UDPSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) { | 359 void UDPSocketLibevent::WriteWatcher::OnFileCanWriteWithoutBlocking(int) { |
357 if (!socket_->write_callback_.is_null()) | 360 if (!socket_->write_callback_.is_null()) |
358 socket_->DidCompleteWrite(); | 361 socket_->DidCompleteWrite(); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 addr, | 515 addr, |
513 storage.addr_len)); | 516 storage.addr_len)); |
514 if (result < 0) | 517 if (result < 0) |
515 result = MapSystemError(errno); | 518 result = MapSystemError(errno); |
516 if (result != ERR_IO_PENDING) | 519 if (result != ERR_IO_PENDING) |
517 LogWrite(result, buf->data(), address); | 520 LogWrite(result, buf->data(), address); |
518 return result; | 521 return result; |
519 } | 522 } |
520 | 523 |
521 int UDPSocketLibevent::SetSocketOptions() { | 524 int UDPSocketLibevent::SetSocketOptions() { |
522 int true_value = 1; | |
523 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | 525 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
524 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, | 526 int true_value = 1; |
525 sizeof(true_value)); | 527 int rv = setsockopt( |
528 socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value)); | |
526 if (rv < 0) | 529 if (rv < 0) |
527 return MapSystemError(errno); | 530 return MapSystemError(errno); |
528 } | 531 } |
529 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | |
530 int rv; | |
531 #if defined(OS_MACOSX) | |
532 // SO_REUSEPORT on OSX permits multiple processes to each receive | |
533 // UDP multicast or broadcast datagrams destined for the bound | |
534 // port. | |
535 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, | |
536 sizeof(true_value)); | |
537 #else | |
538 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, | |
539 sizeof(true_value)); | |
540 #endif // defined(OS_MACOSX) | |
541 if (rv < 0) | |
542 return MapSystemError(errno); | |
543 } | |
544 | 532 |
545 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { | 533 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
546 int rv; | 534 int rv; |
547 if (addr_family_ == AF_INET) { | 535 if (addr_family_ == AF_INET) { |
548 u_char loop = 0; | 536 u_char loop = 0; |
549 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, | 537 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, |
550 &loop, sizeof(loop)); | 538 &loop, sizeof(loop)); |
551 } else { | 539 } else { |
552 u_int loop = 0; | 540 u_int loop = 0; |
553 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, | 541 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
770 return MapSystemError(errno); | 758 return MapSystemError(errno); |
771 | 759 |
772 return OK; | 760 return OK; |
773 } | 761 } |
774 | 762 |
775 void UDPSocketLibevent::DetachFromThread() { | 763 void UDPSocketLibevent::DetachFromThread() { |
776 base::NonThreadSafe::DetachFromThread(); | 764 base::NonThreadSafe::DetachFromThread(); |
777 } | 765 } |
778 | 766 |
779 } // namespace net | 767 } // namespace net |
OLD | NEW |