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 |
| 29 |
| 30 namespace net { |
| 31 |
27 namespace { | 32 namespace { |
28 | 33 |
29 const int kBindRetries = 10; | 34 const int kBindRetries = 10; |
30 const int kPortStart = 1024; | 35 const int kPortStart = 1024; |
31 const int kPortEnd = 65535; | 36 const int kPortEnd = 65535; |
32 | 37 |
| 38 #if defined(OS_MACOSX) |
| 39 |
| 40 // Returns IPv4 address in network order. |
| 41 int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address){ |
| 42 if (!index) { |
| 43 *address = htonl(INADDR_ANY); |
| 44 return OK; |
| 45 } |
| 46 ifreq ifr; |
| 47 ifr.ifr_addr.sa_family = AF_INET; |
| 48 if (!if_indextoname(index, ifr.ifr_name)) |
| 49 return ERR_FAILED; |
| 50 int rv = ioctl(socket, SIOCGIFADDR, &ifr); |
| 51 if (!rv) |
| 52 return MapSystemError(rv); |
| 53 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr; |
| 54 return OK; |
| 55 } |
| 56 |
| 57 #endif // OS_MACOSX |
| 58 |
33 } // namespace | 59 } // namespace |
34 | 60 |
35 namespace net { | |
36 | |
37 UDPSocketLibevent::UDPSocketLibevent( | 61 UDPSocketLibevent::UDPSocketLibevent( |
38 DatagramSocket::BindType bind_type, | 62 DatagramSocket::BindType bind_type, |
39 const RandIntCallback& rand_int_cb, | 63 const RandIntCallback& rand_int_cb, |
40 net::NetLog* net_log, | 64 net::NetLog* net_log, |
41 const net::NetLog::Source& source) | 65 const net::NetLog::Source& source) |
42 : socket_(kInvalidSocket), | 66 : socket_(kInvalidSocket), |
43 addr_family_(0), | 67 addr_family_(0), |
44 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 68 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| 69 multicast_interface_(0), |
45 multicast_time_to_live_(1), | 70 multicast_time_to_live_(1), |
46 bind_type_(bind_type), | 71 bind_type_(bind_type), |
47 rand_int_cb_(rand_int_cb), | 72 rand_int_cb_(rand_int_cb), |
48 read_watcher_(this), | 73 read_watcher_(this), |
49 write_watcher_(this), | 74 write_watcher_(this), |
50 read_buf_len_(0), | 75 read_buf_len_(0), |
51 recv_from_address_(NULL), | 76 recv_from_address_(NULL), |
52 write_buf_len_(0), | 77 write_buf_len_(0), |
53 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 78 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
54 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 79 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 if (rv < 0) | 542 if (rv < 0) |
518 return MapSystemError(errno); | 543 return MapSystemError(errno); |
519 } | 544 } |
520 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { | 545 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) { |
521 int rv; | 546 int rv; |
522 if (addr_family_ == AF_INET) { | 547 if (addr_family_ == AF_INET) { |
523 u_char ttl = multicast_time_to_live_; | 548 u_char ttl = multicast_time_to_live_; |
524 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, | 549 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL, |
525 &ttl, sizeof(ttl)); | 550 &ttl, sizeof(ttl)); |
526 } else { | 551 } else { |
527 // Signed interger. -1 to use route default. | 552 // Signed integer. -1 to use route default. |
528 int ttl = multicast_time_to_live_; | 553 int ttl = multicast_time_to_live_; |
529 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, | 554 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, |
530 &ttl, sizeof(ttl)); | 555 &ttl, sizeof(ttl)); |
531 } | 556 } |
532 if (rv < 0) | 557 if (rv < 0) |
533 return MapSystemError(errno); | 558 return MapSystemError(errno); |
534 } | 559 } |
| 560 if (multicast_interface_ != 0) { |
| 561 switch (addr_family_) { |
| 562 case AF_INET: { |
| 563 #if !defined(OS_MACOSX) |
| 564 ip_mreqn mreq; |
| 565 mreq.imr_ifindex = multicast_interface_; |
| 566 mreq.imr_address.s_addr = htonl(INADDR_ANY); |
| 567 #else |
| 568 ip_mreq mreq; |
| 569 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, |
| 570 &mreq.imr_interface.s_addr); |
| 571 if (error != OK) |
| 572 return error; |
| 573 #endif |
| 574 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, |
| 575 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); |
| 576 if (rv) |
| 577 return MapSystemError(errno); |
| 578 break; |
| 579 } |
| 580 case AF_INET6: { |
| 581 uint32 interface_index = multicast_interface_; |
| 582 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, |
| 583 reinterpret_cast<const char*>(&interface_index), |
| 584 sizeof(interface_index)); |
| 585 if (rv) |
| 586 return MapSystemError(errno); |
| 587 break; |
| 588 } |
| 589 default: |
| 590 NOTREACHED() << "Invalid address family"; |
| 591 return ERR_ADDRESS_INVALID; |
| 592 } |
| 593 } |
535 return OK; | 594 return OK; |
536 } | 595 } |
537 | 596 |
538 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { | 597 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { |
539 SockaddrStorage storage; | 598 SockaddrStorage storage; |
540 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 599 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
541 return ERR_ADDRESS_INVALID; | 600 return ERR_ADDRESS_INVALID; |
542 int rv = bind(socket_, storage.addr, storage.addr_len); | 601 int rv = bind(socket_, storage.addr, storage.addr_len); |
543 return rv < 0 ? MapSystemError(errno) : rv; | 602 return rv < 0 ? MapSystemError(errno) : rv; |
544 } | 603 } |
(...skipping 14 matching lines...) Expand all Loading... |
559 | 618 |
560 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { | 619 int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const { |
561 DCHECK(CalledOnValidThread()); | 620 DCHECK(CalledOnValidThread()); |
562 if (!is_connected()) | 621 if (!is_connected()) |
563 return ERR_SOCKET_NOT_CONNECTED; | 622 return ERR_SOCKET_NOT_CONNECTED; |
564 | 623 |
565 switch (group_address.size()) { | 624 switch (group_address.size()) { |
566 case kIPv4AddressSize: { | 625 case kIPv4AddressSize: { |
567 if (addr_family_ != AF_INET) | 626 if (addr_family_ != AF_INET) |
568 return ERR_ADDRESS_INVALID; | 627 return ERR_ADDRESS_INVALID; |
| 628 |
| 629 #if !defined(OS_MACOSX) |
| 630 ip_mreqn mreq; |
| 631 mreq.imr_ifindex = multicast_interface_; |
| 632 mreq.imr_address.s_addr = htonl(INADDR_ANY); |
| 633 #else |
569 ip_mreq mreq; | 634 ip_mreq mreq; |
570 mreq.imr_interface.s_addr = INADDR_ANY; | 635 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_, |
| 636 &mreq.imr_interface.s_addr); |
| 637 if (error != OK) |
| 638 return error; |
| 639 #endif |
571 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 640 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
572 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | 641 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
573 &mreq, sizeof(mreq)); | 642 &mreq, sizeof(mreq)); |
574 if (rv < 0) | 643 if (rv < 0) |
575 return MapSystemError(errno); | 644 return MapSystemError(errno); |
576 return OK; | 645 return OK; |
577 } | 646 } |
578 case kIPv6AddressSize: { | 647 case kIPv6AddressSize: { |
579 if (addr_family_ != AF_INET6) | 648 if (addr_family_ != AF_INET6) |
580 return ERR_ADDRESS_INVALID; | 649 return ERR_ADDRESS_INVALID; |
581 ipv6_mreq mreq; | 650 ipv6_mreq mreq; |
582 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 651 mreq.ipv6mr_interface = multicast_interface_; |
583 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 652 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
584 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, | 653 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP, |
585 &mreq, sizeof(mreq)); | 654 &mreq, sizeof(mreq)); |
586 if (rv < 0) | 655 if (rv < 0) |
587 return MapSystemError(errno); | 656 return MapSystemError(errno); |
588 return OK; | 657 return OK; |
589 } | 658 } |
590 default: | 659 default: |
591 NOTREACHED() << "Invalid address family"; | 660 NOTREACHED() << "Invalid address family"; |
592 return ERR_ADDRESS_INVALID; | 661 return ERR_ADDRESS_INVALID; |
(...skipping 30 matching lines...) Expand all Loading... |
623 if (rv < 0) | 692 if (rv < 0) |
624 return MapSystemError(errno); | 693 return MapSystemError(errno); |
625 return OK; | 694 return OK; |
626 } | 695 } |
627 default: | 696 default: |
628 NOTREACHED() << "Invalid address family"; | 697 NOTREACHED() << "Invalid address family"; |
629 return ERR_ADDRESS_INVALID; | 698 return ERR_ADDRESS_INVALID; |
630 } | 699 } |
631 } | 700 } |
632 | 701 |
| 702 int UDPSocketLibevent::SetMulticastInterface(uint32 interface_index) { |
| 703 DCHECK(CalledOnValidThread()); |
| 704 if (is_connected()) |
| 705 return ERR_SOCKET_IS_CONNECTED; |
| 706 multicast_interface_ = interface_index; |
| 707 return OK; |
| 708 } |
| 709 |
633 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) { | 710 int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) { |
634 DCHECK(CalledOnValidThread()); | 711 DCHECK(CalledOnValidThread()); |
635 if (is_connected()) | 712 if (is_connected()) |
636 return ERR_SOCKET_IS_CONNECTED; | 713 return ERR_SOCKET_IS_CONNECTED; |
637 | 714 |
638 if (time_to_live < 0 || time_to_live > 255) | 715 if (time_to_live < 0 || time_to_live > 255) |
639 return ERR_INVALID_ARGUMENT; | 716 return ERR_INVALID_ARGUMENT; |
640 multicast_time_to_live_ = time_to_live; | 717 multicast_time_to_live_ = time_to_live; |
641 return OK; | 718 return OK; |
642 } | 719 } |
(...skipping 23 matching lines...) Expand all Loading... |
666 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, | 743 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, |
667 &dscp_and_ecn, sizeof(dscp_and_ecn)); | 744 &dscp_and_ecn, sizeof(dscp_and_ecn)); |
668 } | 745 } |
669 if (rv < 0) | 746 if (rv < 0) |
670 return MapSystemError(errno); | 747 return MapSystemError(errno); |
671 | 748 |
672 return OK; | 749 return OK; |
673 } | 750 } |
674 | 751 |
675 } // namespace net | 752 } // namespace net |
OLD | NEW |