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_win.h" | 5 #include "net/udp/udp_socket_win.h" |
6 | 6 |
7 #include <mstcpip.h> | 7 #include <mstcpip.h> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 | 158 |
159 //----------------------------------------------------------------------------- | 159 //----------------------------------------------------------------------------- |
160 | 160 |
161 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, | 161 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, |
162 const RandIntCallback& rand_int_cb, | 162 const RandIntCallback& rand_int_cb, |
163 net::NetLog* net_log, | 163 net::NetLog* net_log, |
164 const net::NetLog::Source& source) | 164 const net::NetLog::Source& source) |
165 : socket_(INVALID_SOCKET), | 165 : socket_(INVALID_SOCKET), |
166 addr_family_(0), | 166 addr_family_(0), |
167 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), | 167 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), |
| 168 multicast_interface_(0), |
168 multicast_time_to_live_(1), | 169 multicast_time_to_live_(1), |
169 bind_type_(bind_type), | 170 bind_type_(bind_type), |
170 rand_int_cb_(rand_int_cb), | 171 rand_int_cb_(rand_int_cb), |
171 recv_from_address_(NULL), | 172 recv_from_address_(NULL), |
172 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { | 173 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { |
173 EnsureWinsockInit(); | 174 EnsureWinsockInit(); |
174 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, | 175 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, |
175 source.ToEventParametersCallback()); | 176 source.ToEventParametersCallback()); |
176 if (bind_type == DatagramSocket::RANDOM_BIND) | 177 if (bind_type == DatagramSocket::RANDOM_BIND) |
177 DCHECK(!rand_int_cb.is_null()); | 178 DCHECK(!rand_int_cb.is_null()); |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 DWORD hops = multicast_time_to_live_; | 615 DWORD hops = multicast_time_to_live_; |
615 int protocol_level = | 616 int protocol_level = |
616 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 617 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
617 int option = | 618 int option = |
618 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; | 619 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; |
619 int rv = setsockopt(socket_, protocol_level, option, | 620 int rv = setsockopt(socket_, protocol_level, option, |
620 reinterpret_cast<const char*>(&hops), sizeof(hops)); | 621 reinterpret_cast<const char*>(&hops), sizeof(hops)); |
621 if (rv < 0) | 622 if (rv < 0) |
622 return MapSystemError(WSAGetLastError()); | 623 return MapSystemError(WSAGetLastError()); |
623 } | 624 } |
| 625 if (multicast_interface_ != 0) { |
| 626 switch (addr_family_) { |
| 627 case AF_INET: { |
| 628 in_addr address; |
| 629 address.s_addr = htonl(multicast_interface_); |
| 630 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, |
| 631 reinterpret_cast<const char*>(&address), |
| 632 sizeof(address)); |
| 633 if (rv) |
| 634 return MapSystemError(WSAGetLastError()); |
| 635 break; |
| 636 } |
| 637 case AF_INET6: { |
| 638 uint32 interface_index = multicast_interface_; |
| 639 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, |
| 640 reinterpret_cast<const char*>(&interface_index), |
| 641 sizeof(interface_index)); |
| 642 if (rv) |
| 643 return MapSystemError(WSAGetLastError()); |
| 644 break; |
| 645 } |
| 646 default: |
| 647 NOTREACHED() << "Invalid address family"; |
| 648 return ERR_ADDRESS_INVALID; |
| 649 } |
| 650 } |
624 return OK; | 651 return OK; |
625 } | 652 } |
626 | 653 |
627 int UDPSocketWin::DoBind(const IPEndPoint& address) { | 654 int UDPSocketWin::DoBind(const IPEndPoint& address) { |
628 SockaddrStorage storage; | 655 SockaddrStorage storage; |
629 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) | 656 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) |
630 return ERR_ADDRESS_INVALID; | 657 return ERR_ADDRESS_INVALID; |
631 int rv = bind(socket_, storage.addr, storage.addr_len); | 658 int rv = bind(socket_, storage.addr, storage.addr_len); |
632 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; | 659 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; |
633 } | 660 } |
(...skipping 21 matching lines...) Expand all Loading... |
655 const IPAddressNumber& group_address) const { | 682 const IPAddressNumber& group_address) const { |
656 DCHECK(CalledOnValidThread()); | 683 DCHECK(CalledOnValidThread()); |
657 if (!is_connected()) | 684 if (!is_connected()) |
658 return ERR_SOCKET_NOT_CONNECTED; | 685 return ERR_SOCKET_NOT_CONNECTED; |
659 | 686 |
660 switch (group_address.size()) { | 687 switch (group_address.size()) { |
661 case kIPv4AddressSize: { | 688 case kIPv4AddressSize: { |
662 if (addr_family_ != AF_INET) | 689 if (addr_family_ != AF_INET) |
663 return ERR_ADDRESS_INVALID; | 690 return ERR_ADDRESS_INVALID; |
664 ip_mreq mreq; | 691 ip_mreq mreq; |
665 mreq.imr_interface.s_addr = INADDR_ANY; | 692 mreq.imr_interface.s_addr = htonl(multicast_interface_); |
666 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 693 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
667 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, | 694 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
668 reinterpret_cast<const char*>(&mreq), | 695 reinterpret_cast<const char*>(&mreq), |
669 sizeof(mreq)); | 696 sizeof(mreq)); |
670 if (rv) | 697 if (rv) |
671 return MapSystemError(WSAGetLastError()); | 698 return MapSystemError(WSAGetLastError()); |
672 return OK; | 699 return OK; |
673 } | 700 } |
674 case kIPv6AddressSize: { | 701 case kIPv6AddressSize: { |
675 if (addr_family_ != AF_INET6) | 702 if (addr_family_ != AF_INET6) |
676 return ERR_ADDRESS_INVALID; | 703 return ERR_ADDRESS_INVALID; |
677 ipv6_mreq mreq; | 704 ipv6_mreq mreq; |
678 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 705 mreq.ipv6mr_interface = multicast_interface_; |
679 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 706 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
680 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, | 707 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, |
681 reinterpret_cast<const char*>(&mreq), | 708 reinterpret_cast<const char*>(&mreq), |
682 sizeof(mreq)); | 709 sizeof(mreq)); |
683 if (rv) | 710 if (rv) |
684 return MapSystemError(WSAGetLastError()); | 711 return MapSystemError(WSAGetLastError()); |
685 return OK; | 712 return OK; |
686 } | 713 } |
687 default: | 714 default: |
688 NOTREACHED() << "Invalid address family"; | 715 NOTREACHED() << "Invalid address family"; |
689 return ERR_ADDRESS_INVALID; | 716 return ERR_ADDRESS_INVALID; |
690 } | 717 } |
691 } | 718 } |
692 | 719 |
693 int UDPSocketWin::LeaveGroup( | 720 int UDPSocketWin::LeaveGroup( |
694 const IPAddressNumber& group_address) const { | 721 const IPAddressNumber& group_address) const { |
695 DCHECK(CalledOnValidThread()); | 722 DCHECK(CalledOnValidThread()); |
696 if (!is_connected()) | 723 if (!is_connected()) |
697 return ERR_SOCKET_NOT_CONNECTED; | 724 return ERR_SOCKET_NOT_CONNECTED; |
698 | 725 |
699 switch (group_address.size()) { | 726 switch (group_address.size()) { |
700 case kIPv4AddressSize: { | 727 case kIPv4AddressSize: { |
701 if (addr_family_ != AF_INET) | 728 if (addr_family_ != AF_INET) |
702 return ERR_ADDRESS_INVALID; | 729 return ERR_ADDRESS_INVALID; |
703 ip_mreq mreq; | 730 ip_mreq mreq; |
704 mreq.imr_interface.s_addr = INADDR_ANY; | 731 mreq.imr_interface.s_addr = htonl(multicast_interface_); |
705 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); | 732 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); |
706 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, | 733 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, |
707 reinterpret_cast<const char*>(&mreq), | 734 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); |
708 sizeof(mreq)); | |
709 if (rv) | 735 if (rv) |
710 return MapSystemError(WSAGetLastError()); | 736 return MapSystemError(WSAGetLastError()); |
711 return OK; | 737 return OK; |
712 } | 738 } |
713 case kIPv6AddressSize: { | 739 case kIPv6AddressSize: { |
714 if (addr_family_ != AF_INET6) | 740 if (addr_family_ != AF_INET6) |
715 return ERR_ADDRESS_INVALID; | 741 return ERR_ADDRESS_INVALID; |
716 ipv6_mreq mreq; | 742 ipv6_mreq mreq; |
717 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. | 743 mreq.ipv6mr_interface = multicast_interface_; |
718 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); | 744 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); |
719 int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP, | 745 int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP, |
720 reinterpret_cast<const char*>(&mreq), | 746 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); |
721 sizeof(mreq)); | |
722 if (rv) | 747 if (rv) |
723 return MapSystemError(WSAGetLastError()); | 748 return MapSystemError(WSAGetLastError()); |
724 return OK; | 749 return OK; |
725 } | 750 } |
726 default: | 751 default: |
727 NOTREACHED() << "Invalid address family"; | 752 NOTREACHED() << "Invalid address family"; |
728 return ERR_ADDRESS_INVALID; | 753 return ERR_ADDRESS_INVALID; |
729 } | 754 } |
730 } | 755 } |
731 | 756 |
| 757 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) { |
| 758 DCHECK(CalledOnValidThread()); |
| 759 if (is_connected()) |
| 760 return ERR_SOCKET_IS_CONNECTED; |
| 761 multicast_interface_ = interface_index; |
| 762 return OK; |
| 763 } |
| 764 |
732 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) { | 765 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) { |
733 DCHECK(CalledOnValidThread()); | 766 DCHECK(CalledOnValidThread()); |
734 if (is_connected()) | 767 if (is_connected()) |
735 return ERR_SOCKET_IS_CONNECTED; | 768 return ERR_SOCKET_IS_CONNECTED; |
736 | 769 |
737 if (time_to_live < 0 || time_to_live > 255) | 770 if (time_to_live < 0 || time_to_live > 255) |
738 return ERR_INVALID_ARGUMENT; | 771 return ERR_INVALID_ARGUMENT; |
739 multicast_time_to_live_ = time_to_live; | 772 multicast_time_to_live_ = time_to_live; |
740 return OK; | 773 return OK; |
741 } | 774 } |
(...skipping 10 matching lines...) Expand all Loading... |
752 return OK; | 785 return OK; |
753 } | 786 } |
754 | 787 |
755 // TODO(hubbe): Implement differentiated services for windows. | 788 // TODO(hubbe): Implement differentiated services for windows. |
756 // Note: setsockopt(IP_TOS) does not work on windows XP and later. | 789 // Note: setsockopt(IP_TOS) does not work on windows XP and later. |
757 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { | 790 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { |
758 return ERR_NOT_IMPLEMENTED; | 791 return ERR_NOT_IMPLEMENTED; |
759 } | 792 } |
760 | 793 |
761 } // namespace net | 794 } // namespace net |
OLD | NEW |