Home | History | Annotate | Download | only in udp
      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
      3 // found in the LICENSE file.
      4 
      5 #include "net/udp/udp_socket_win.h"
      6 
      7 #include <mstcpip.h>
      8 
      9 #include "base/callback.h"
     10 #include "base/logging.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/metrics/histogram.h"
     13 #include "base/metrics/sparse_histogram.h"
     14 #include "base/metrics/stats_counters.h"
     15 #include "base/rand_util.h"
     16 #include "net/base/io_buffer.h"
     17 #include "net/base/ip_endpoint.h"
     18 #include "net/base/net_errors.h"
     19 #include "net/base/net_log.h"
     20 #include "net/base/net_util.h"
     21 #include "net/base/winsock_init.h"
     22 #include "net/base/winsock_util.h"
     23 #include "net/socket/socket_descriptor.h"
     24 #include "net/udp/udp_net_log_parameters.h"
     25 
     26 namespace {
     27 
     28 const int kBindRetries = 10;
     29 const int kPortStart = 1024;
     30 const int kPortEnd = 65535;
     31 
     32 }  // namespace
     33 
     34 namespace net {
     35 
     36 // This class encapsulates all the state that has to be preserved as long as
     37 // there is a network IO operation in progress. If the owner UDPSocketWin
     38 // is destroyed while an operation is in progress, the Core is detached and it
     39 // lives until the operation completes and the OS doesn't reference any resource
     40 // declared on this class anymore.
     41 class UDPSocketWin::Core : public base::RefCounted<Core> {
     42  public:
     43   explicit Core(UDPSocketWin* socket);
     44 
     45   // Start watching for the end of a read or write operation.
     46   void WatchForRead();
     47   void WatchForWrite();
     48 
     49   // The UDPSocketWin is going away.
     50   void Detach() { socket_ = NULL; }
     51 
     52   // The separate OVERLAPPED variables for asynchronous operation.
     53   OVERLAPPED read_overlapped_;
     54   OVERLAPPED write_overlapped_;
     55 
     56   // The buffers used in Read() and Write().
     57   scoped_refptr<IOBuffer> read_iobuffer_;
     58   scoped_refptr<IOBuffer> write_iobuffer_;
     59 
     60   // The address storage passed to WSARecvFrom().
     61   SockaddrStorage recv_addr_storage_;
     62 
     63  private:
     64   friend class base::RefCounted<Core>;
     65 
     66   class ReadDelegate : public base::win::ObjectWatcher::Delegate {
     67    public:
     68     explicit ReadDelegate(Core* core) : core_(core) {}
     69     virtual ~ReadDelegate() {}
     70 
     71     // base::ObjectWatcher::Delegate methods:
     72     virtual void OnObjectSignaled(HANDLE object);
     73 
     74    private:
     75     Core* const core_;
     76   };
     77 
     78   class WriteDelegate : public base::win::ObjectWatcher::Delegate {
     79    public:
     80     explicit WriteDelegate(Core* core) : core_(core) {}
     81     virtual ~WriteDelegate() {}
     82 
     83     // base::ObjectWatcher::Delegate methods:
     84     virtual void OnObjectSignaled(HANDLE object);
     85 
     86    private:
     87     Core* const core_;
     88   };
     89 
     90   ~Core();
     91 
     92   // The socket that created this object.
     93   UDPSocketWin* socket_;
     94 
     95   // |reader_| handles the signals from |read_watcher_|.
     96   ReadDelegate reader_;
     97   // |writer_| handles the signals from |write_watcher_|.
     98   WriteDelegate writer_;
     99 
    100   // |read_watcher_| watches for events from Read().
    101   base::win::ObjectWatcher read_watcher_;
    102   // |write_watcher_| watches for events from Write();
    103   base::win::ObjectWatcher write_watcher_;
    104 
    105   DISALLOW_COPY_AND_ASSIGN(Core);
    106 };
    107 
    108 UDPSocketWin::Core::Core(UDPSocketWin* socket)
    109     : socket_(socket),
    110       reader_(this),
    111       writer_(this) {
    112   memset(&read_overlapped_, 0, sizeof(read_overlapped_));
    113   memset(&write_overlapped_, 0, sizeof(write_overlapped_));
    114 
    115   read_overlapped_.hEvent = WSACreateEvent();
    116   write_overlapped_.hEvent = WSACreateEvent();
    117 }
    118 
    119 UDPSocketWin::Core::~Core() {
    120   // Make sure the message loop is not watching this object anymore.
    121   read_watcher_.StopWatching();
    122   write_watcher_.StopWatching();
    123 
    124   WSACloseEvent(read_overlapped_.hEvent);
    125   memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
    126   WSACloseEvent(write_overlapped_.hEvent);
    127   memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
    128 }
    129 
    130 void UDPSocketWin::Core::WatchForRead() {
    131   // We grab an extra reference because there is an IO operation in progress.
    132   // Balanced in ReadDelegate::OnObjectSignaled().
    133   AddRef();
    134   read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
    135 }
    136 
    137 void UDPSocketWin::Core::WatchForWrite() {
    138   // We grab an extra reference because there is an IO operation in progress.
    139   // Balanced in WriteDelegate::OnObjectSignaled().
    140   AddRef();
    141   write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
    142 }
    143 
    144 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
    145   DCHECK_EQ(object, core_->read_overlapped_.hEvent);
    146   if (core_->socket_)
    147     core_->socket_->DidCompleteRead();
    148 
    149   core_->Release();
    150 }
    151 
    152 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) {
    153   DCHECK_EQ(object, core_->write_overlapped_.hEvent);
    154   if (core_->socket_)
    155     core_->socket_->DidCompleteWrite();
    156 
    157   core_->Release();
    158 }
    159 
    160 //-----------------------------------------------------------------------------
    161 
    162 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
    163                            const RandIntCallback& rand_int_cb,
    164                            net::NetLog* net_log,
    165                            const net::NetLog::Source& source)
    166     : socket_(INVALID_SOCKET),
    167       addr_family_(0),
    168       socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
    169       multicast_interface_(0),
    170       multicast_time_to_live_(1),
    171       bind_type_(bind_type),
    172       rand_int_cb_(rand_int_cb),
    173       recv_from_address_(NULL),
    174       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
    175   EnsureWinsockInit();
    176   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
    177                       source.ToEventParametersCallback());
    178   if (bind_type == DatagramSocket::RANDOM_BIND)
    179     DCHECK(!rand_int_cb.is_null());
    180 }
    181 
    182 UDPSocketWin::~UDPSocketWin() {
    183   Close();
    184   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
    185 }
    186 
    187 void UDPSocketWin::Close() {
    188   DCHECK(CalledOnValidThread());
    189 
    190   if (!is_connected())
    191     return;
    192 
    193   // Zero out any pending read/write callback state.
    194   read_callback_.Reset();
    195   recv_from_address_ = NULL;
    196   write_callback_.Reset();
    197 
    198   base::TimeTicks start_time = base::TimeTicks::Now();
    199   closesocket(socket_);
    200   UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
    201                       base::TimeTicks::Now() - start_time);
    202   socket_ = INVALID_SOCKET;
    203   addr_family_ = 0;
    204 
    205   core_->Detach();
    206   core_ = NULL;
    207 }
    208 
    209 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
    210   DCHECK(CalledOnValidThread());
    211   DCHECK(address);
    212   if (!is_connected())
    213     return ERR_SOCKET_NOT_CONNECTED;
    214 
    215   // TODO(szym): Simplify. http://crbug.com/126152
    216   if (!remote_address_.get()) {
    217     SockaddrStorage storage;
    218     if (getpeername(socket_, storage.addr, &storage.addr_len))
    219       return MapSystemError(WSAGetLastError());
    220     scoped_ptr<IPEndPoint> address(new IPEndPoint());
    221     if (!address->FromSockAddr(storage.addr, storage.addr_len))
    222       return ERR_ADDRESS_INVALID;
    223     remote_address_.reset(address.release());
    224   }
    225 
    226   *address = *remote_address_;
    227   return OK;
    228 }
    229 
    230 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
    231   DCHECK(CalledOnValidThread());
    232   DCHECK(address);
    233   if (!is_connected())
    234     return ERR_SOCKET_NOT_CONNECTED;
    235 
    236   // TODO(szym): Simplify. http://crbug.com/126152
    237   if (!local_address_.get()) {
    238     SockaddrStorage storage;
    239     if (getsockname(socket_, storage.addr, &storage.addr_len))
    240       return MapSystemError(WSAGetLastError());
    241     scoped_ptr<IPEndPoint> address(new IPEndPoint());
    242     if (!address->FromSockAddr(storage.addr, storage.addr_len))
    243       return ERR_ADDRESS_INVALID;
    244     local_address_.reset(address.release());
    245     net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
    246                       CreateNetLogUDPConnectCallback(local_address_.get()));
    247   }
    248 
    249   *address = *local_address_;
    250   return OK;
    251 }
    252 
    253 int UDPSocketWin::Read(IOBuffer* buf,
    254                        int buf_len,
    255                        const CompletionCallback& callback) {
    256   return RecvFrom(buf, buf_len, NULL, callback);
    257 }
    258 
    259 int UDPSocketWin::RecvFrom(IOBuffer* buf,
    260                            int buf_len,
    261                            IPEndPoint* address,
    262                            const CompletionCallback& callback) {
    263   DCHECK(CalledOnValidThread());
    264   DCHECK_NE(INVALID_SOCKET, socket_);
    265   DCHECK(read_callback_.is_null());
    266   DCHECK(!recv_from_address_);
    267   DCHECK(!callback.is_null());  // Synchronous operation not supported.
    268   DCHECK_GT(buf_len, 0);
    269 
    270   int nread = InternalRecvFrom(buf, buf_len, address);
    271   if (nread != ERR_IO_PENDING)
    272     return nread;
    273 
    274   read_callback_ = callback;
    275   recv_from_address_ = address;
    276   return ERR_IO_PENDING;
    277 }
    278 
    279 int UDPSocketWin::Write(IOBuffer* buf,
    280                         int buf_len,
    281                         const CompletionCallback& callback) {
    282   return SendToOrWrite(buf, buf_len, NULL, callback);
    283 }
    284 
    285 int UDPSocketWin::SendTo(IOBuffer* buf,
    286                          int buf_len,
    287                          const IPEndPoint& address,
    288                          const CompletionCallback& callback) {
    289   return SendToOrWrite(buf, buf_len, &address, callback);
    290 }
    291 
    292 int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
    293                                 int buf_len,
    294                                 const IPEndPoint* address,
    295                                 const CompletionCallback& callback) {
    296   DCHECK(CalledOnValidThread());
    297   DCHECK_NE(INVALID_SOCKET, socket_);
    298   DCHECK(write_callback_.is_null());
    299   DCHECK(!callback.is_null());  // Synchronous operation not supported.
    300   DCHECK_GT(buf_len, 0);
    301   DCHECK(!send_to_address_.get());
    302 
    303   int nwrite = InternalSendTo(buf, buf_len, address);
    304   if (nwrite != ERR_IO_PENDING)
    305     return nwrite;
    306 
    307   if (address)
    308     send_to_address_.reset(new IPEndPoint(*address));
    309   write_callback_ = callback;
    310   return ERR_IO_PENDING;
    311 }
    312 
    313 int UDPSocketWin::Connect(const IPEndPoint& address) {
    314   net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
    315                       CreateNetLogUDPConnectCallback(&address));
    316   int rv = InternalConnect(address);
    317   if (rv != OK)
    318     Close();
    319   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
    320   return rv;
    321 }
    322 
    323 int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
    324   DCHECK(!is_connected());
    325   DCHECK(!remote_address_.get());
    326   int addr_family = address.GetSockAddrFamily();
    327   int rv = CreateSocket(addr_family);
    328   if (rv < 0)
    329     return rv;
    330 
    331   if (bind_type_ == DatagramSocket::RANDOM_BIND) {
    332     // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
    333     // representing INADDR_ANY or in6addr_any.
    334     size_t addr_size =
    335         addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize;
    336     IPAddressNumber addr_any(addr_size);
    337     rv = RandomBind(addr_any);
    338   }
    339   // else connect() does the DatagramSocket::DEFAULT_BIND
    340 
    341   if (rv < 0) {
    342     UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", rv);
    343     Close();
    344     return rv;
    345   }
    346 
    347   SockaddrStorage storage;
    348   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
    349     return ERR_ADDRESS_INVALID;
    350 
    351   rv = connect(socket_, storage.addr, storage.addr_len);
    352   if (rv < 0) {
    353     // Close() may change the last error. Map it beforehand.
    354     int result = MapSystemError(WSAGetLastError());
    355     Close();
    356     return result;
    357   }
    358 
    359   remote_address_.reset(new IPEndPoint(address));
    360   return rv;
    361 }
    362 
    363 int UDPSocketWin::Bind(const IPEndPoint& address) {
    364   DCHECK(!is_connected());
    365   int rv = CreateSocket(address.GetSockAddrFamily());
    366   if (rv < 0)
    367     return rv;
    368   rv = SetSocketOptions();
    369   if (rv < 0) {
    370     Close();
    371     return rv;
    372   }
    373   rv = DoBind(address);
    374   if (rv < 0) {
    375     Close();
    376     return rv;
    377   }
    378   local_address_.reset();
    379   return rv;
    380 }
    381 
    382 int UDPSocketWin::CreateSocket(int addr_family) {
    383   addr_family_ = addr_family;
    384   socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
    385   if (socket_ == INVALID_SOCKET)
    386     return MapSystemError(WSAGetLastError());
    387   core_ = new Core(this);
    388   return OK;
    389 }
    390 
    391 bool UDPSocketWin::SetReceiveBufferSize(int32 size) {
    392   DCHECK(CalledOnValidThread());
    393   int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
    394                       reinterpret_cast<const char*>(&size), sizeof(size));
    395   DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
    396   return rv == 0;
    397 }
    398 
    399 bool UDPSocketWin::SetSendBufferSize(int32 size) {
    400   DCHECK(CalledOnValidThread());
    401   int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
    402                       reinterpret_cast<const char*>(&size), sizeof(size));
    403   DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
    404   return rv == 0;
    405 }
    406 
    407 void UDPSocketWin::AllowAddressReuse() {
    408   DCHECK(CalledOnValidThread());
    409   DCHECK(!is_connected());
    410 
    411   socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
    412 }
    413 
    414 void UDPSocketWin::AllowBroadcast() {
    415   DCHECK(CalledOnValidThread());
    416   DCHECK(!is_connected());
    417 
    418   socket_options_ |= SOCKET_OPTION_BROADCAST;
    419 }
    420 
    421 void UDPSocketWin::DoReadCallback(int rv) {
    422   DCHECK_NE(rv, ERR_IO_PENDING);
    423   DCHECK(!read_callback_.is_null());
    424 
    425   // since Run may result in Read being called, clear read_callback_ up front.
    426   CompletionCallback c = read_callback_;
    427   read_callback_.Reset();
    428   c.Run(rv);
    429 }
    430 
    431 void UDPSocketWin::DoWriteCallback(int rv) {
    432   DCHECK_NE(rv, ERR_IO_PENDING);
    433   DCHECK(!write_callback_.is_null());
    434 
    435   // since Run may result in Write being called, clear write_callback_ up front.
    436   CompletionCallback c = write_callback_;
    437   write_callback_.Reset();
    438   c.Run(rv);
    439 }
    440 
    441 void UDPSocketWin::DidCompleteRead() {
    442   DWORD num_bytes, flags;
    443   BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
    444                                    &num_bytes, FALSE, &flags);
    445   WSAResetEvent(core_->read_overlapped_.hEvent);
    446   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
    447   // Convert address.
    448   if (recv_from_address_ && result >= 0) {
    449     if (!ReceiveAddressToIPEndpoint(recv_from_address_))
    450       result = ERR_ADDRESS_INVALID;
    451   }
    452   LogRead(result, core_->read_iobuffer_->data());
    453   core_->read_iobuffer_ = NULL;
    454   recv_from_address_ = NULL;
    455   DoReadCallback(result);
    456 }
    457 
    458 void UDPSocketWin::LogRead(int result, const char* bytes) const {
    459   if (result < 0) {
    460     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
    461     return;
    462   }
    463 
    464   if (net_log_.IsLoggingAllEvents()) {
    465     // Get address for logging, if |address| is NULL.
    466     IPEndPoint address;
    467     bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
    468     net_log_.AddEvent(
    469         NetLog::TYPE_UDP_BYTES_RECEIVED,
    470         CreateNetLogUDPDataTranferCallback(
    471             result, bytes,
    472             is_address_valid ? &address : NULL));
    473   }
    474 
    475   base::StatsCounter read_bytes("udp.read_bytes");
    476   read_bytes.Add(result);
    477 }
    478 
    479 void UDPSocketWin::DidCompleteWrite() {
    480   DWORD num_bytes, flags;
    481   BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
    482                                    &num_bytes, FALSE, &flags);
    483   WSAResetEvent(core_->write_overlapped_.hEvent);
    484   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
    485   LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
    486 
    487   send_to_address_.reset();
    488   core_->write_iobuffer_ = NULL;
    489   DoWriteCallback(result);
    490 }
    491 
    492 void UDPSocketWin::LogWrite(int result,
    493                             const char* bytes,
    494                             const IPEndPoint* address) const {
    495   if (result < 0) {
    496     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
    497     return;
    498   }
    499 
    500   if (net_log_.IsLoggingAllEvents()) {
    501     net_log_.AddEvent(
    502         NetLog::TYPE_UDP_BYTES_SENT,
    503         CreateNetLogUDPDataTranferCallback(result, bytes, address));
    504   }
    505 
    506   base::StatsCounter write_bytes("udp.write_bytes");
    507   write_bytes.Add(result);
    508 }
    509 
    510 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
    511                                    IPEndPoint* address) {
    512   DCHECK(!core_->read_iobuffer_);
    513   SockaddrStorage& storage = core_->recv_addr_storage_;
    514   storage.addr_len = sizeof(storage.addr_storage);
    515 
    516   WSABUF read_buffer;
    517   read_buffer.buf = buf->data();
    518   read_buffer.len = buf_len;
    519 
    520   DWORD flags = 0;
    521   DWORD num;
    522   CHECK_NE(INVALID_SOCKET, socket_);
    523   AssertEventNotSignaled(core_->read_overlapped_.hEvent);
    524   int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
    525                        &storage.addr_len, &core_->read_overlapped_, NULL);
    526   if (rv == 0) {
    527     if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
    528       int result = num;
    529       // Convert address.
    530       if (address && result >= 0) {
    531         if (!ReceiveAddressToIPEndpoint(address))
    532           result = ERR_FAILED;
    533       }
    534       LogRead(result, buf->data());
    535       return result;
    536     }
    537   } else {
    538     int os_error = WSAGetLastError();
    539     if (os_error != WSA_IO_PENDING) {
    540       int result = MapSystemError(os_error);
    541       LogRead(result, NULL);
    542       return result;
    543     }
    544   }
    545   core_->WatchForRead();
    546   core_->read_iobuffer_ = buf;
    547   return ERR_IO_PENDING;
    548 }
    549 
    550 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
    551                                  const IPEndPoint* address) {
    552   DCHECK(!core_->write_iobuffer_);
    553   SockaddrStorage storage;
    554   struct sockaddr* addr = storage.addr;
    555   // Convert address.
    556   if (!address) {
    557     addr = NULL;
    558     storage.addr_len = 0;
    559   } else {
    560     if (!address->ToSockAddr(addr, &storage.addr_len)) {
    561       int result = ERR_FAILED;
    562       LogWrite(result, NULL, NULL);
    563       return result;
    564     }
    565   }
    566 
    567   WSABUF write_buffer;
    568   write_buffer.buf = buf->data();
    569   write_buffer.len = buf_len;
    570 
    571   DWORD flags = 0;
    572   DWORD num;
    573   AssertEventNotSignaled(core_->write_overlapped_.hEvent);
    574   int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
    575                      addr, storage.addr_len, &core_->write_overlapped_, NULL);
    576   if (rv == 0) {
    577     if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
    578       int result = num;
    579       LogWrite(result, buf->data(), address);
    580       return result;
    581     }
    582   } else {
    583     int os_error = WSAGetLastError();
    584     if (os_error != WSA_IO_PENDING) {
    585       int result = MapSystemError(os_error);
    586       LogWrite(result, NULL, NULL);
    587       return result;
    588     }
    589   }
    590 
    591   core_->WatchForWrite();
    592   core_->write_iobuffer_ = buf;
    593   return ERR_IO_PENDING;
    594 }
    595 
    596 int UDPSocketWin::SetSocketOptions() {
    597   BOOL true_value = 1;
    598   if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
    599     int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
    600                         reinterpret_cast<const char*>(&true_value),
    601                         sizeof(true_value));
    602     if (rv < 0)
    603       return MapSystemError(WSAGetLastError());
    604   }
    605   if (socket_options_ & SOCKET_OPTION_BROADCAST) {
    606     int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
    607                         reinterpret_cast<const char*>(&true_value),
    608                         sizeof(true_value));
    609     if (rv < 0)
    610       return MapSystemError(WSAGetLastError());
    611   }
    612   if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
    613     DWORD loop = 0;
    614     int protocol_level =
    615         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
    616     int option =
    617         addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
    618     int rv = setsockopt(socket_, protocol_level, option,
    619                         reinterpret_cast<const char*>(&loop), sizeof(loop));
    620     if (rv < 0)
    621       return MapSystemError(WSAGetLastError());
    622   }
    623   if (multicast_time_to_live_ != 1) {
    624     DWORD hops = multicast_time_to_live_;
    625     int protocol_level =
    626         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
    627     int option =
    628         addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
    629     int rv = setsockopt(socket_, protocol_level, option,
    630                         reinterpret_cast<const char*>(&hops), sizeof(hops));
    631     if (rv < 0)
    632       return MapSystemError(WSAGetLastError());
    633   }
    634   if (multicast_interface_ != 0) {
    635     switch (addr_family_) {
    636       case AF_INET: {
    637         in_addr address;
    638         address.s_addr = htonl(multicast_interface_);
    639         int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
    640                             reinterpret_cast<const char*>(&address),
    641                             sizeof(address));
    642         if (rv)
    643           return MapSystemError(WSAGetLastError());
    644         break;
    645       }
    646       case AF_INET6: {
    647         uint32 interface_index = multicast_interface_;
    648         int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
    649                             reinterpret_cast<const char*>(&interface_index),
    650                             sizeof(interface_index));
    651         if (rv)
    652           return MapSystemError(WSAGetLastError());
    653         break;
    654       }
    655       default:
    656         NOTREACHED() << "Invalid address family";
    657         return ERR_ADDRESS_INVALID;
    658     }
    659   }
    660   return OK;
    661 }
    662 
    663 int UDPSocketWin::DoBind(const IPEndPoint& address) {
    664   SockaddrStorage storage;
    665   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
    666     return ERR_ADDRESS_INVALID;
    667   int rv = bind(socket_, storage.addr, storage.addr_len);
    668   if (rv == 0)
    669     return OK;
    670   int last_error = WSAGetLastError();
    671   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
    672   // Map some codes that are special to bind() separately.
    673   if (last_error == WSAEACCES || last_error == WSAEINVAL)
    674     return ERR_ADDRESS_IN_USE;
    675   return MapSystemError(last_error);
    676 }
    677 
    678 int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
    679   DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
    680 
    681   for (int i = 0; i < kBindRetries; ++i) {
    682     int rv = DoBind(IPEndPoint(address,
    683                                rand_int_cb_.Run(kPortStart, kPortEnd)));
    684     if (rv == OK || rv != ERR_ADDRESS_IN_USE)
    685       return rv;
    686   }
    687   return DoBind(IPEndPoint(address, 0));
    688 }
    689 
    690 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
    691   SockaddrStorage& storage = core_->recv_addr_storage_;
    692   return address->FromSockAddr(storage.addr, storage.addr_len);
    693 }
    694 
    695 int UDPSocketWin::JoinGroup(
    696     const IPAddressNumber& group_address) const {
    697   DCHECK(CalledOnValidThread());
    698   if (!is_connected())
    699     return ERR_SOCKET_NOT_CONNECTED;
    700 
    701   switch (group_address.size()) {
    702     case kIPv4AddressSize: {
    703       if (addr_family_ != AF_INET)
    704         return ERR_ADDRESS_INVALID;
    705       ip_mreq mreq;
    706       mreq.imr_interface.s_addr = htonl(multicast_interface_);
    707       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
    708       int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
    709                           reinterpret_cast<const char*>(&mreq),
    710                           sizeof(mreq));
    711       if (rv)
    712         return MapSystemError(WSAGetLastError());
    713       return OK;
    714     }
    715     case kIPv6AddressSize: {
    716       if (addr_family_ != AF_INET6)
    717         return ERR_ADDRESS_INVALID;
    718       ipv6_mreq mreq;
    719       mreq.ipv6mr_interface = multicast_interface_;
    720       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
    721       int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
    722                           reinterpret_cast<const char*>(&mreq),
    723                           sizeof(mreq));
    724       if (rv)
    725         return MapSystemError(WSAGetLastError());
    726       return OK;
    727     }
    728     default:
    729       NOTREACHED() << "Invalid address family";
    730       return ERR_ADDRESS_INVALID;
    731   }
    732 }
    733 
    734 int UDPSocketWin::LeaveGroup(
    735     const IPAddressNumber& group_address) const {
    736   DCHECK(CalledOnValidThread());
    737   if (!is_connected())
    738     return ERR_SOCKET_NOT_CONNECTED;
    739 
    740   switch (group_address.size()) {
    741     case kIPv4AddressSize: {
    742       if (addr_family_ != AF_INET)
    743         return ERR_ADDRESS_INVALID;
    744       ip_mreq mreq;
    745       mreq.imr_interface.s_addr = htonl(multicast_interface_);
    746       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
    747       int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
    748                           reinterpret_cast<const char*>(&mreq), sizeof(mreq));
    749       if (rv)
    750         return MapSystemError(WSAGetLastError());
    751       return OK;
    752     }
    753     case kIPv6AddressSize: {
    754       if (addr_family_ != AF_INET6)
    755         return ERR_ADDRESS_INVALID;
    756       ipv6_mreq mreq;
    757       mreq.ipv6mr_interface = multicast_interface_;
    758       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
    759       int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
    760                           reinterpret_cast<const char*>(&mreq), sizeof(mreq));
    761       if (rv)
    762         return MapSystemError(WSAGetLastError());
    763       return OK;
    764     }
    765     default:
    766       NOTREACHED() << "Invalid address family";
    767       return ERR_ADDRESS_INVALID;
    768   }
    769 }
    770 
    771 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
    772   DCHECK(CalledOnValidThread());
    773   if (is_connected())
    774     return ERR_SOCKET_IS_CONNECTED;
    775   multicast_interface_ = interface_index;
    776   return OK;
    777 }
    778 
    779 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
    780   DCHECK(CalledOnValidThread());
    781   if (is_connected())
    782     return ERR_SOCKET_IS_CONNECTED;
    783 
    784   if (time_to_live < 0 || time_to_live > 255)
    785     return ERR_INVALID_ARGUMENT;
    786   multicast_time_to_live_ = time_to_live;
    787   return OK;
    788 }
    789 
    790 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
    791   DCHECK(CalledOnValidThread());
    792   if (is_connected())
    793     return ERR_SOCKET_IS_CONNECTED;
    794 
    795   if (loopback)
    796     socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
    797   else
    798     socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
    799   return OK;
    800 }
    801 
    802 // TODO(hubbe): Implement differentiated services for windows.
    803 // Note: setsockopt(IP_TOS) does not work on windows XP and later.
    804 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
    805   return ERR_NOT_IMPLEMENTED;
    806 }
    807 
    808 }  // namespace net
    809