Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / udp / udp_socket_win.cc
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 int 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
413 int 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
434 void UDPSocketWin::AllowAddressReuse() {
435   DCHECK(CalledOnValidThread());
436   DCHECK(!is_connected());
437
438   socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
439 }
440
441 void UDPSocketWin::AllowBroadcast() {
442   DCHECK(CalledOnValidThread());
443   DCHECK(!is_connected());
444
445   socket_options_ |= SOCKET_OPTION_BROADCAST;
446 }
447
448 void 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
458 void 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
468 void 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
485 void 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
506 void 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
519 void 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
537 int 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
577 int 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
623 int 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
690 int 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
710 int 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
722 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
723   SockaddrStorage& storage = core_->recv_addr_storage_;
724   return address->FromSockAddr(storage.addr, storage.addr_len);
725 }
726
727 int 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
766 int 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
803 int 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
811 int 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
822 int 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.
836 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
837   return ERR_NOT_IMPLEMENTED;
838 }
839
840 void UDPSocketWin::DetachFromThread() {
841   base::NonThreadSafe::DetachFromThread();
842 }
843
844 }  // namespace net