- add sources.
[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/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/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_time_to_live_(1),
170       bind_type_(bind_type),
171       rand_int_cb_(rand_int_cb),
172       recv_from_address_(NULL),
173       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
174   EnsureWinsockInit();
175   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
176                       source.ToEventParametersCallback());
177   if (bind_type == DatagramSocket::RANDOM_BIND)
178     DCHECK(!rand_int_cb.is_null());
179 }
180
181 UDPSocketWin::~UDPSocketWin() {
182   Close();
183   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
184 }
185
186 void UDPSocketWin::Close() {
187   DCHECK(CalledOnValidThread());
188
189   if (!is_connected())
190     return;
191
192   // Zero out any pending read/write callback state.
193   read_callback_.Reset();
194   recv_from_address_ = NULL;
195   write_callback_.Reset();
196
197   base::TimeTicks start_time = base::TimeTicks::Now();
198   closesocket(socket_);
199   UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
200                       base::TimeTicks::Now() - start_time);
201   socket_ = INVALID_SOCKET;
202   addr_family_ = 0;
203
204   core_->Detach();
205   core_ = NULL;
206 }
207
208 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
209   DCHECK(CalledOnValidThread());
210   DCHECK(address);
211   if (!is_connected())
212     return ERR_SOCKET_NOT_CONNECTED;
213
214   // TODO(szym): Simplify. http://crbug.com/126152
215   if (!remote_address_.get()) {
216     SockaddrStorage storage;
217     if (getpeername(socket_, storage.addr, &storage.addr_len))
218       return MapSystemError(WSAGetLastError());
219     scoped_ptr<IPEndPoint> address(new IPEndPoint());
220     if (!address->FromSockAddr(storage.addr, storage.addr_len))
221       return ERR_ADDRESS_INVALID;
222     remote_address_.reset(address.release());
223   }
224
225   *address = *remote_address_;
226   return OK;
227 }
228
229 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
230   DCHECK(CalledOnValidThread());
231   DCHECK(address);
232   if (!is_connected())
233     return ERR_SOCKET_NOT_CONNECTED;
234
235   // TODO(szym): Simplify. http://crbug.com/126152
236   if (!local_address_.get()) {
237     SockaddrStorage storage;
238     if (getsockname(socket_, storage.addr, &storage.addr_len))
239       return MapSystemError(WSAGetLastError());
240     scoped_ptr<IPEndPoint> address(new IPEndPoint());
241     if (!address->FromSockAddr(storage.addr, storage.addr_len))
242       return ERR_ADDRESS_INVALID;
243     local_address_.reset(address.release());
244     net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
245                       CreateNetLogUDPConnectCallback(local_address_.get()));
246   }
247
248   *address = *local_address_;
249   return OK;
250 }
251
252 int UDPSocketWin::Read(IOBuffer* buf,
253                        int buf_len,
254                        const CompletionCallback& callback) {
255   return RecvFrom(buf, buf_len, NULL, callback);
256 }
257
258 int UDPSocketWin::RecvFrom(IOBuffer* buf,
259                            int buf_len,
260                            IPEndPoint* address,
261                            const CompletionCallback& callback) {
262   DCHECK(CalledOnValidThread());
263   DCHECK_NE(INVALID_SOCKET, socket_);
264   DCHECK(read_callback_.is_null());
265   DCHECK(!recv_from_address_);
266   DCHECK(!callback.is_null());  // Synchronous operation not supported.
267   DCHECK_GT(buf_len, 0);
268
269   int nread = InternalRecvFrom(buf, buf_len, address);
270   if (nread != ERR_IO_PENDING)
271     return nread;
272
273   read_callback_ = callback;
274   recv_from_address_ = address;
275   return ERR_IO_PENDING;
276 }
277
278 int UDPSocketWin::Write(IOBuffer* buf,
279                         int buf_len,
280                         const CompletionCallback& callback) {
281   return SendToOrWrite(buf, buf_len, NULL, callback);
282 }
283
284 int UDPSocketWin::SendTo(IOBuffer* buf,
285                          int buf_len,
286                          const IPEndPoint& address,
287                          const CompletionCallback& callback) {
288   return SendToOrWrite(buf, buf_len, &address, callback);
289 }
290
291 int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
292                                 int buf_len,
293                                 const IPEndPoint* address,
294                                 const CompletionCallback& callback) {
295   DCHECK(CalledOnValidThread());
296   DCHECK_NE(INVALID_SOCKET, socket_);
297   DCHECK(write_callback_.is_null());
298   DCHECK(!callback.is_null());  // Synchronous operation not supported.
299   DCHECK_GT(buf_len, 0);
300   DCHECK(!send_to_address_.get());
301
302   int nwrite = InternalSendTo(buf, buf_len, address);
303   if (nwrite != ERR_IO_PENDING)
304     return nwrite;
305
306   if (address)
307     send_to_address_.reset(new IPEndPoint(*address));
308   write_callback_ = callback;
309   return ERR_IO_PENDING;
310 }
311
312 int UDPSocketWin::Connect(const IPEndPoint& address) {
313   net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
314                       CreateNetLogUDPConnectCallback(&address));
315   int rv = InternalConnect(address);
316   if (rv != OK)
317     Close();
318   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
319   return rv;
320 }
321
322 int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
323   DCHECK(!is_connected());
324   DCHECK(!remote_address_.get());
325   int rv = CreateSocket(address);
326   if (rv < 0)
327     return rv;
328
329   if (bind_type_ == DatagramSocket::RANDOM_BIND)
330     rv = RandomBind(address);
331   // else connect() does the DatagramSocket::DEFAULT_BIND
332
333   if (rv < 0) {
334     Close();
335     return rv;
336   }
337
338   SockaddrStorage storage;
339   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
340     return ERR_ADDRESS_INVALID;
341
342   rv = connect(socket_, storage.addr, storage.addr_len);
343   if (rv < 0) {
344     // Close() may change the last error. Map it beforehand.
345     int result = MapSystemError(WSAGetLastError());
346     Close();
347     return result;
348   }
349
350   remote_address_.reset(new IPEndPoint(address));
351   return rv;
352 }
353
354 int UDPSocketWin::Bind(const IPEndPoint& address) {
355   DCHECK(!is_connected());
356   int rv = CreateSocket(address);
357   if (rv < 0)
358     return rv;
359   rv = SetSocketOptions();
360   if (rv < 0) {
361     Close();
362     return rv;
363   }
364   rv = DoBind(address);
365   if (rv < 0) {
366     Close();
367     return rv;
368   }
369   local_address_.reset();
370   return rv;
371 }
372
373 int UDPSocketWin::CreateSocket(const IPEndPoint& address) {
374   addr_family_ = address.GetSockAddrFamily();
375   socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
376   if (socket_ == INVALID_SOCKET)
377     return MapSystemError(WSAGetLastError());
378   core_ = new Core(this);
379   return OK;
380 }
381
382 bool UDPSocketWin::SetReceiveBufferSize(int32 size) {
383   DCHECK(CalledOnValidThread());
384   int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
385                       reinterpret_cast<const char*>(&size), sizeof(size));
386   DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
387   return rv == 0;
388 }
389
390 bool UDPSocketWin::SetSendBufferSize(int32 size) {
391   DCHECK(CalledOnValidThread());
392   int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
393                       reinterpret_cast<const char*>(&size), sizeof(size));
394   DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
395   return rv == 0;
396 }
397
398 void UDPSocketWin::AllowAddressReuse() {
399   DCHECK(CalledOnValidThread());
400   DCHECK(!is_connected());
401
402   socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
403 }
404
405 void UDPSocketWin::AllowBroadcast() {
406   DCHECK(CalledOnValidThread());
407   DCHECK(!is_connected());
408
409   socket_options_ |= SOCKET_OPTION_BROADCAST;
410 }
411
412 void UDPSocketWin::DoReadCallback(int rv) {
413   DCHECK_NE(rv, ERR_IO_PENDING);
414   DCHECK(!read_callback_.is_null());
415
416   // since Run may result in Read being called, clear read_callback_ up front.
417   CompletionCallback c = read_callback_;
418   read_callback_.Reset();
419   c.Run(rv);
420 }
421
422 void UDPSocketWin::DoWriteCallback(int rv) {
423   DCHECK_NE(rv, ERR_IO_PENDING);
424   DCHECK(!write_callback_.is_null());
425
426   // since Run may result in Write being called, clear write_callback_ up front.
427   CompletionCallback c = write_callback_;
428   write_callback_.Reset();
429   c.Run(rv);
430 }
431
432 void UDPSocketWin::DidCompleteRead() {
433   DWORD num_bytes, flags;
434   BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
435                                    &num_bytes, FALSE, &flags);
436   WSAResetEvent(core_->read_overlapped_.hEvent);
437   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
438   // Convert address.
439   if (recv_from_address_ && result >= 0) {
440     if (!ReceiveAddressToIPEndpoint(recv_from_address_))
441       result = ERR_ADDRESS_INVALID;
442   }
443   LogRead(result, core_->read_iobuffer_->data());
444   core_->read_iobuffer_ = NULL;
445   recv_from_address_ = NULL;
446   DoReadCallback(result);
447 }
448
449 void UDPSocketWin::LogRead(int result, const char* bytes) const {
450   if (result < 0) {
451     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
452     return;
453   }
454
455   if (net_log_.IsLoggingAllEvents()) {
456     // Get address for logging, if |address| is NULL.
457     IPEndPoint address;
458     bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
459     net_log_.AddEvent(
460         NetLog::TYPE_UDP_BYTES_RECEIVED,
461         CreateNetLogUDPDataTranferCallback(
462             result, bytes,
463             is_address_valid ? &address : NULL));
464   }
465
466   base::StatsCounter read_bytes("udp.read_bytes");
467   read_bytes.Add(result);
468 }
469
470 void UDPSocketWin::DidCompleteWrite() {
471   DWORD num_bytes, flags;
472   BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
473                                    &num_bytes, FALSE, &flags);
474   WSAResetEvent(core_->write_overlapped_.hEvent);
475   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
476   LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
477
478   send_to_address_.reset();
479   core_->write_iobuffer_ = NULL;
480   DoWriteCallback(result);
481 }
482
483 void UDPSocketWin::LogWrite(int result,
484                             const char* bytes,
485                             const IPEndPoint* address) const {
486   if (result < 0) {
487     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
488     return;
489   }
490
491   if (net_log_.IsLoggingAllEvents()) {
492     net_log_.AddEvent(
493         NetLog::TYPE_UDP_BYTES_SENT,
494         CreateNetLogUDPDataTranferCallback(result, bytes, address));
495   }
496
497   base::StatsCounter write_bytes("udp.write_bytes");
498   write_bytes.Add(result);
499 }
500
501 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
502                                    IPEndPoint* address) {
503   DCHECK(!core_->read_iobuffer_);
504   SockaddrStorage& storage = core_->recv_addr_storage_;
505   storage.addr_len = sizeof(storage.addr_storage);
506
507   WSABUF read_buffer;
508   read_buffer.buf = buf->data();
509   read_buffer.len = buf_len;
510
511   DWORD flags = 0;
512   DWORD num;
513   CHECK_NE(INVALID_SOCKET, socket_);
514   AssertEventNotSignaled(core_->read_overlapped_.hEvent);
515   int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
516                        &storage.addr_len, &core_->read_overlapped_, NULL);
517   if (rv == 0) {
518     if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
519       int result = num;
520       // Convert address.
521       if (address && result >= 0) {
522         if (!ReceiveAddressToIPEndpoint(address))
523           result = ERR_FAILED;
524       }
525       LogRead(result, buf->data());
526       return result;
527     }
528   } else {
529     int os_error = WSAGetLastError();
530     if (os_error != WSA_IO_PENDING) {
531       int result = MapSystemError(os_error);
532       LogRead(result, NULL);
533       return result;
534     }
535   }
536   core_->WatchForRead();
537   core_->read_iobuffer_ = buf;
538   return ERR_IO_PENDING;
539 }
540
541 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
542                                  const IPEndPoint* address) {
543   DCHECK(!core_->write_iobuffer_);
544   SockaddrStorage storage;
545   struct sockaddr* addr = storage.addr;
546   // Convert address.
547   if (!address) {
548     addr = NULL;
549     storage.addr_len = 0;
550   } else {
551     if (!address->ToSockAddr(addr, &storage.addr_len)) {
552       int result = ERR_FAILED;
553       LogWrite(result, NULL, NULL);
554       return result;
555     }
556   }
557
558   WSABUF write_buffer;
559   write_buffer.buf = buf->data();
560   write_buffer.len = buf_len;
561
562   DWORD flags = 0;
563   DWORD num;
564   AssertEventNotSignaled(core_->write_overlapped_.hEvent);
565   int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
566                      addr, storage.addr_len, &core_->write_overlapped_, NULL);
567   if (rv == 0) {
568     if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
569       int result = num;
570       LogWrite(result, buf->data(), address);
571       return result;
572     }
573   } else {
574     int os_error = WSAGetLastError();
575     if (os_error != WSA_IO_PENDING) {
576       int result = MapSystemError(os_error);
577       LogWrite(result, NULL, NULL);
578       return result;
579     }
580   }
581
582   core_->WatchForWrite();
583   core_->write_iobuffer_ = buf;
584   return ERR_IO_PENDING;
585 }
586
587 int UDPSocketWin::SetSocketOptions() {
588   BOOL true_value = 1;
589   if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
590     int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
591                         reinterpret_cast<const char*>(&true_value),
592                         sizeof(true_value));
593     if (rv < 0)
594       return MapSystemError(WSAGetLastError());
595   }
596   if (socket_options_ & SOCKET_OPTION_BROADCAST) {
597     int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
598                         reinterpret_cast<const char*>(&true_value),
599                         sizeof(true_value));
600     if (rv < 0)
601       return MapSystemError(WSAGetLastError());
602   }
603   if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
604     DWORD loop = 0;
605     int protocol_level =
606         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
607     int option =
608         addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
609     int rv = setsockopt(socket_, protocol_level, option,
610                         reinterpret_cast<const char*>(&loop), sizeof(loop));
611     if (rv < 0)
612       return MapSystemError(WSAGetLastError());
613   }
614   if (multicast_time_to_live_ != 1) {
615     DWORD hops = multicast_time_to_live_;
616     int protocol_level =
617         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
618     int option =
619         addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
620     int rv = setsockopt(socket_, protocol_level, option,
621                         reinterpret_cast<const char*>(&hops), sizeof(hops));
622     if (rv < 0)
623       return MapSystemError(WSAGetLastError());
624   }
625   return OK;
626 }
627
628 int UDPSocketWin::DoBind(const IPEndPoint& address) {
629   SockaddrStorage storage;
630   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
631     return ERR_ADDRESS_INVALID;
632   int rv = bind(socket_, storage.addr, storage.addr_len);
633   return rv < 0 ? MapSystemError(WSAGetLastError()) : rv;
634 }
635
636 int UDPSocketWin::RandomBind(const IPEndPoint& address) {
637   DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
638
639   // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
640   IPAddressNumber ip(address.address().size());
641
642   for (int i = 0; i < kBindRetries; ++i) {
643     int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
644     if (rv == OK || rv != ERR_ADDRESS_IN_USE)
645       return rv;
646   }
647   return DoBind(IPEndPoint(ip, 0));
648 }
649
650 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
651   SockaddrStorage& storage = core_->recv_addr_storage_;
652   return address->FromSockAddr(storage.addr, storage.addr_len);
653 }
654
655 int UDPSocketWin::JoinGroup(
656     const IPAddressNumber& group_address) const {
657   DCHECK(CalledOnValidThread());
658   if (!is_connected())
659     return ERR_SOCKET_NOT_CONNECTED;
660
661   switch (group_address.size()) {
662     case kIPv4AddressSize: {
663       if (addr_family_ != AF_INET)
664         return ERR_ADDRESS_INVALID;
665       ip_mreq mreq;
666       mreq.imr_interface.s_addr = INADDR_ANY;
667       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
668       int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
669                           reinterpret_cast<const char*>(&mreq),
670                           sizeof(mreq));
671       if (rv)
672         return MapSystemError(WSAGetLastError());
673       return OK;
674     }
675     case kIPv6AddressSize: {
676       if (addr_family_ != AF_INET6)
677         return ERR_ADDRESS_INVALID;
678       ipv6_mreq mreq;
679       mreq.ipv6mr_interface = 0;  // 0 indicates default multicast interface.
680       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
681       int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
682                           reinterpret_cast<const char*>(&mreq),
683                           sizeof(mreq));
684       if (rv)
685         return MapSystemError(WSAGetLastError());
686       return OK;
687     }
688     default:
689       NOTREACHED() << "Invalid address family";
690       return ERR_ADDRESS_INVALID;
691   }
692 }
693
694 int UDPSocketWin::LeaveGroup(
695     const IPAddressNumber& group_address) const {
696   DCHECK(CalledOnValidThread());
697   if (!is_connected())
698     return ERR_SOCKET_NOT_CONNECTED;
699
700   switch (group_address.size()) {
701     case kIPv4AddressSize: {
702       if (addr_family_ != AF_INET)
703         return ERR_ADDRESS_INVALID;
704       ip_mreq mreq;
705       mreq.imr_interface.s_addr = INADDR_ANY;
706       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
707       int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
708                       reinterpret_cast<const char*>(&mreq),
709                       sizeof(mreq));
710       if (rv)
711         return MapSystemError(WSAGetLastError());
712       return OK;
713     }
714     case kIPv6AddressSize: {
715       if (addr_family_ != AF_INET6)
716         return ERR_ADDRESS_INVALID;
717       ipv6_mreq mreq;
718       mreq.ipv6mr_interface = 0;  // 0 indicates default multicast interface.
719       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
720       int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
721                       reinterpret_cast<const char*>(&mreq),
722                       sizeof(mreq));
723       if (rv)
724         return MapSystemError(WSAGetLastError());
725       return OK;
726     }
727     default:
728       NOTREACHED() << "Invalid address family";
729       return ERR_ADDRESS_INVALID;
730   }
731 }
732
733 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
734   DCHECK(CalledOnValidThread());
735   if (is_connected())
736     return ERR_SOCKET_IS_CONNECTED;
737
738   if (time_to_live < 0 || time_to_live > 255)
739     return ERR_INVALID_ARGUMENT;
740   multicast_time_to_live_ = time_to_live;
741   return OK;
742 }
743
744 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
745   DCHECK(CalledOnValidThread());
746   if (is_connected())
747     return ERR_SOCKET_IS_CONNECTED;
748
749   if (loopback)
750     socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
751   else
752     socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
753   return OK;
754 }
755
756 // TODO(hubbe): Implement differentiated services for windows.
757 // Note: setsockopt(IP_TOS) does not work on windows XP and later.
758 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
759   return ERR_NOT_IMPLEMENTED;
760 }
761
762 }  // namespace net