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 <netdb.h> | 9 #include <netdb.h> |
| 10 #include <net/if.h> | |
| 11 #include <netinet/in.h> | |
| 12 #include <sys/ioctl.h> | |
| 10 #include <sys/socket.h> | 13 #include <sys/socket.h> |
| 11 #include <netinet/in.h> | |
| 12 | 14 |
| 13 #include "base/callback.h" | 15 #include "base/callback.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 16 #include "base/metrics/stats_counters.h" | 18 #include "base/metrics/stats_counters.h" |
| 17 #include "base/posix/eintr_wrapper.h" | 19 #include "base/posix/eintr_wrapper.h" |
| 18 #include "base/rand_util.h" | 20 #include "base/rand_util.h" |
| 19 #include "net/base/io_buffer.h" | 21 #include "net/base/io_buffer.h" |
| 20 #include "net/base/ip_endpoint.h" | 22 #include "net/base/ip_endpoint.h" |
| 21 #include "net/base/net_errors.h" | 23 #include "net/base/net_errors.h" |
| 22 #include "net/base/net_log.h" | 24 #include "net/base/net_log.h" |
| 23 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
| 24 #include "net/socket/socket_descriptor.h" | 26 #include "net/socket/socket_descriptor.h" |
| 25 #include "net/udp/udp_net_log_parameters.h" | 27 #include "net/udp/udp_net_log_parameters.h" |
| 26 | 28 |
| 27 namespace { | 29 namespace { |
| 28 | 30 |
| 29 const int kBindRetries = 10; | 31 const int kBindRetries = 10; |
| 30 const int kPortStart = 1024; | 32 const int kPortStart = 1024; |
| 31 const int kPortEnd = 65535; | 33 const int kPortEnd = 65535; |
| 32 | 34 |
| 35 #if defined(OS_MACOSX) | |
| 36 uint32 GetIPv4AddressFromIndex(int socket, uint32 index){ | |
|
szym
2013/12/04 00:52:15
Add comment:
// Returns IPv4 address in network or
Vitaly Buka (NO REVIEWS)
2013/12/04 09:39:36
Done.
| |
| 37 if (!index) | |
| 38 return htonl(INADDR_ANY); | |
| 39 ifreq ifr; | |
| 40 ifr.ifr_addr.sa_family = AF_INET; | |
| 41 if (!if_indextoname(index, ifr.ifr_name)) | |
| 42 return htonl(INADDR_ANY); | |
| 43 if (ioctl(socket, SIOCGIFADDR, &ifr)) | |
| 44 return htonl(INADDR_ANY); | |
|
szym
2013/12/04 00:52:15
I am a bit concerned about this failure mode.
If
Vitaly Buka (NO REVIEWS)
2013/12/04 01:00:49
For current use-cases returning error is not a pro
Vitaly Buka (NO REVIEWS)
2013/12/04 09:39:36
Done.
| |
| 45 return reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; | |
| 46 } | |
| 47 #endif // OS_MACOSX | |
| 48 | |
| 33 } // namespace | 49 } // namespace |
| 34 | 50 |
| 35 namespace net { | 51 namespace net { |
| 36 | 52 |
| 37 UDPSocketLibevent::UDPSocketLibevent( | 53 UDPSocketLibevent::UDPSocketLibevent( |
| 38 DatagramSocket::BindType bind_type, | 54 DatagramSocket::BindType bind_type, |
| 39 const RandIntCallback& rand_int_cb, | 55 const RandIntCallback& rand_int_cb, |
| 40 net::NetLog* net_log, | 56 net::NetLog* net_log, |
| 41 const net::NetLog::Source& source) | 57 const net::NetLog::Source& source) |
| 42 : socket_(kInvalidSocket), | 58 : socket_(kInvalidSocket), |
| 43 addr_family_(0), | 59 addr_family_(0), |
| 44 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 60 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| 61 multicast_interface_(0), | |
| 45 multicast_time_to_live_(1), | 62 multicast_time_to_live_(1), |
| 46 bind_type_(bind_type), | 63 bind_type_(bind_type), |
| 47 rand_int_cb_(rand_int_cb), | 64 rand_int_cb_(rand_int_cb), |
| 48 read_watcher_(this), | 65 read_watcher_(this), |
| 49 write_watcher_(this), | 66 write_watcher_(this), |
| 50 read_buf_len_(0), | 67 read_buf_len_(0), |
| 51 recv_from_address_(NULL), | 68 recv_from_address_(NULL), |
| 52 write_buf_len_(0), | 69 write_buf_len_(0), |
| 53 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 70 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
| 54 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 71 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 if (rv < 0) | 534 if (rv < 0) |
| 518 return MapSystemError(errno); | 535 return MapSystemError(errno); |
| 519 } | 536 } |
| 520 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { | 537 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { |
| 521 int rv; | 538 int rv; |
| 522 if (addr_family_ == AF_INET) { | 539 if (addr_family_ == AF_INET) { |
| 523 u_char ttl = multicast_time_to_live_; | 540 u_char ttl = multicast_time_to_live_; |
| 524 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, | 541 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, |
| 525 &ttl, sizeof(ttl)); | 542 &ttl, sizeof(ttl)); |
| 526 } else { | 543 } else { |
| 527 // Signed interger. -1 to use route default. | 544 // Signed integer. -1 to use route default. |
| 528 int ttl = multicast_time_to_live_; | 545 int ttl = multicast_time_to_live_; |
| 529 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, | 546 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, |
| 530 &ttl, sizeof(ttl)); | 547 &ttl, sizeof(ttl)); |
| 531 } | 548 } |
| 532 if (rv < 0) | 549 if (rv < 0) |
| 533 return MapSystemError(errno); | 550 return MapSystemError(errno); |
| 534 } | 551 } |
| 552 if (multicast_interface_ != 0) { | |
| 553 switch (addr_family_) { | |
| 554 case AF_INET: { | |
| 555 #if !defined(OS_MACOSX) | |
| 556 ip_mreqn mreq; | |
| 557 mreq.imr_ifindex = multicast_interface_; | |
| 558 mreq.imr_address.s_addr = htonl(INADDR_ANY); | |
| 559 #else | |
| 560 ip_mreq mreq; | |
| 561 mreq.imr_interface.s_addr = | |
| 562 GetIPv4AddressFromIndex(socket_, multicast_interface_); | |
| 563 #endif | |
| 564 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, | |
| 565 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); | |
| 566 if (rv) | |
| 567 return MapSystemError(errno); | |
| 568 break; | |
| 569 } | |
| 570 case AF_INET6: { | |
| 571 uint32 interface_index = multicast_interface_; | |
| 572 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, | |
| 573 reinterpret_cast<const char*>(&interface_index), | |
| 574 sizeof(interface_index)); | |
| 575 if (rv) | |
| 576 return MapSystemError(errno); | |
| 577 break; | |
| 578 } | |
| 579 default: | |
| 580 NOTREACHED() << "Invalid address family"; | |
| 581 return ERR_ADDRESS_INVALID; | |
| 582 } | |
| 583 } | |
| 535 return OK; | 584 return OK; |
| 536 } | 585 } |
| 537 | 586 |
| 538 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { | 587 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { |
| 539 SockaddrStorage storage; | 588 SockaddrStorage storage; |
| 540 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 589 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
| 541 return ERR_ADDRESS_INVALID; | 590 return ERR_ADDRESS_INVALID; |
| 542 int rv = bind(socket_, storage.addr, storage.addr_len); | 591 int rv = bind(socket_, storage.addr, storage.addr_len); |
| 543 return rv < 0 ? MapSystemError(errno) : rv; | 592 return rv < 0 ? MapSystemError(errno) : rv; |
| 544 } | 593 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 559 | 608 |
| 560 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { | 609 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { |
| 561 DCHECK(CalledOnValidThread()); | 610 DCHECK(CalledOnValidThread()); |
| 562 if (!is_connected()) | 611 if (!is_connected()) |
| 563 return ERR_SOCKET_NOT_CONNECTED; | 612 return ERR_SOCKET_NOT_CONNECTED; |
| 564 | 613 |
| 565 switch (group_address.size()) { | 614 switch (group_address.size()) { |
| 566 case kIPv4AddressSize: { | 615 case kIPv4AddressSize: { |
| 567 if (addr_family_ != AF_INET) | 616 if (addr_family_ != AF_INET) |
| 568 return ERR_ADDRESS_INVALID; | 617 return ERR_ADDRESS_INVALID; |
| 618 | |
| 619 #if !defined(OS_MACOSX) | |
| 620 ip_mreqn mreq; | |
| 621 mreq.imr_ifindex = multicast_interface_; | |
| 622 mreq.imr_address.s_addr = htonl(INADDR_ANY); | |
| 623 #else | |
| 569 ip_mreq mreq; | 624 ip_mreq mreq; |
| 570 mreq.imr_interface.s_addr = INADDR_ANY; | 625 mreq.imr_interface.s_addr = |
| 626 GetIPv4AddressFromIndex(socket_, multicast_interface_); | |
| 627 #endif | |
| 571 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 628 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
| 572 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | 629 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
| 573 &mreq, sizeof(mreq)); | 630 &mreq, sizeof(mreq)); |
| 574 if (rv < 0) | 631 if (rv < 0) |
| 575 return MapSystemError(errno); | 632 return MapSystemError(errno); |
| 576 return OK; | 633 return OK; |
| 577 } | 634 } |
| 578 case kIPv6AddressSize: { | 635 case kIPv6AddressSize: { |
| 579 if (addr_family_ != AF_INET6) | 636 if (addr_family_ != AF_INET6) |
| 580 return ERR_ADDRESS_INVALID; | 637 return ERR_ADDRESS_INVALID; |
| 581 ipv6_mreq mreq; | 638 ipv6_mreq mreq; |
| 582 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 639 mreq.ipv6mr_interface = multicast_interface_; |
| 583 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 640 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
| 584 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, | 641 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, |
| 585 &mreq, sizeof(mreq)); | 642 &mreq, sizeof(mreq)); |
| 586 if (rv < 0) | 643 if (rv < 0) |
| 587 return MapSystemError(errno); | 644 return MapSystemError(errno); |
| 588 return OK; | 645 return OK; |
| 589 } | 646 } |
| 590 default: | 647 default: |
| 591 NOTREACHED() << "Invalid address family"; | 648 NOTREACHED() << "Invalid address family"; |
| 592 return ERR_ADDRESS_INVALID; | 649 return ERR_ADDRESS_INVALID; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 623 if (rv < 0) | 680 if (rv < 0) |
| 624 return MapSystemError(errno); | 681 return MapSystemError(errno); |
| 625 return OK; | 682 return OK; |
| 626 } | 683 } |
| 627 default: | 684 default: |
| 628 NOTREACHED() << "Invalid address family"; | 685 NOTREACHED() << "Invalid address family"; |
| 629 return ERR_ADDRESS_INVALID; | 686 return ERR_ADDRESS_INVALID; |
| 630 } | 687 } |
| 631 } | 688 } |
| 632 | 689 |
| 690 int UDPSocketLibevent::SetMulticastInterface(uint32 interface_index) { | |
| 691 DCHECK(CalledOnValidThread()); | |
| 692 if (is_connected()) | |
| 693 return ERR_SOCKET_IS_CONNECTED; | |
| 694 multicast_interface_ = interface_index; | |
| 695 return OK; | |
| 696 } | |
| 697 | |
| 633 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) { | 698 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) { |
| 634 DCHECK(CalledOnValidThread()); | 699 DCHECK(CalledOnValidThread()); |
| 635 if (is_connected()) | 700 if (is_connected()) |
| 636 return ERR_SOCKET_IS_CONNECTED; | 701 return ERR_SOCKET_IS_CONNECTED; |
| 637 | 702 |
| 638 if (time_to_live < 0 || time_to_live > 255) | 703 if (time_to_live < 0 || time_to_live > 255) |
| 639 return ERR_INVALID_ARGUMENT; | 704 return ERR_INVALID_ARGUMENT; |
| 640 multicast_time_to_live_ = time_to_live; | 705 multicast_time_to_live_ = time_to_live; |
| 641 return OK; | 706 return OK; |
| 642 } | 707 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 666 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, | 731 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, |
| 667 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 732 &dscp_and_ecn, sizeof(dscp_and_ecn)); |
| 668 } | 733 } |
| 669 if (rv < 0) | 734 if (rv < 0) |
| 670 return MapSystemError(errno); | 735 return MapSystemError(errno); |
| 671 | 736 |
| 672 return OK; | 737 return OK; |
| 673 } | 738 } |
| 674 | 739 |
| 675 } // namespace net | 740 } // namespace net |
| OLD | NEW |