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
26namespace {
27
28const int kBindRetries = 10;
29const int kPortStart = 1024;
30const int kPortEnd = 65535;
31
32}  // namespace
33
34namespace 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.
41class 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
108UDPSocketWin::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
119UDPSocketWin::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
130void 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
137void 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
144void 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
152void 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
162UDPSocketWin::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
182UDPSocketWin::~UDPSocketWin() {
183  Close();
184  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
185}
186
187void 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
209int 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
230int 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
253int UDPSocketWin::Read(IOBuffer* buf,
254                       int buf_len,
255                       const CompletionCallback& callback) {
256  return RecvFrom(buf, buf_len, NULL, callback);
257}
258
259int 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
279int UDPSocketWin::Write(IOBuffer* buf,
280                        int buf_len,
281                        const CompletionCallback& callback) {
282  return SendToOrWrite(buf, buf_len, NULL, callback);
283}
284
285int 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
292int 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
313int 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
323int 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
363int 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
382int 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
391int 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  if (rv != 0)
396    return MapSystemError(WSAGetLastError());
397
398  // According to documentation, setsockopt may succeed, but we need to check
399  // the results via getsockopt to be sure it works on Windows.
400  int32 actual_size = 0;
401  int option_size = sizeof(actual_size);
402  rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
403                  reinterpret_cast<char*>(&actual_size), &option_size);
404  if (rv != 0)
405    return MapSystemError(WSAGetLastError());
406  if (actual_size >= size)
407    return OK;
408  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
409                              actual_size, 1000, 1000000, 50);
410  return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE;
411}
412
413int UDPSocketWin::SetSendBufferSize(int32 size) {
414  DCHECK(CalledOnValidThread());
415  int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
416                      reinterpret_cast<const char*>(&size), sizeof(size));
417  if (rv != 0)
418    return MapSystemError(WSAGetLastError());
419  // According to documentation, setsockopt may succeed, but we need to check
420  // the results via getsockopt to be sure it works on Windows.
421  int32 actual_size = 0;
422  int option_size = sizeof(actual_size);
423  rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
424                  reinterpret_cast<char*>(&actual_size), &option_size);
425  if (rv != 0)
426    return MapSystemError(WSAGetLastError());
427  if (actual_size >= size)
428    return OK;
429  UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
430                              actual_size, 1000, 1000000, 50);
431  return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE;
432}
433
434void UDPSocketWin::AllowAddressReuse() {
435  DCHECK(CalledOnValidThread());
436  DCHECK(!is_connected());
437
438  socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
439}
440
441void UDPSocketWin::AllowBroadcast() {
442  DCHECK(CalledOnValidThread());
443  DCHECK(!is_connected());
444
445  socket_options_ |= SOCKET_OPTION_BROADCAST;
446}
447
448void UDPSocketWin::DoReadCallback(int rv) {
449  DCHECK_NE(rv, ERR_IO_PENDING);
450  DCHECK(!read_callback_.is_null());
451
452  // since Run may result in Read being called, clear read_callback_ up front.
453  CompletionCallback c = read_callback_;
454  read_callback_.Reset();
455  c.Run(rv);
456}
457
458void UDPSocketWin::DoWriteCallback(int rv) {
459  DCHECK_NE(rv, ERR_IO_PENDING);
460  DCHECK(!write_callback_.is_null());
461
462  // since Run may result in Write being called, clear write_callback_ up front.
463  CompletionCallback c = write_callback_;
464  write_callback_.Reset();
465  c.Run(rv);
466}
467
468void UDPSocketWin::DidCompleteRead() {
469  DWORD num_bytes, flags;
470  BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
471                                   &num_bytes, FALSE, &flags);
472  WSAResetEvent(core_->read_overlapped_.hEvent);
473  int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
474  // Convert address.
475  if (recv_from_address_ && result >= 0) {
476    if (!ReceiveAddressToIPEndpoint(recv_from_address_))
477      result = ERR_ADDRESS_INVALID;
478  }
479  LogRead(result, core_->read_iobuffer_->data());
480  core_->read_iobuffer_ = NULL;
481  recv_from_address_ = NULL;
482  DoReadCallback(result);
483}
484
485void UDPSocketWin::LogRead(int result, const char* bytes) const {
486  if (result < 0) {
487    net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
488    return;
489  }
490
491  if (net_log_.IsLogging()) {
492    // Get address for logging, if |address| is NULL.
493    IPEndPoint address;
494    bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
495    net_log_.AddEvent(
496        NetLog::TYPE_UDP_BYTES_RECEIVED,
497        CreateNetLogUDPDataTranferCallback(
498            result, bytes,
499            is_address_valid ? &address : NULL));
500  }
501
502  base::StatsCounter read_bytes("udp.read_bytes");
503  read_bytes.Add(result);
504}
505
506void UDPSocketWin::DidCompleteWrite() {
507  DWORD num_bytes, flags;
508  BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
509                                   &num_bytes, FALSE, &flags);
510  WSAResetEvent(core_->write_overlapped_.hEvent);
511  int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
512  LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
513
514  send_to_address_.reset();
515  core_->write_iobuffer_ = NULL;
516  DoWriteCallback(result);
517}
518
519void UDPSocketWin::LogWrite(int result,
520                            const char* bytes,
521                            const IPEndPoint* address) const {
522  if (result < 0) {
523    net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
524    return;
525  }
526
527  if (net_log_.IsLogging()) {
528    net_log_.AddEvent(
529        NetLog::TYPE_UDP_BYTES_SENT,
530        CreateNetLogUDPDataTranferCallback(result, bytes, address));
531  }
532
533  base::StatsCounter write_bytes("udp.write_bytes");
534  write_bytes.Add(result);
535}
536
537int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
538                                   IPEndPoint* address) {
539  DCHECK(!core_->read_iobuffer_);
540  SockaddrStorage& storage = core_->recv_addr_storage_;
541  storage.addr_len = sizeof(storage.addr_storage);
542
543  WSABUF read_buffer;
544  read_buffer.buf = buf->data();
545  read_buffer.len = buf_len;
546
547  DWORD flags = 0;
548  DWORD num;
549  CHECK_NE(INVALID_SOCKET, socket_);
550  AssertEventNotSignaled(core_->read_overlapped_.hEvent);
551  int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
552                       &storage.addr_len, &core_->read_overlapped_, NULL);
553  if (rv == 0) {
554    if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
555      int result = num;
556      // Convert address.
557      if (address && result >= 0) {
558        if (!ReceiveAddressToIPEndpoint(address))
559          result = ERR_ADDRESS_INVALID;
560      }
561      LogRead(result, buf->data());
562      return result;
563    }
564  } else {
565    int os_error = WSAGetLastError();
566    if (os_error != WSA_IO_PENDING) {
567      int result = MapSystemError(os_error);
568      LogRead(result, NULL);
569      return result;
570    }
571  }
572  core_->WatchForRead();
573  core_->read_iobuffer_ = buf;
574  return ERR_IO_PENDING;
575}
576
577int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
578                                 const IPEndPoint* address) {
579  DCHECK(!core_->write_iobuffer_);
580  SockaddrStorage storage;
581  struct sockaddr* addr = storage.addr;
582  // Convert address.
583  if (!address) {
584    addr = NULL;
585    storage.addr_len = 0;
586  } else {
587    if (!address->ToSockAddr(addr, &storage.addr_len)) {
588      int result = ERR_ADDRESS_INVALID;
589      LogWrite(result, NULL, NULL);
590      return result;
591    }
592  }
593
594  WSABUF write_buffer;
595  write_buffer.buf = buf->data();
596  write_buffer.len = buf_len;
597
598  DWORD flags = 0;
599  DWORD num;
600  AssertEventNotSignaled(core_->write_overlapped_.hEvent);
601  int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
602                     addr, storage.addr_len, &core_->write_overlapped_, NULL);
603  if (rv == 0) {
604    if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
605      int result = num;
606      LogWrite(result, buf->data(), address);
607      return result;
608    }
609  } else {
610    int os_error = WSAGetLastError();
611    if (os_error != WSA_IO_PENDING) {
612      int result = MapSystemError(os_error);
613      LogWrite(result, NULL, NULL);
614      return result;
615    }
616  }
617
618  core_->WatchForWrite();
619  core_->write_iobuffer_ = buf;
620  return ERR_IO_PENDING;
621}
622
623int UDPSocketWin::SetSocketOptions() {
624  BOOL true_value = 1;
625  if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
626    int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
627                        reinterpret_cast<const char*>(&true_value),
628                        sizeof(true_value));
629    if (rv < 0)
630      return MapSystemError(WSAGetLastError());
631  }
632  if (socket_options_ & SOCKET_OPTION_BROADCAST) {
633    int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
634                        reinterpret_cast<const char*>(&true_value),
635                        sizeof(true_value));
636    if (rv < 0)
637      return MapSystemError(WSAGetLastError());
638  }
639  if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
640    DWORD loop = 0;
641    int protocol_level =
642        addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
643    int option =
644        addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
645    int rv = setsockopt(socket_, protocol_level, option,
646                        reinterpret_cast<const char*>(&loop), sizeof(loop));
647    if (rv < 0)
648      return MapSystemError(WSAGetLastError());
649  }
650  if (multicast_time_to_live_ != 1) {
651    DWORD hops = multicast_time_to_live_;
652    int protocol_level =
653        addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
654    int option =
655        addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
656    int rv = setsockopt(socket_, protocol_level, option,
657                        reinterpret_cast<const char*>(&hops), sizeof(hops));
658    if (rv < 0)
659      return MapSystemError(WSAGetLastError());
660  }
661  if (multicast_interface_ != 0) {
662    switch (addr_family_) {
663      case AF_INET: {
664        in_addr address;
665        address.s_addr = htonl(multicast_interface_);
666        int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
667                            reinterpret_cast<const char*>(&address),
668                            sizeof(address));
669        if (rv)
670          return MapSystemError(WSAGetLastError());
671        break;
672      }
673      case AF_INET6: {
674        uint32 interface_index = multicast_interface_;
675        int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
676                            reinterpret_cast<const char*>(&interface_index),
677                            sizeof(interface_index));
678        if (rv)
679          return MapSystemError(WSAGetLastError());
680        break;
681      }
682      default:
683        NOTREACHED() << "Invalid address family";
684        return ERR_ADDRESS_INVALID;
685    }
686  }
687  return OK;
688}
689
690int UDPSocketWin::DoBind(const IPEndPoint& address) {
691  SockaddrStorage storage;
692  if (!address.ToSockAddr(storage.addr, &storage.addr_len))
693    return ERR_ADDRESS_INVALID;
694  int rv = bind(socket_, storage.addr, storage.addr_len);
695  if (rv == 0)
696    return OK;
697  int last_error = WSAGetLastError();
698  UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
699  // Map some codes that are special to bind() separately.
700  // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
701  //   returned instead of WSAEADDRINUSE, depending on whether the socket
702  //   option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
703  //   conflicting socket is owned by a different user account. See the MSDN
704  //   page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
705  if (last_error == WSAEACCES || last_error == WSAEADDRNOTAVAIL)
706    return ERR_ADDRESS_IN_USE;
707  return MapSystemError(last_error);
708}
709
710int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
711  DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
712
713  for (int i = 0; i < kBindRetries; ++i) {
714    int rv = DoBind(IPEndPoint(address,
715                               rand_int_cb_.Run(kPortStart, kPortEnd)));
716    if (rv == OK || rv != ERR_ADDRESS_IN_USE)
717      return rv;
718  }
719  return DoBind(IPEndPoint(address, 0));
720}
721
722bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
723  SockaddrStorage& storage = core_->recv_addr_storage_;
724  return address->FromSockAddr(storage.addr, storage.addr_len);
725}
726
727int UDPSocketWin::JoinGroup(
728    const IPAddressNumber& group_address) const {
729  DCHECK(CalledOnValidThread());
730  if (!is_connected())
731    return ERR_SOCKET_NOT_CONNECTED;
732
733  switch (group_address.size()) {
734    case kIPv4AddressSize: {
735      if (addr_family_ != AF_INET)
736        return ERR_ADDRESS_INVALID;
737      ip_mreq mreq;
738      mreq.imr_interface.s_addr = htonl(multicast_interface_);
739      memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
740      int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
741                          reinterpret_cast<const char*>(&mreq),
742                          sizeof(mreq));
743      if (rv)
744        return MapSystemError(WSAGetLastError());
745      return OK;
746    }
747    case kIPv6AddressSize: {
748      if (addr_family_ != AF_INET6)
749        return ERR_ADDRESS_INVALID;
750      ipv6_mreq mreq;
751      mreq.ipv6mr_interface = multicast_interface_;
752      memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
753      int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
754                          reinterpret_cast<const char*>(&mreq),
755                          sizeof(mreq));
756      if (rv)
757        return MapSystemError(WSAGetLastError());
758      return OK;
759    }
760    default:
761      NOTREACHED() << "Invalid address family";
762      return ERR_ADDRESS_INVALID;
763  }
764}
765
766int UDPSocketWin::LeaveGroup(
767    const IPAddressNumber& group_address) const {
768  DCHECK(CalledOnValidThread());
769  if (!is_connected())
770    return ERR_SOCKET_NOT_CONNECTED;
771
772  switch (group_address.size()) {
773    case kIPv4AddressSize: {
774      if (addr_family_ != AF_INET)
775        return ERR_ADDRESS_INVALID;
776      ip_mreq mreq;
777      mreq.imr_interface.s_addr = htonl(multicast_interface_);
778      memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
779      int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
780                          reinterpret_cast<const char*>(&mreq), sizeof(mreq));
781      if (rv)
782        return MapSystemError(WSAGetLastError());
783      return OK;
784    }
785    case kIPv6AddressSize: {
786      if (addr_family_ != AF_INET6)
787        return ERR_ADDRESS_INVALID;
788      ipv6_mreq mreq;
789      mreq.ipv6mr_interface = multicast_interface_;
790      memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
791      int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
792                          reinterpret_cast<const char*>(&mreq), sizeof(mreq));
793      if (rv)
794        return MapSystemError(WSAGetLastError());
795      return OK;
796    }
797    default:
798      NOTREACHED() << "Invalid address family";
799      return ERR_ADDRESS_INVALID;
800  }
801}
802
803int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
804  DCHECK(CalledOnValidThread());
805  if (is_connected())
806    return ERR_SOCKET_IS_CONNECTED;
807  multicast_interface_ = interface_index;
808  return OK;
809}
810
811int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
812  DCHECK(CalledOnValidThread());
813  if (is_connected())
814    return ERR_SOCKET_IS_CONNECTED;
815
816  if (time_to_live < 0 || time_to_live > 255)
817    return ERR_INVALID_ARGUMENT;
818  multicast_time_to_live_ = time_to_live;
819  return OK;
820}
821
822int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
823  DCHECK(CalledOnValidThread());
824  if (is_connected())
825    return ERR_SOCKET_IS_CONNECTED;
826
827  if (loopback)
828    socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
829  else
830    socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
831  return OK;
832}
833
834// TODO(hubbe): Implement differentiated services for windows.
835// Note: setsockopt(IP_TOS) does not work on windows XP and later.
836int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
837  return ERR_NOT_IMPLEMENTED;
838}
839
840void UDPSocketWin::DetachFromThread() {
841  base::NonThreadSafe::DetachFromThread();
842}
843
844}  // namespace net
845