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> |
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/logging.h" | 16 #include "base/logging.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "base/metrics/sparse_histogram.h" | 18 #include "base/metrics/sparse_histogram.h" |
19 #include "base/metrics/stats_counters.h" | 19 #include "base/metrics/stats_counters.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/socket/socket_descriptor.h" | 27 #include "net/socket/socket_descriptor.h" |
28 #include "net/udp/udp_net_log_parameters.h" | 28 #include "net/udp/udp_net_log_parameters.h" |
29 | 29 |
30 | |
31 namespace net { | 30 namespace net { |
32 | 31 |
33 namespace { | 32 namespace { |
34 | 33 |
35 const int kBindRetries = 10; | 34 const int kBindRetries = 10; |
36 const int kPortStart = 1024; | 35 const int kPortStart = 1024; |
37 const int kPortEnd = 65535; | 36 const int kPortEnd = 65535; |
38 | 37 |
39 #if defined(OS_MACOSX) | 38 #if defined(OS_MACOSX) |
40 | 39 |
41 // Returns IPv4 address in network order. | 40 // Returns IPv4 address in network order. |
42 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address){ | 41 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address) { |
43 if (!index) { | 42 if (!index) { |
44 *address = htonl(INADDR_ANY); | 43 *address = htonl(INADDR_ANY); |
45 return OK; | 44 return OK; |
46 } | 45 } |
47 ifreq ifr; | 46 ifreq ifr; |
48 ifr.ifr_addr.sa_family = AF_INET; | 47 ifr.ifr_addr.sa_family = AF_INET; |
49 if (!if_indextoname(index, ifr.ifr_name)) | 48 if (!if_indextoname(index, ifr.ifr_name)) |
50 return MapSystemError(errno); | 49 return MapSystemError(errno); |
51 int rv = ioctl(socket, SIOCGIFADDR, &ifr); | 50 int rv = ioctl(socket, SIOCGIFADDR, &ifr); |
52 if (rv == -1) | 51 if (rv == -1) |
53 return MapSystemError(errno); | 52 return MapSystemError(errno); |
54 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; | 53 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; |
55 return OK; | 54 return OK; |
56 } | 55 } |
57 | 56 |
58 #endif // OS_MACOSX | 57 #endif // OS_MACOSX |
59 | 58 |
60 } // namespace | 59 } // namespace |
61 | 60 |
62 UDPSocketLibevent::UDPSocketLibevent( | 61 UDPSocketLibevent::UDPSocketLibevent(DatagramSocket::BindType bind_type, |
63 DatagramSocket::BindType bind_type, | 62 const RandIntCallback& rand_int_cb, |
64 const RandIntCallback& rand_int_cb, | 63 net::NetLog* net_log, |
65 net::NetLog* net_log, | 64 const net::NetLog::Source& source) |
66 const net::NetLog::Source& source) | 65 : socket_(kInvalidSocket), |
67 : socket_(kInvalidSocket), | 66 addr_family_(0), |
68 addr_family_(0), | 67 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
69 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 68 multicast_interface_(0), |
70 multicast_interface_(0), | 69 multicast_time_to_live_(1), |
71 multicast_time_to_live_(1), | 70 bind_type_(bind_type), |
72 bind_type_(bind_type), | 71 rand_int_cb_(rand_int_cb), |
73 rand_int_cb_(rand_int_cb), | 72 read_watcher_(this), |
74 read_watcher_(this), | 73 write_watcher_(this), |
75 write_watcher_(this), | 74 read_buf_len_(0), |
76 read_buf_len_(0), | 75 recv_from_address_(NULL), |
77 recv_from_address_(NULL), | 76 write_buf_len_(0), |
78 write_buf_len_(0), | 77 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
79 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | |
80 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 78 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
81 source.ToEventParametersCallback()); | 79 source.ToEventParametersCallback()); |
82 if (bind_type == DatagramSocket::RANDOM_BIND) | 80 if (bind_type == DatagramSocket::RANDOM_BIND) |
83 DCHECK(!rand_int_cb.is_null()); | 81 DCHECK(!rand_int_cb.is_null()); |
84 } | 82 } |
85 | 83 |
86 UDPSocketLibevent::~UDPSocketLibevent() { | 84 UDPSocketLibevent::~UDPSocketLibevent() { |
87 Close(); | 85 Close(); |
88 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); | 86 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); |
89 } | 87 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 DCHECK(read_callback_.is_null()); | 171 DCHECK(read_callback_.is_null()); |
174 DCHECK(!recv_from_address_); | 172 DCHECK(!recv_from_address_); |
175 DCHECK(!callback.is_null()); // Synchronous operation not supported | 173 DCHECK(!callback.is_null()); // Synchronous operation not supported |
176 DCHECK_GT(buf_len, 0); | 174 DCHECK_GT(buf_len, 0); |
177 | 175 |
178 int nread = InternalRecvFrom(buf, buf_len, address); | 176 int nread = InternalRecvFrom(buf, buf_len, address); |
179 if (nread != ERR_IO_PENDING) | 177 if (nread != ERR_IO_PENDING) |
180 return nread; | 178 return nread; |
181 | 179 |
182 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 180 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
183 socket_, true, base::MessageLoopForIO::WATCH_READ, | 181 socket_, |
184 &read_socket_watcher_, &read_watcher_)) { | 182 true, |
| 183 base::MessageLoopForIO::WATCH_READ, |
| 184 &read_socket_watcher_, |
| 185 &read_watcher_)) { |
185 PLOG(ERROR) << "WatchFileDescriptor failed on read"; | 186 PLOG(ERROR) << "WatchFileDescriptor failed on read"; |
186 int result = MapSystemError(errno); | 187 int result = MapSystemError(errno); |
187 LogRead(result, NULL, 0, NULL); | 188 LogRead(result, NULL, 0, NULL); |
188 return result; | 189 return result; |
189 } | 190 } |
190 | 191 |
191 read_buf_ = buf; | 192 read_buf_ = buf; |
192 read_buf_len_ = buf_len; | 193 read_buf_len_ = buf_len; |
193 recv_from_address_ = address; | 194 recv_from_address_ = address; |
194 read_callback_ = callback; | 195 read_callback_ = callback; |
(...skipping 21 matching lines...) Expand all Loading... |
216 DCHECK_NE(kInvalidSocket, socket_); | 217 DCHECK_NE(kInvalidSocket, socket_); |
217 DCHECK(write_callback_.is_null()); | 218 DCHECK(write_callback_.is_null()); |
218 DCHECK(!callback.is_null()); // Synchronous operation not supported | 219 DCHECK(!callback.is_null()); // Synchronous operation not supported |
219 DCHECK_GT(buf_len, 0); | 220 DCHECK_GT(buf_len, 0); |
220 | 221 |
221 int result = InternalSendTo(buf, buf_len, address); | 222 int result = InternalSendTo(buf, buf_len, address); |
222 if (result != ERR_IO_PENDING) | 223 if (result != ERR_IO_PENDING) |
223 return result; | 224 return result; |
224 | 225 |
225 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( | 226 if (!base::MessageLoopForIO::current()->WatchFileDescriptor( |
226 socket_, true, base::MessageLoopForIO::WATCH_WRITE, | 227 socket_, |
227 &write_socket_watcher_, &write_watcher_)) { | 228 true, |
| 229 base::MessageLoopForIO::WATCH_WRITE, |
| 230 &write_socket_watcher_, |
| 231 &write_watcher_)) { |
228 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; | 232 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; |
229 int result = MapSystemError(errno); | 233 int result = MapSystemError(errno); |
230 LogWrite(result, NULL, NULL); | 234 LogWrite(result, NULL, NULL); |
231 return result; | 235 return result; |
232 } | 236 } |
233 | 237 |
234 write_buf_ = buf; | 238 write_buf_ = buf; |
235 write_buf_len_ = buf_len; | 239 write_buf_len_ = buf_len; |
236 DCHECK(!send_to_address_.get()); | 240 DCHECK(!send_to_address_.get()); |
237 if (address) { | 241 if (address) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 if (rv < 0) { | 314 if (rv < 0) { |
311 Close(); | 315 Close(); |
312 return rv; | 316 return rv; |
313 } | 317 } |
314 local_address_.reset(); | 318 local_address_.reset(); |
315 return rv; | 319 return rv; |
316 } | 320 } |
317 | 321 |
318 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { | 322 int UDPSocketLibevent::SetReceiveBufferSize(int32 size) { |
319 DCHECK(CalledOnValidThread()); | 323 DCHECK(CalledOnValidThread()); |
320 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, | 324 int rv = setsockopt(socket_, |
321 reinterpret_cast<const char*>(&size), sizeof(size)); | 325 SOL_SOCKET, |
| 326 SO_RCVBUF, |
| 327 reinterpret_cast<const char*>(&size), |
| 328 sizeof(size)); |
322 int last_error = errno; | 329 int last_error = errno; |
323 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; | 330 DCHECK(!rv) << "Could not set socket receive buffer size: " << last_error; |
324 return rv == 0 ? OK : MapSystemError(last_error); | 331 return rv == 0 ? OK : MapSystemError(last_error); |
325 } | 332 } |
326 | 333 |
327 int UDPSocketLibevent::SetSendBufferSize(int32 size) { | 334 int UDPSocketLibevent::SetSendBufferSize(int32 size) { |
328 DCHECK(CalledOnValidThread()); | 335 DCHECK(CalledOnValidThread()); |
329 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, | 336 int rv = setsockopt(socket_, |
330 reinterpret_cast<const char*>(&size), sizeof(size)); | 337 SOL_SOCKET, |
| 338 SO_SNDBUF, |
| 339 reinterpret_cast<const char*>(&size), |
| 340 sizeof(size)); |
331 int last_error = errno; | 341 int last_error = errno; |
332 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; | 342 DCHECK(!rv) << "Could not set socket send buffer size: " << last_error; |
333 return rv == 0 ? OK : MapSystemError(last_error); | 343 return rv == 0 ? OK : MapSystemError(last_error); |
334 } | 344 } |
335 | 345 |
336 void UDPSocketLibevent::AllowAddressReuse() { | 346 void UDPSocketLibevent::AllowAddressReuse() { |
337 DCHECK(CalledOnValidThread()); | 347 DCHECK(CalledOnValidThread()); |
338 DCHECK(!is_connected()); | 348 DCHECK(!is_connected()); |
339 | 349 |
340 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; | 350 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); | 408 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); |
399 return; | 409 return; |
400 } | 410 } |
401 | 411 |
402 if (net_log_.IsLogging()) { | 412 if (net_log_.IsLogging()) { |
403 DCHECK(addr_len > 0); | 413 DCHECK(addr_len > 0); |
404 DCHECK(addr); | 414 DCHECK(addr); |
405 | 415 |
406 IPEndPoint address; | 416 IPEndPoint address; |
407 bool is_address_valid = address.FromSockAddr(addr, addr_len); | 417 bool is_address_valid = address.FromSockAddr(addr, addr_len); |
408 net_log_.AddEvent( | 418 net_log_.AddEvent(NetLog::TYPE_UDP_BYTES_RECEIVED, |
409 NetLog::TYPE_UDP_BYTES_RECEIVED, | 419 CreateNetLogUDPDataTranferCallback( |
410 CreateNetLogUDPDataTranferCallback( | 420 result, bytes, is_address_valid ? &address : NULL)); |
411 result, bytes, | |
412 is_address_valid ? &address : NULL)); | |
413 } | 421 } |
414 | 422 |
415 base::StatsCounter read_bytes("udp.read_bytes"); | 423 base::StatsCounter read_bytes("udp.read_bytes"); |
416 read_bytes.Add(result); | 424 read_bytes.Add(result); |
417 } | 425 } |
418 | 426 |
419 int UDPSocketLibevent::CreateSocket(int addr_family) { | 427 int UDPSocketLibevent::CreateSocket(int addr_family) { |
420 addr_family_ = addr_family; | 428 addr_family_ = addr_family; |
421 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); | 429 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0); |
422 if (socket_ == kInvalidSocket) | 430 if (socket_ == kInvalidSocket) |
(...skipping 30 matching lines...) Expand all Loading... |
453 if (net_log_.IsLogging()) { | 461 if (net_log_.IsLogging()) { |
454 net_log_.AddEvent( | 462 net_log_.AddEvent( |
455 NetLog::TYPE_UDP_BYTES_SENT, | 463 NetLog::TYPE_UDP_BYTES_SENT, |
456 CreateNetLogUDPDataTranferCallback(result, bytes, address)); | 464 CreateNetLogUDPDataTranferCallback(result, bytes, address)); |
457 } | 465 } |
458 | 466 |
459 base::StatsCounter write_bytes("udp.write_bytes"); | 467 base::StatsCounter write_bytes("udp.write_bytes"); |
460 write_bytes.Add(result); | 468 write_bytes.Add(result); |
461 } | 469 } |
462 | 470 |
463 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len, | 471 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, |
| 472 int buf_len, |
464 IPEndPoint* address) { | 473 IPEndPoint* address) { |
465 int bytes_transferred; | 474 int bytes_transferred; |
466 int flags = 0; | 475 int flags = 0; |
467 | 476 |
468 SockaddrStorage storage; | 477 SockaddrStorage storage; |
469 | 478 |
470 bytes_transferred = | 479 bytes_transferred = HANDLE_EINTR(recvfrom( |
471 HANDLE_EINTR(recvfrom(socket_, | 480 socket_, buf->data(), buf_len, flags, storage.addr, &storage.addr_len)); |
472 buf->data(), | |
473 buf_len, | |
474 flags, | |
475 storage.addr, | |
476 &storage.addr_len)); | |
477 int result; | 481 int result; |
478 if (bytes_transferred >= 0) { | 482 if (bytes_transferred >= 0) { |
479 result = bytes_transferred; | 483 result = bytes_transferred; |
480 if (address && !address->FromSockAddr(storage.addr, storage.addr_len)) | 484 if (address && !address->FromSockAddr(storage.addr, storage.addr_len)) |
481 result = ERR_ADDRESS_INVALID; | 485 result = ERR_ADDRESS_INVALID; |
482 } else { | 486 } else { |
483 result = MapSystemError(errno); | 487 result = MapSystemError(errno); |
484 } | 488 } |
485 if (result != ERR_IO_PENDING) | 489 if (result != ERR_IO_PENDING) |
486 LogRead(result, buf->data(), storage.addr_len, storage.addr); | 490 LogRead(result, buf->data(), storage.addr_len, storage.addr); |
487 return result; | 491 return result; |
488 } | 492 } |
489 | 493 |
490 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, | 494 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, |
| 495 int buf_len, |
491 const IPEndPoint* address) { | 496 const IPEndPoint* address) { |
492 SockaddrStorage storage; | 497 SockaddrStorage storage; |
493 struct sockaddr* addr = storage.addr; | 498 struct sockaddr* addr = storage.addr; |
494 if (!address) { | 499 if (!address) { |
495 addr = NULL; | 500 addr = NULL; |
496 storage.addr_len = 0; | 501 storage.addr_len = 0; |
497 } else { | 502 } else { |
498 if (!address->ToSockAddr(storage.addr, &storage.addr_len)) { | 503 if (!address->ToSockAddr(storage.addr, &storage.addr_len)) { |
499 int result = ERR_ADDRESS_INVALID; | 504 int result = ERR_ADDRESS_INVALID; |
500 LogWrite(result, NULL, NULL); | 505 LogWrite(result, NULL, NULL); |
501 return result; | 506 return result; |
502 } | 507 } |
503 } | 508 } |
504 | 509 |
505 int result = HANDLE_EINTR(sendto(socket_, | 510 int result = HANDLE_EINTR( |
506 buf->data(), | 511 sendto(socket_, buf->data(), buf_len, 0, addr, storage.addr_len)); |
507 buf_len, | |
508 0, | |
509 addr, | |
510 storage.addr_len)); | |
511 if (result < 0) | 512 if (result < 0) |
512 result = MapSystemError(errno); | 513 result = MapSystemError(errno); |
513 if (result != ERR_IO_PENDING) | 514 if (result != ERR_IO_PENDING) |
514 LogWrite(result, buf->data(), address); | 515 LogWrite(result, buf->data(), address); |
515 return result; | 516 return result; |
516 } | 517 } |
517 | 518 |
518 int UDPSocketLibevent::SetSocketOptions() { | 519 int UDPSocketLibevent::SetSocketOptions() { |
519 int true_value = 1; | 520 int true_value = 1; |
520 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { | 521 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { |
521 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, | 522 int rv = setsockopt( |
522 sizeof(true_value)); | 523 socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value)); |
523 if (rv < 0) | 524 if (rv < 0) |
524 return MapSystemError(errno); | 525 return MapSystemError(errno); |
525 } | 526 } |
526 if (socket_options_ & SOCKET_OPTION_BROADCAST) { | 527 if (socket_options_ & SOCKET_OPTION_BROADCAST) { |
527 int rv; | 528 int rv; |
528 #if defined(OS_MACOSX) | 529 #if defined(OS_MACOSX) |
529 // SO_REUSEPORT on OSX permits multiple processes to each receive | 530 // SO_REUSEPORT on OSX permits multiple processes to each receive |
530 // UDP multicast or broadcast datagrams destined for the bound | 531 // UDP multicast or broadcast datagrams destined for the bound |
531 // port. | 532 // port. |
532 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, | 533 rv = setsockopt( |
533 sizeof(true_value)); | 534 socket_, SOL_SOCKET, SO_REUSEPORT, &true_value, sizeof(true_value)); |
534 #else | 535 #else |
535 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &true_value, | 536 rv = setsockopt( |
536 sizeof(true_value)); | 537 socket_, SOL_SOCKET, SO_BROADCAST, &true_value, sizeof(true_value)); |
537 #endif // defined(OS_MACOSX) | 538 #endif // defined(OS_MACOSX) |
538 if (rv < 0) | 539 if (rv < 0) |
539 return MapSystemError(errno); | 540 return MapSystemError(errno); |
540 } | 541 } |
541 | 542 |
542 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { | 543 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { |
543 int rv; | 544 int rv; |
544 if (addr_family_ == AF_INET) { | 545 if (addr_family_ == AF_INET) { |
545 u_char loop = 0; | 546 u_char loop = 0; |
546 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, | 547 rv = setsockopt( |
547 &loop, sizeof(loop)); | 548 socket_, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)); |
548 } else { | 549 } else { |
549 u_int loop = 0; | 550 u_int loop = 0; |
550 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, | 551 rv = setsockopt( |
551 &loop, sizeof(loop)); | 552 socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &loop, sizeof(loop)); |
552 } | 553 } |
553 if (rv < 0) | 554 if (rv < 0) |
554 return MapSystemError(errno); | 555 return MapSystemError(errno); |
555 } | 556 } |
556 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { | 557 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { |
557 int rv; | 558 int rv; |
558 if (addr_family_ == AF_INET) { | 559 if (addr_family_ == AF_INET) { |
559 u_char ttl = multicast_time_to_live_; | 560 u_char ttl = multicast_time_to_live_; |
560 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, | 561 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); |
561 &ttl, sizeof(ttl)); | |
562 } else { | 562 } else { |
563 // Signed integer. -1 to use route default. | 563 // Signed integer. -1 to use route default. |
564 int ttl = multicast_time_to_live_; | 564 int ttl = multicast_time_to_live_; |
565 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, | 565 rv = setsockopt( |
566 &ttl, sizeof(ttl)); | 566 socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)); |
567 } | 567 } |
568 if (rv < 0) | 568 if (rv < 0) |
569 return MapSystemError(errno); | 569 return MapSystemError(errno); |
570 } | 570 } |
571 if (multicast_interface_ != 0) { | 571 if (multicast_interface_ != 0) { |
572 switch (addr_family_) { | 572 switch (addr_family_) { |
573 case AF_INET: { | 573 case AF_INET: { |
574 #if !defined(OS_MACOSX) | 574 #if !defined(OS_MACOSX) |
575 ip_mreqn mreq; | 575 ip_mreqn mreq; |
576 mreq.imr_ifindex = multicast_interface_; | 576 mreq.imr_ifindex = multicast_interface_; |
577 mreq.imr_address.s_addr = htonl(INADDR_ANY); | 577 mreq.imr_address.s_addr = htonl(INADDR_ANY); |
578 #else | 578 #else |
579 ip_mreq mreq; | 579 ip_mreq mreq; |
580 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, | 580 int error = GetIPv4AddressFromIndex( |
581 &mreq.imr_interface.s_addr); | 581 socket_, multicast_interface_, &mreq.imr_interface.s_addr); |
582 if (error != OK) | 582 if (error != OK) |
583 return error; | 583 return error; |
584 #endif | 584 #endif |
585 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, | 585 int rv = setsockopt(socket_, |
586 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); | 586 IPPROTO_IP, |
| 587 IP_MULTICAST_IF, |
| 588 reinterpret_cast<const char*>(&mreq), |
| 589 sizeof(mreq)); |
587 if (rv) | 590 if (rv) |
588 return MapSystemError(errno); | 591 return MapSystemError(errno); |
589 break; | 592 break; |
590 } | 593 } |
591 case AF_INET6: { | 594 case AF_INET6: { |
592 uint32 interface_index = multicast_interface_; | 595 uint32 interface_index = multicast_interface_; |
593 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, | 596 int rv = setsockopt(socket_, |
| 597 IPPROTO_IPV6, |
| 598 IPV6_MULTICAST_IF, |
594 reinterpret_cast<const char*>(&interface_index), | 599 reinterpret_cast<const char*>(&interface_index), |
595 sizeof(interface_index)); | 600 sizeof(interface_index)); |
596 if (rv) | 601 if (rv) |
597 return MapSystemError(errno); | 602 return MapSystemError(errno); |
598 break; | 603 break; |
599 } | 604 } |
600 default: | 605 default: |
601 NOTREACHED() << "Invalid address family"; | 606 NOTREACHED() << "Invalid address family"; |
602 return ERR_ADDRESS_INVALID; | 607 return ERR_ADDRESS_INVALID; |
603 } | 608 } |
(...skipping 17 matching lines...) Expand all Loading... |
621 if (last_error == EADDRNOTAVAIL) | 626 if (last_error == EADDRNOTAVAIL) |
622 return ERR_ADDRESS_IN_USE; | 627 return ERR_ADDRESS_IN_USE; |
623 #endif | 628 #endif |
624 return MapSystemError(last_error); | 629 return MapSystemError(last_error); |
625 } | 630 } |
626 | 631 |
627 int UDPSocketLibevent::RandomBind(const IPAddressNumber& address) { | 632 int UDPSocketLibevent::RandomBind(const IPAddressNumber& address) { |
628 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); | 633 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); |
629 | 634 |
630 for (int i = 0; i < kBindRetries; ++i) { | 635 for (int i = 0; i < kBindRetries; ++i) { |
631 int rv = DoBind(IPEndPoint(address, | 636 int rv = |
632 rand_int_cb_.Run(kPortStart, kPortEnd))); | 637 DoBind(IPEndPoint(address, rand_int_cb_.Run(kPortStart, kPortEnd))); |
633 if (rv == OK || rv != ERR_ADDRESS_IN_USE) | 638 if (rv == OK || rv != ERR_ADDRESS_IN_USE) |
634 return rv; | 639 return rv; |
635 } | 640 } |
636 return DoBind(IPEndPoint(address, 0)); | 641 return DoBind(IPEndPoint(address, 0)); |
637 } | 642 } |
638 | 643 |
639 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { | 644 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { |
640 DCHECK(CalledOnValidThread()); | 645 DCHECK(CalledOnValidThread()); |
641 if (!is_connected()) | 646 if (!is_connected()) |
642 return ERR_SOCKET_NOT_CONNECTED; | 647 return ERR_SOCKET_NOT_CONNECTED; |
643 | 648 |
644 switch (group_address.size()) { | 649 switch (group_address.size()) { |
645 case kIPv4AddressSize: { | 650 case kIPv4AddressSize: { |
646 if (addr_family_ != AF_INET) | 651 if (addr_family_ != AF_INET) |
647 return ERR_ADDRESS_INVALID; | 652 return ERR_ADDRESS_INVALID; |
648 | 653 |
649 #if !defined(OS_MACOSX) | 654 #if !defined(OS_MACOSX) |
650 ip_mreqn mreq; | 655 ip_mreqn mreq; |
651 mreq.imr_ifindex = multicast_interface_; | 656 mreq.imr_ifindex = multicast_interface_; |
652 mreq.imr_address.s_addr = htonl(INADDR_ANY); | 657 mreq.imr_address.s_addr = htonl(INADDR_ANY); |
653 #else | 658 #else |
654 ip_mreq mreq; | 659 ip_mreq mreq; |
655 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, | 660 int error = GetIPv4AddressFromIndex( |
656 &mreq.imr_interface.s_addr); | 661 socket_, multicast_interface_, &mreq.imr_interface.s_addr); |
657 if (error != OK) | 662 if (error != OK) |
658 return error; | 663 return error; |
659 #endif | 664 #endif |
660 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 665 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
661 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | 666 int rv = setsockopt( |
662 &mreq, sizeof(mreq)); | 667 socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); |
663 if (rv < 0) | 668 if (rv < 0) |
664 return MapSystemError(errno); | 669 return MapSystemError(errno); |
665 return OK; | 670 return OK; |
666 } | 671 } |
667 case kIPv6AddressSize: { | 672 case kIPv6AddressSize: { |
668 if (addr_family_ != AF_INET6) | 673 if (addr_family_ != AF_INET6) |
669 return ERR_ADDRESS_INVALID; | 674 return ERR_ADDRESS_INVALID; |
670 ipv6_mreq mreq; | 675 ipv6_mreq mreq; |
671 mreq.ipv6mr_interface = multicast_interface_; | 676 mreq.ipv6mr_interface = multicast_interface_; |
672 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 677 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
673 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, | 678 int rv = setsockopt( |
674 &mreq, sizeof(mreq)); | 679 socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); |
675 if (rv < 0) | 680 if (rv < 0) |
676 return MapSystemError(errno); | 681 return MapSystemError(errno); |
677 return OK; | 682 return OK; |
678 } | 683 } |
679 default: | 684 default: |
680 NOTREACHED() << "Invalid address family"; | 685 NOTREACHED() << "Invalid address family"; |
681 return ERR_ADDRESS_INVALID; | 686 return ERR_ADDRESS_INVALID; |
682 } | 687 } |
683 } | 688 } |
684 | 689 |
685 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const { | 690 int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const { |
686 DCHECK(CalledOnValidThread()); | 691 DCHECK(CalledOnValidThread()); |
687 | 692 |
688 if (!is_connected()) | 693 if (!is_connected()) |
689 return ERR_SOCKET_NOT_CONNECTED; | 694 return ERR_SOCKET_NOT_CONNECTED; |
690 | 695 |
691 switch (group_address.size()) { | 696 switch (group_address.size()) { |
692 case kIPv4AddressSize: { | 697 case kIPv4AddressSize: { |
693 if (addr_family_ != AF_INET) | 698 if (addr_family_ != AF_INET) |
694 return ERR_ADDRESS_INVALID; | 699 return ERR_ADDRESS_INVALID; |
695 ip_mreq mreq; | 700 ip_mreq mreq; |
696 mreq.imr_interface.s_addr = INADDR_ANY; | 701 mreq.imr_interface.s_addr = INADDR_ANY; |
697 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 702 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
698 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, | 703 int rv = setsockopt( |
699 &mreq, sizeof(mreq)); | 704 socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); |
700 if (rv < 0) | 705 if (rv < 0) |
701 return MapSystemError(errno); | 706 return MapSystemError(errno); |
702 return OK; | 707 return OK; |
703 } | 708 } |
704 case kIPv6AddressSize: { | 709 case kIPv6AddressSize: { |
705 if (addr_family_ != AF_INET6) | 710 if (addr_family_ != AF_INET6) |
706 return ERR_ADDRESS_INVALID; | 711 return ERR_ADDRESS_INVALID; |
707 ipv6_mreq mreq; | 712 ipv6_mreq mreq; |
708 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 713 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. |
709 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 714 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
710 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP, | 715 int rv = setsockopt( |
711 &mreq, sizeof(mreq)); | 716 socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)); |
712 if (rv < 0) | 717 if (rv < 0) |
713 return MapSystemError(errno); | 718 return MapSystemError(errno); |
714 return OK; | 719 return OK; |
715 } | 720 } |
716 default: | 721 default: |
717 NOTREACHED() << "Invalid address family"; | 722 NOTREACHED() << "Invalid address family"; |
718 return ERR_ADDRESS_INVALID; | 723 return ERR_ADDRESS_INVALID; |
719 } | 724 } |
720 } | 725 } |
721 | 726 |
(...skipping 28 matching lines...) Expand all Loading... |
750 return OK; | 755 return OK; |
751 } | 756 } |
752 | 757 |
753 int UDPSocketLibevent::SetDiffServCodePoint(DiffServCodePoint dscp) { | 758 int UDPSocketLibevent::SetDiffServCodePoint(DiffServCodePoint dscp) { |
754 if (dscp == DSCP_NO_CHANGE) { | 759 if (dscp == DSCP_NO_CHANGE) { |
755 return OK; | 760 return OK; |
756 } | 761 } |
757 int rv; | 762 int rv; |
758 int dscp_and_ecn = dscp << 2; | 763 int dscp_and_ecn = dscp << 2; |
759 if (addr_family_ == AF_INET) { | 764 if (addr_family_ == AF_INET) { |
760 rv = setsockopt(socket_, IPPROTO_IP, IP_TOS, | 765 rv = setsockopt( |
761 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 766 socket_, IPPROTO_IP, IP_TOS, &dscp_and_ecn, sizeof(dscp_and_ecn)); |
762 } else { | 767 } else { |
763 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, | 768 rv = setsockopt(socket_, |
764 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 769 IPPROTO_IPV6, |
| 770 IPV6_TCLASS, |
| 771 &dscp_and_ecn, |
| 772 sizeof(dscp_and_ecn)); |
765 } | 773 } |
766 if (rv < 0) | 774 if (rv < 0) |
767 return MapSystemError(errno); | 775 return MapSystemError(errno); |
768 | 776 |
769 return OK; | 777 return OK; |
770 } | 778 } |
771 | 779 |
772 void UDPSocketLibevent::DetachFromThread() { | 780 void UDPSocketLibevent::DetachFromThread() { |
773 base::NonThreadSafe::DetachFromThread(); | 781 base::NonThreadSafe::DetachFromThread(); |
774 } | 782 } |
775 | 783 |
776 } // namespace net | 784 } // namespace net |
OLD | NEW |