Chromium Code Reviews| 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..cd3e83c20a22ebf7eb112154e4e4ced8d7b75b79 100644 |
| --- a/net/udp/udp_socket_win.cc |
| +++ b/net/udp/udp_socket_win.cc |
| @@ -163,7 +163,10 @@ UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, |
| net::NetLog* net_log, |
| const net::NetLog::Source& source) |
| : socket_(INVALID_SOCKET), |
| + sock_addr_family_(0), |
| socket_options_(0), |
| + multicast_time_to_live_(1), |
| + multicast_loopback_mode_(true), |
| bind_type_(bind_type), |
| rand_int_cb_(rand_int_cb), |
| recv_from_address_(NULL), |
| @@ -355,7 +358,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()); |
| @@ -584,6 +588,16 @@ int UDPSocketWin::SetSocketOptions() { |
| if (rv < 0) |
| return MapSystemError(errno); |
| } |
| + if (multicast_time_to_live_ != 1) { |
|
wtc
2013/04/16 19:59:42
Can you cite a MSDN page or some Microsoft documen
Bei Zhang
2013/04/17 17:53:03
http://ibiblio.org/pub/linux/docs/HOWTO/other-form
|
| + int rv = SetMulticastTimeToLive(multicast_time_to_live_); |
| + if (rv != OK) |
| + return rv; |
| + } |
| + if (!multicast_loopback_mode_) { |
| + int rv = SetMulticastLoopbackMode(multicast_loopback_mode_); |
| + if (rv != OK) |
| + return rv; |
| + } |
| return OK; |
| } |
| @@ -614,4 +628,103 @@ 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; |
|
wtc
2013/04/16 19:59:42
Nit: initialize |rv| to SOCKET_ERROR (which has th
Bei Zhang
2013/04/17 17:53:03
Done.
|
| + 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; |
|
wtc
2013/04/16 19:59:42
NOTE: all of my comments on JoinGroup also apply t
Bei Zhang
2013/04/17 17:53:03
Done.
|
| + } |
| + } |
| + return MapSystemError(rv); |
|
wtc
2013/04/16 19:59:42
BUG: this should be:
if (rv != 0)
return Map
Bei Zhang
2013/04/17 17:53:03
Done.
|
| +} |
| + |
| +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 time_to_live) { |
| + DCHECK(CalledOnValidThread()); |
| + if (is_connected()) { |
| + if (time_to_live < 0 || time_to_live > 255) |
| + return ERR_INVALID_ARGUMENT; |
|
wtc
2013/04/16 19:59:42
This check should be moved to line 709, before we
Bei Zhang
2013/04/17 17:53:03
I'm changing the behavior to make it only works be
|
| + uint8 ttl = time_to_live; |
| + 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))); |
| + } else { |
| + multicast_time_to_live_ = time_to_live; |
| + return OK; |
| + } |
| +} |
| + |
| +int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) { |
| + DCHECK(CalledOnValidThread()); |
| + if (is_connected()) { |
| + uint8 loop = loopback; |
|
wtc
2013/04/16 19:59:42
NOTE: all of my comments on SetMulticastLoopbackMo
Bei Zhang
2013/04/17 17:53:03
Thank you for pointing that out. Adding the notes
wtc
2013/04/17 22:06:50
I think you should also add the notes to the
udp_s
|
| + int ip_family = sock_addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
| + return MapSystemError(setsockopt(socket_, |
|
wtc
2013/04/16 19:59:42
BUG: MapSystemError() takes a socket error code
(W
Bei Zhang
2013/04/17 17:53:03
Done.
|
| + ip_family, |
| + IP_MULTICAST_LOOP, |
| + reinterpret_cast<const char*>(&loop), |
| + sizeof(loop))); |
| + } else { |
| + multicast_loopback_mode_ = loopback; |
|
wtc
2013/04/16 19:59:42
I think this function should always store |loopbac
Bei Zhang
2013/04/17 17:53:03
Done.
|
| + return OK; |
| + } |
| +} |
| + |
| } // namespace net |