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