• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
Detach()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:
ReadDelegate(Core * core)68     explicit ReadDelegate(Core* core) : core_(core) {}
~ReadDelegate()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:
WriteDelegate(Core * core)80     explicit WriteDelegate(Core* core) : core_(core) {}
~WriteDelegate()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 
Core(UDPSocketWin * socket)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 
~Core()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 
WatchForRead()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 
WatchForWrite()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 
OnObjectSignaled(HANDLE object)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 
OnObjectSignaled(HANDLE object)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 
UDPSocketWin(DatagramSocket::BindType bind_type,const RandIntCallback & rand_int_cb,net::NetLog * net_log,const net::NetLog::Source & source)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 
~UDPSocketWin()182 UDPSocketWin::~UDPSocketWin() {
183   Close();
184   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
185 }
186 
Close()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 
GetPeerAddress(IPEndPoint * address) const209 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 
GetLocalAddress(IPEndPoint * address) const230 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 
Read(IOBuffer * buf,int buf_len,const CompletionCallback & callback)253 int UDPSocketWin::Read(IOBuffer* buf,
254                        int buf_len,
255                        const CompletionCallback& callback) {
256   return RecvFrom(buf, buf_len, NULL, callback);
257 }
258 
RecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address,const CompletionCallback & callback)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 
Write(IOBuffer * buf,int buf_len,const CompletionCallback & callback)279 int UDPSocketWin::Write(IOBuffer* buf,
280                         int buf_len,
281                         const CompletionCallback& callback) {
282   return SendToOrWrite(buf, buf_len, NULL, callback);
283 }
284 
SendTo(IOBuffer * buf,int buf_len,const IPEndPoint & address,const CompletionCallback & callback)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 
SendToOrWrite(IOBuffer * buf,int buf_len,const IPEndPoint * address,const CompletionCallback & callback)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 
Connect(const IPEndPoint & address)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 
InternalConnect(const IPEndPoint & address)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 
Bind(const IPEndPoint & address)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 
CreateSocket(int addr_family)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 
SetReceiveBufferSize(int32 size)391 bool UDPSocketWin::SetReceiveBufferSize(int32 size) {
392   DCHECK(CalledOnValidThread());
393   int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
394                       reinterpret_cast<const char*>(&size), sizeof(size));
395   DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
396   return rv == 0;
397 }
398 
SetSendBufferSize(int32 size)399 bool UDPSocketWin::SetSendBufferSize(int32 size) {
400   DCHECK(CalledOnValidThread());
401   int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
402                       reinterpret_cast<const char*>(&size), sizeof(size));
403   DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
404   return rv == 0;
405 }
406 
AllowAddressReuse()407 void UDPSocketWin::AllowAddressReuse() {
408   DCHECK(CalledOnValidThread());
409   DCHECK(!is_connected());
410 
411   socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
412 }
413 
AllowBroadcast()414 void UDPSocketWin::AllowBroadcast() {
415   DCHECK(CalledOnValidThread());
416   DCHECK(!is_connected());
417 
418   socket_options_ |= SOCKET_OPTION_BROADCAST;
419 }
420 
DoReadCallback(int rv)421 void UDPSocketWin::DoReadCallback(int rv) {
422   DCHECK_NE(rv, ERR_IO_PENDING);
423   DCHECK(!read_callback_.is_null());
424 
425   // since Run may result in Read being called, clear read_callback_ up front.
426   CompletionCallback c = read_callback_;
427   read_callback_.Reset();
428   c.Run(rv);
429 }
430 
DoWriteCallback(int rv)431 void UDPSocketWin::DoWriteCallback(int rv) {
432   DCHECK_NE(rv, ERR_IO_PENDING);
433   DCHECK(!write_callback_.is_null());
434 
435   // since Run may result in Write being called, clear write_callback_ up front.
436   CompletionCallback c = write_callback_;
437   write_callback_.Reset();
438   c.Run(rv);
439 }
440 
DidCompleteRead()441 void UDPSocketWin::DidCompleteRead() {
442   DWORD num_bytes, flags;
443   BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
444                                    &num_bytes, FALSE, &flags);
445   WSAResetEvent(core_->read_overlapped_.hEvent);
446   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
447   // Convert address.
448   if (recv_from_address_ && result >= 0) {
449     if (!ReceiveAddressToIPEndpoint(recv_from_address_))
450       result = ERR_ADDRESS_INVALID;
451   }
452   LogRead(result, core_->read_iobuffer_->data());
453   core_->read_iobuffer_ = NULL;
454   recv_from_address_ = NULL;
455   DoReadCallback(result);
456 }
457 
LogRead(int result,const char * bytes) const458 void UDPSocketWin::LogRead(int result, const char* bytes) const {
459   if (result < 0) {
460     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
461     return;
462   }
463 
464   if (net_log_.IsLoggingAllEvents()) {
465     // Get address for logging, if |address| is NULL.
466     IPEndPoint address;
467     bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
468     net_log_.AddEvent(
469         NetLog::TYPE_UDP_BYTES_RECEIVED,
470         CreateNetLogUDPDataTranferCallback(
471             result, bytes,
472             is_address_valid ? &address : NULL));
473   }
474 
475   base::StatsCounter read_bytes("udp.read_bytes");
476   read_bytes.Add(result);
477 }
478 
DidCompleteWrite()479 void UDPSocketWin::DidCompleteWrite() {
480   DWORD num_bytes, flags;
481   BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
482                                    &num_bytes, FALSE, &flags);
483   WSAResetEvent(core_->write_overlapped_.hEvent);
484   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
485   LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
486 
487   send_to_address_.reset();
488   core_->write_iobuffer_ = NULL;
489   DoWriteCallback(result);
490 }
491 
LogWrite(int result,const char * bytes,const IPEndPoint * address) const492 void UDPSocketWin::LogWrite(int result,
493                             const char* bytes,
494                             const IPEndPoint* address) const {
495   if (result < 0) {
496     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
497     return;
498   }
499 
500   if (net_log_.IsLoggingAllEvents()) {
501     net_log_.AddEvent(
502         NetLog::TYPE_UDP_BYTES_SENT,
503         CreateNetLogUDPDataTranferCallback(result, bytes, address));
504   }
505 
506   base::StatsCounter write_bytes("udp.write_bytes");
507   write_bytes.Add(result);
508 }
509 
InternalRecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address)510 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
511                                    IPEndPoint* address) {
512   DCHECK(!core_->read_iobuffer_);
513   SockaddrStorage& storage = core_->recv_addr_storage_;
514   storage.addr_len = sizeof(storage.addr_storage);
515 
516   WSABUF read_buffer;
517   read_buffer.buf = buf->data();
518   read_buffer.len = buf_len;
519 
520   DWORD flags = 0;
521   DWORD num;
522   CHECK_NE(INVALID_SOCKET, socket_);
523   AssertEventNotSignaled(core_->read_overlapped_.hEvent);
524   int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
525                        &storage.addr_len, &core_->read_overlapped_, NULL);
526   if (rv == 0) {
527     if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
528       int result = num;
529       // Convert address.
530       if (address && result >= 0) {
531         if (!ReceiveAddressToIPEndpoint(address))
532           result = ERR_FAILED;
533       }
534       LogRead(result, buf->data());
535       return result;
536     }
537   } else {
538     int os_error = WSAGetLastError();
539     if (os_error != WSA_IO_PENDING) {
540       int result = MapSystemError(os_error);
541       LogRead(result, NULL);
542       return result;
543     }
544   }
545   core_->WatchForRead();
546   core_->read_iobuffer_ = buf;
547   return ERR_IO_PENDING;
548 }
549 
InternalSendTo(IOBuffer * buf,int buf_len,const IPEndPoint * address)550 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
551                                  const IPEndPoint* address) {
552   DCHECK(!core_->write_iobuffer_);
553   SockaddrStorage storage;
554   struct sockaddr* addr = storage.addr;
555   // Convert address.
556   if (!address) {
557     addr = NULL;
558     storage.addr_len = 0;
559   } else {
560     if (!address->ToSockAddr(addr, &storage.addr_len)) {
561       int result = ERR_FAILED;
562       LogWrite(result, NULL, NULL);
563       return result;
564     }
565   }
566 
567   WSABUF write_buffer;
568   write_buffer.buf = buf->data();
569   write_buffer.len = buf_len;
570 
571   DWORD flags = 0;
572   DWORD num;
573   AssertEventNotSignaled(core_->write_overlapped_.hEvent);
574   int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
575                      addr, storage.addr_len, &core_->write_overlapped_, NULL);
576   if (rv == 0) {
577     if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
578       int result = num;
579       LogWrite(result, buf->data(), address);
580       return result;
581     }
582   } else {
583     int os_error = WSAGetLastError();
584     if (os_error != WSA_IO_PENDING) {
585       int result = MapSystemError(os_error);
586       LogWrite(result, NULL, NULL);
587       return result;
588     }
589   }
590 
591   core_->WatchForWrite();
592   core_->write_iobuffer_ = buf;
593   return ERR_IO_PENDING;
594 }
595 
SetSocketOptions()596 int UDPSocketWin::SetSocketOptions() {
597   BOOL true_value = 1;
598   if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
599     int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
600                         reinterpret_cast<const char*>(&true_value),
601                         sizeof(true_value));
602     if (rv < 0)
603       return MapSystemError(WSAGetLastError());
604   }
605   if (socket_options_ & SOCKET_OPTION_BROADCAST) {
606     int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
607                         reinterpret_cast<const char*>(&true_value),
608                         sizeof(true_value));
609     if (rv < 0)
610       return MapSystemError(WSAGetLastError());
611   }
612   if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
613     DWORD loop = 0;
614     int protocol_level =
615         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
616     int option =
617         addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
618     int rv = setsockopt(socket_, protocol_level, option,
619                         reinterpret_cast<const char*>(&loop), sizeof(loop));
620     if (rv < 0)
621       return MapSystemError(WSAGetLastError());
622   }
623   if (multicast_time_to_live_ != 1) {
624     DWORD hops = multicast_time_to_live_;
625     int protocol_level =
626         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
627     int option =
628         addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
629     int rv = setsockopt(socket_, protocol_level, option,
630                         reinterpret_cast<const char*>(&hops), sizeof(hops));
631     if (rv < 0)
632       return MapSystemError(WSAGetLastError());
633   }
634   if (multicast_interface_ != 0) {
635     switch (addr_family_) {
636       case AF_INET: {
637         in_addr address;
638         address.s_addr = htonl(multicast_interface_);
639         int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
640                             reinterpret_cast<const char*>(&address),
641                             sizeof(address));
642         if (rv)
643           return MapSystemError(WSAGetLastError());
644         break;
645       }
646       case AF_INET6: {
647         uint32 interface_index = multicast_interface_;
648         int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
649                             reinterpret_cast<const char*>(&interface_index),
650                             sizeof(interface_index));
651         if (rv)
652           return MapSystemError(WSAGetLastError());
653         break;
654       }
655       default:
656         NOTREACHED() << "Invalid address family";
657         return ERR_ADDRESS_INVALID;
658     }
659   }
660   return OK;
661 }
662 
DoBind(const IPEndPoint & address)663 int UDPSocketWin::DoBind(const IPEndPoint& address) {
664   SockaddrStorage storage;
665   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
666     return ERR_ADDRESS_INVALID;
667   int rv = bind(socket_, storage.addr, storage.addr_len);
668   if (rv == 0)
669     return OK;
670   int last_error = WSAGetLastError();
671   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
672   // Map some codes that are special to bind() separately.
673   if (last_error == WSAEACCES || last_error == WSAEINVAL)
674     return ERR_ADDRESS_IN_USE;
675   return MapSystemError(last_error);
676 }
677 
RandomBind(const IPAddressNumber & address)678 int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
679   DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
680 
681   for (int i = 0; i < kBindRetries; ++i) {
682     int rv = DoBind(IPEndPoint(address,
683                                rand_int_cb_.Run(kPortStart, kPortEnd)));
684     if (rv == OK || rv != ERR_ADDRESS_IN_USE)
685       return rv;
686   }
687   return DoBind(IPEndPoint(address, 0));
688 }
689 
ReceiveAddressToIPEndpoint(IPEndPoint * address) const690 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
691   SockaddrStorage& storage = core_->recv_addr_storage_;
692   return address->FromSockAddr(storage.addr, storage.addr_len);
693 }
694 
JoinGroup(const IPAddressNumber & group_address) const695 int UDPSocketWin::JoinGroup(
696     const IPAddressNumber& group_address) const {
697   DCHECK(CalledOnValidThread());
698   if (!is_connected())
699     return ERR_SOCKET_NOT_CONNECTED;
700 
701   switch (group_address.size()) {
702     case kIPv4AddressSize: {
703       if (addr_family_ != AF_INET)
704         return ERR_ADDRESS_INVALID;
705       ip_mreq mreq;
706       mreq.imr_interface.s_addr = htonl(multicast_interface_);
707       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
708       int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
709                           reinterpret_cast<const char*>(&mreq),
710                           sizeof(mreq));
711       if (rv)
712         return MapSystemError(WSAGetLastError());
713       return OK;
714     }
715     case kIPv6AddressSize: {
716       if (addr_family_ != AF_INET6)
717         return ERR_ADDRESS_INVALID;
718       ipv6_mreq mreq;
719       mreq.ipv6mr_interface = multicast_interface_;
720       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
721       int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
722                           reinterpret_cast<const char*>(&mreq),
723                           sizeof(mreq));
724       if (rv)
725         return MapSystemError(WSAGetLastError());
726       return OK;
727     }
728     default:
729       NOTREACHED() << "Invalid address family";
730       return ERR_ADDRESS_INVALID;
731   }
732 }
733 
LeaveGroup(const IPAddressNumber & group_address) const734 int UDPSocketWin::LeaveGroup(
735     const IPAddressNumber& group_address) const {
736   DCHECK(CalledOnValidThread());
737   if (!is_connected())
738     return ERR_SOCKET_NOT_CONNECTED;
739 
740   switch (group_address.size()) {
741     case kIPv4AddressSize: {
742       if (addr_family_ != AF_INET)
743         return ERR_ADDRESS_INVALID;
744       ip_mreq mreq;
745       mreq.imr_interface.s_addr = htonl(multicast_interface_);
746       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
747       int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
748                           reinterpret_cast<const char*>(&mreq), sizeof(mreq));
749       if (rv)
750         return MapSystemError(WSAGetLastError());
751       return OK;
752     }
753     case kIPv6AddressSize: {
754       if (addr_family_ != AF_INET6)
755         return ERR_ADDRESS_INVALID;
756       ipv6_mreq mreq;
757       mreq.ipv6mr_interface = multicast_interface_;
758       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
759       int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
760                           reinterpret_cast<const char*>(&mreq), sizeof(mreq));
761       if (rv)
762         return MapSystemError(WSAGetLastError());
763       return OK;
764     }
765     default:
766       NOTREACHED() << "Invalid address family";
767       return ERR_ADDRESS_INVALID;
768   }
769 }
770 
SetMulticastInterface(uint32 interface_index)771 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
772   DCHECK(CalledOnValidThread());
773   if (is_connected())
774     return ERR_SOCKET_IS_CONNECTED;
775   multicast_interface_ = interface_index;
776   return OK;
777 }
778 
SetMulticastTimeToLive(int time_to_live)779 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
780   DCHECK(CalledOnValidThread());
781   if (is_connected())
782     return ERR_SOCKET_IS_CONNECTED;
783 
784   if (time_to_live < 0 || time_to_live > 255)
785     return ERR_INVALID_ARGUMENT;
786   multicast_time_to_live_ = time_to_live;
787   return OK;
788 }
789 
SetMulticastLoopbackMode(bool loopback)790 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
791   DCHECK(CalledOnValidThread());
792   if (is_connected())
793     return ERR_SOCKET_IS_CONNECTED;
794 
795   if (loopback)
796     socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
797   else
798     socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
799   return OK;
800 }
801 
802 // TODO(hubbe): Implement differentiated services for windows.
803 // Note: setsockopt(IP_TOS) does not work on windows XP and later.
SetDiffServCodePoint(DiffServCodePoint dscp)804 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
805   return ERR_NOT_IMPLEMENTED;
806 }
807 
808 }  // namespace net
809