| Index: net/udp/udp_socket_win.cc
|
| diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
|
| index 5c6da9fc47c154dfd9e40ad682e980512eb19002..1ab96ac0aae63dfc58ca2a7f1600d9c0551e2510 100644
|
| --- a/net/udp/udp_socket_win.cc
|
| +++ b/net/udp/udp_socket_win.cc
|
| @@ -355,7 +355,8 @@ int UDPSocketWin::Bind(const IPEndPoint& address) {
|
| }
|
|
|
| int UDPSocketWin::CreateSocket(const IPEndPoint& address) {
|
| - socket_ = WSASocket(address.GetSockAddrFamily(), SOCK_DGRAM, IPPROTO_UDP,
|
| + sock_addr_family_ = address.GetSockAddrFamily();
|
| + socket_ = WSASocket(sock_addr_family_, SOCK_DGRAM, IPPROTO_UDP,
|
| NULL, 0, WSA_FLAG_OVERLAPPED);
|
| if (socket_ == INVALID_SOCKET)
|
| return MapSystemError(WSAGetLastError());
|
| @@ -614,4 +615,99 @@ bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
|
| return address->FromSockAddr(storage.addr, storage.addr_len);
|
| }
|
|
|
| +
|
| +int UDPSocketWin::JoinGroup(
|
| + const net::IPAddressNumber& group_address) const {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(is_connected());
|
| + int rv = -1;
|
| + switch(group_address.size()) {
|
| + case kIPv4AddressSize: {
|
| + if (sock_addr_family_ != AF_INET) {
|
| + return ERR_ADDRESS_INVALID;
|
| + }
|
| + ip_mreq mreq;
|
| + memset(&mreq, 0, sizeof(mreq));
|
| + memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
|
| + rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
| + reinterpret_cast<const char*>(&mreq),
|
| + sizeof(mreq));
|
| + break;
|
| + }
|
| + case kIPv6AddressSize: {
|
| + if (sock_addr_family_ != AF_INET6) {
|
| + return ERR_ADDRESS_INVALID;
|
| + }
|
| + ipv6_mreq mreq;
|
| + memset(&mreq, 0, sizeof(mreq));
|
| + memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
|
| + rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
|
| + reinterpret_cast<const char*>(&mreq),
|
| + sizeof(mreq));
|
| + break;
|
| + }
|
| + }
|
| + return MapSystemError(rv);
|
| +}
|
| +
|
| +int UDPSocketWin::LeaveGroup(
|
| + const net::IPAddressNumber& group_address) const {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(is_connected());
|
| + int rv = -1;
|
| + switch(group_address.size()) {
|
| + case kIPv4AddressSize: {
|
| + if (sock_addr_family_ != AF_INET) {
|
| + return ERR_ADDRESS_INVALID;
|
| + }
|
| + ip_mreq mreq;
|
| + memset(&mreq, 0, sizeof(mreq));
|
| + memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
|
| + rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
| + reinterpret_cast<const char*>(&mreq),
|
| + sizeof(mreq));
|
| + break;
|
| + }
|
| + case kIPv6AddressSize: {
|
| + if (sock_addr_family_ != AF_INET6) {
|
| + return ERR_ADDRESS_INVALID;
|
| + }
|
| + ipv6_mreq mreq;
|
| + memset(&mreq, 0, sizeof(mreq));
|
| + memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
|
| + rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
|
| + reinterpret_cast<const char*>(&mreq),
|
| + sizeof(mreq));
|
| + break;
|
| + }
|
| + }
|
| + return MapSystemError(rv);
|
| +}
|
| +
|
| +int UDPSocketWin::SetMulticastTimeToLive(int timeToLive) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(is_connected());
|
| +
|
| + uint8 ttl = timeToLive;
|
| + int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
|
| + return MapSystemError(setsockopt(socket_,
|
| + ip_family,
|
| + IP_MULTICAST_TTL,
|
| + reinterpret_cast<const char*>(&ttl),
|
| + sizeof(ttl)));
|
| +}
|
| +
|
| +int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
|
| + DCHECK(CalledOnValidThread());
|
| + DCHECK(is_connected());
|
| +
|
| + uint8 loop = loopback;
|
| + int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
|
| + return MapSystemError(setsockopt(socket_,
|
| + ip_family,
|
| + IP_MULTICAST_LOOP,
|
| + reinterpret_cast<const char*>(&loop),
|
| + sizeof(loop)));
|
| +}
|
| +
|
| } // namespace net
|
|
|