• 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/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram.h"
14 #include "base/metrics/sparse_histogram.h"
15 #include "base/metrics/stats_counters.h"
16 #include "base/rand_util.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/ip_endpoint.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/net_log.h"
21 #include "net/base/net_util.h"
22 #include "net/base/winsock_init.h"
23 #include "net/base/winsock_util.h"
24 #include "net/socket/socket_descriptor.h"
25 #include "net/udp/udp_net_log_parameters.h"
26 
27 namespace {
28 
29 const int kBindRetries = 10;
30 const int kPortStart = 1024;
31 const int kPortEnd = 65535;
32 
33 }  // namespace
34 
35 namespace net {
36 
37 // This class encapsulates all the state that has to be preserved as long as
38 // there is a network IO operation in progress. If the owner UDPSocketWin
39 // is destroyed while an operation is in progress, the Core is detached and it
40 // lives until the operation completes and the OS doesn't reference any resource
41 // declared on this class anymore.
42 class UDPSocketWin::Core : public base::RefCounted<Core> {
43  public:
44   explicit Core(UDPSocketWin* socket);
45 
46   // Start watching for the end of a read or write operation.
47   void WatchForRead();
48   void WatchForWrite();
49 
50   // The UDPSocketWin is going away.
Detach()51   void Detach() { socket_ = NULL; }
52 
53   // The separate OVERLAPPED variables for asynchronous operation.
54   OVERLAPPED read_overlapped_;
55   OVERLAPPED write_overlapped_;
56 
57   // The buffers used in Read() and Write().
58   scoped_refptr<IOBuffer> read_iobuffer_;
59   scoped_refptr<IOBuffer> write_iobuffer_;
60 
61   // The address storage passed to WSARecvFrom().
62   SockaddrStorage recv_addr_storage_;
63 
64  private:
65   friend class base::RefCounted<Core>;
66 
67   class ReadDelegate : public base::win::ObjectWatcher::Delegate {
68    public:
ReadDelegate(Core * core)69     explicit ReadDelegate(Core* core) : core_(core) {}
~ReadDelegate()70     virtual ~ReadDelegate() {}
71 
72     // base::ObjectWatcher::Delegate methods:
73     virtual void OnObjectSignaled(HANDLE object);
74 
75    private:
76     Core* const core_;
77   };
78 
79   class WriteDelegate : public base::win::ObjectWatcher::Delegate {
80    public:
WriteDelegate(Core * core)81     explicit WriteDelegate(Core* core) : core_(core) {}
~WriteDelegate()82     virtual ~WriteDelegate() {}
83 
84     // base::ObjectWatcher::Delegate methods:
85     virtual void OnObjectSignaled(HANDLE object);
86 
87    private:
88     Core* const core_;
89   };
90 
91   ~Core();
92 
93   // The socket that created this object.
94   UDPSocketWin* socket_;
95 
96   // |reader_| handles the signals from |read_watcher_|.
97   ReadDelegate reader_;
98   // |writer_| handles the signals from |write_watcher_|.
99   WriteDelegate writer_;
100 
101   // |read_watcher_| watches for events from Read().
102   base::win::ObjectWatcher read_watcher_;
103   // |write_watcher_| watches for events from Write();
104   base::win::ObjectWatcher write_watcher_;
105 
106   DISALLOW_COPY_AND_ASSIGN(Core);
107 };
108 
Core(UDPSocketWin * socket)109 UDPSocketWin::Core::Core(UDPSocketWin* socket)
110     : socket_(socket),
111       reader_(this),
112       writer_(this) {
113   memset(&read_overlapped_, 0, sizeof(read_overlapped_));
114   memset(&write_overlapped_, 0, sizeof(write_overlapped_));
115 
116   read_overlapped_.hEvent = WSACreateEvent();
117   write_overlapped_.hEvent = WSACreateEvent();
118 }
119 
~Core()120 UDPSocketWin::Core::~Core() {
121   // Make sure the message loop is not watching this object anymore.
122   read_watcher_.StopWatching();
123   write_watcher_.StopWatching();
124 
125   WSACloseEvent(read_overlapped_.hEvent);
126   memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
127   WSACloseEvent(write_overlapped_.hEvent);
128   memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
129 }
130 
WatchForRead()131 void UDPSocketWin::Core::WatchForRead() {
132   // We grab an extra reference because there is an IO operation in progress.
133   // Balanced in ReadDelegate::OnObjectSignaled().
134   AddRef();
135   read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
136 }
137 
WatchForWrite()138 void UDPSocketWin::Core::WatchForWrite() {
139   // We grab an extra reference because there is an IO operation in progress.
140   // Balanced in WriteDelegate::OnObjectSignaled().
141   AddRef();
142   write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
143 }
144 
OnObjectSignaled(HANDLE object)145 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
146   DCHECK_EQ(object, core_->read_overlapped_.hEvent);
147   if (core_->socket_)
148     core_->socket_->DidCompleteRead();
149 
150   core_->Release();
151 }
152 
OnObjectSignaled(HANDLE object)153 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) {
154   DCHECK_EQ(object, core_->write_overlapped_.hEvent);
155   if (core_->socket_)
156     core_->socket_->DidCompleteWrite();
157 
158   core_->Release();
159 }
160 //-----------------------------------------------------------------------------
161 
QwaveAPI()162 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
163   HMODULE qwave = LoadLibrary(L"qwave.dll");
164   if (!qwave)
165     return;
166   create_handle_func_ =
167       (CreateHandleFn)GetProcAddress(qwave, "QOSCreateHandle");
168   close_handle_func_ =
169       (CloseHandleFn)GetProcAddress(qwave, "QOSCloseHandle");
170   add_socket_to_flow_func_ =
171       (AddSocketToFlowFn)GetProcAddress(qwave, "QOSAddSocketToFlow");
172   remove_socket_from_flow_func_ =
173       (RemoveSocketFromFlowFn)GetProcAddress(qwave, "QOSRemoveSocketFromFlow");
174   set_flow_func_ = (SetFlowFn)GetProcAddress(qwave, "QOSSetFlow");
175 
176   if (create_handle_func_ && close_handle_func_ &&
177       add_socket_to_flow_func_ && remove_socket_from_flow_func_ &&
178       set_flow_func_) {
179     qwave_supported_ = true;
180   }
181 }
182 
Get()183 QwaveAPI& QwaveAPI::Get() {
184   static base::LazyInstance<QwaveAPI>::Leaky lazy_qwave =
185     LAZY_INSTANCE_INITIALIZER;
186   return lazy_qwave.Get();
187 }
188 
qwave_supported() const189 bool QwaveAPI::qwave_supported() const {
190   return qwave_supported_;
191 }
CreateHandle(PQOS_VERSION version,PHANDLE handle)192 BOOL QwaveAPI::CreateHandle(PQOS_VERSION version, PHANDLE handle) {
193   return create_handle_func_(version, handle);
194 }
CloseHandle(HANDLE handle)195 BOOL QwaveAPI::CloseHandle(HANDLE handle) {
196   return close_handle_func_(handle);
197 }
198 
AddSocketToFlow(HANDLE handle,SOCKET socket,PSOCKADDR addr,QOS_TRAFFIC_TYPE traffic_type,DWORD flags,PQOS_FLOWID flow_id)199 BOOL QwaveAPI::AddSocketToFlow(HANDLE handle,
200                                SOCKET socket,
201                                PSOCKADDR addr,
202                                QOS_TRAFFIC_TYPE traffic_type,
203                                DWORD flags,
204                                PQOS_FLOWID flow_id) {
205   return add_socket_to_flow_func_(handle,
206                                   socket,
207                                   addr,
208                                   traffic_type,
209                                   flags,
210                                   flow_id);
211 }
212 
RemoveSocketFromFlow(HANDLE handle,SOCKET socket,QOS_FLOWID flow_id,DWORD reserved)213 BOOL QwaveAPI::RemoveSocketFromFlow(HANDLE handle,
214                                     SOCKET socket,
215                                     QOS_FLOWID flow_id,
216                                     DWORD reserved) {
217   return remove_socket_from_flow_func_(handle, socket, flow_id, reserved);
218 }
219 
SetFlow(HANDLE handle,QOS_FLOWID flow_id,QOS_SET_FLOW op,ULONG size,PVOID data,DWORD reserved,LPOVERLAPPED overlapped)220 BOOL QwaveAPI::SetFlow(HANDLE handle,
221                        QOS_FLOWID flow_id,
222                        QOS_SET_FLOW op,
223                        ULONG size,
224                        PVOID data,
225                        DWORD reserved,
226                        LPOVERLAPPED overlapped) {
227   return set_flow_func_(handle,
228                         flow_id,
229                         op,
230                         size,
231                         data,
232                         reserved,
233                         overlapped);
234 }
235 
236 
237 //-----------------------------------------------------------------------------
238 
UDPSocketWin(DatagramSocket::BindType bind_type,const RandIntCallback & rand_int_cb,net::NetLog * net_log,const net::NetLog::Source & source)239 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
240                            const RandIntCallback& rand_int_cb,
241                            net::NetLog* net_log,
242                            const net::NetLog::Source& source)
243     : socket_(INVALID_SOCKET),
244       addr_family_(0),
245       socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
246       multicast_interface_(0),
247       multicast_time_to_live_(1),
248       bind_type_(bind_type),
249       rand_int_cb_(rand_int_cb),
250       recv_from_address_(NULL),
251       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)),
252       qos_handle_(NULL),
253       qos_flow_id_(0) {
254   EnsureWinsockInit();
255   net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
256                       source.ToEventParametersCallback());
257   if (bind_type == DatagramSocket::RANDOM_BIND)
258     DCHECK(!rand_int_cb.is_null());
259 }
260 
~UDPSocketWin()261 UDPSocketWin::~UDPSocketWin() {
262   Close();
263   net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
264 }
265 
Close()266 void UDPSocketWin::Close() {
267   DCHECK(CalledOnValidThread());
268 
269   if (!is_connected())
270     return;
271 
272   if (qos_handle_) {
273     QwaveAPI::Get().CloseHandle(qos_handle_);
274   }
275 
276   // Zero out any pending read/write callback state.
277   read_callback_.Reset();
278   recv_from_address_ = NULL;
279   write_callback_.Reset();
280 
281   base::TimeTicks start_time = base::TimeTicks::Now();
282   closesocket(socket_);
283   UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
284                       base::TimeTicks::Now() - start_time);
285   socket_ = INVALID_SOCKET;
286   addr_family_ = 0;
287 
288   core_->Detach();
289   core_ = NULL;
290 }
291 
GetPeerAddress(IPEndPoint * address) const292 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
293   DCHECK(CalledOnValidThread());
294   DCHECK(address);
295   if (!is_connected())
296     return ERR_SOCKET_NOT_CONNECTED;
297 
298   // TODO(szym): Simplify. http://crbug.com/126152
299   if (!remote_address_.get()) {
300     SockaddrStorage storage;
301     if (getpeername(socket_, storage.addr, &storage.addr_len))
302       return MapSystemError(WSAGetLastError());
303     scoped_ptr<IPEndPoint> address(new IPEndPoint());
304     if (!address->FromSockAddr(storage.addr, storage.addr_len))
305       return ERR_ADDRESS_INVALID;
306     remote_address_.reset(address.release());
307   }
308 
309   *address = *remote_address_;
310   return OK;
311 }
312 
GetLocalAddress(IPEndPoint * address) const313 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
314   DCHECK(CalledOnValidThread());
315   DCHECK(address);
316   if (!is_connected())
317     return ERR_SOCKET_NOT_CONNECTED;
318 
319   // TODO(szym): Simplify. http://crbug.com/126152
320   if (!local_address_.get()) {
321     SockaddrStorage storage;
322     if (getsockname(socket_, storage.addr, &storage.addr_len))
323       return MapSystemError(WSAGetLastError());
324     scoped_ptr<IPEndPoint> address(new IPEndPoint());
325     if (!address->FromSockAddr(storage.addr, storage.addr_len))
326       return ERR_ADDRESS_INVALID;
327     local_address_.reset(address.release());
328     net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
329                       CreateNetLogUDPConnectCallback(local_address_.get()));
330   }
331 
332   *address = *local_address_;
333   return OK;
334 }
335 
Read(IOBuffer * buf,int buf_len,const CompletionCallback & callback)336 int UDPSocketWin::Read(IOBuffer* buf,
337                        int buf_len,
338                        const CompletionCallback& callback) {
339   return RecvFrom(buf, buf_len, NULL, callback);
340 }
341 
RecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address,const CompletionCallback & callback)342 int UDPSocketWin::RecvFrom(IOBuffer* buf,
343                            int buf_len,
344                            IPEndPoint* address,
345                            const CompletionCallback& callback) {
346   DCHECK(CalledOnValidThread());
347   DCHECK_NE(INVALID_SOCKET, socket_);
348   CHECK(read_callback_.is_null());
349   DCHECK(!recv_from_address_);
350   DCHECK(!callback.is_null());  // Synchronous operation not supported.
351   DCHECK_GT(buf_len, 0);
352 
353   int nread = InternalRecvFrom(buf, buf_len, address);
354   if (nread != ERR_IO_PENDING)
355     return nread;
356 
357   read_callback_ = callback;
358   recv_from_address_ = address;
359   return ERR_IO_PENDING;
360 }
361 
Write(IOBuffer * buf,int buf_len,const CompletionCallback & callback)362 int UDPSocketWin::Write(IOBuffer* buf,
363                         int buf_len,
364                         const CompletionCallback& callback) {
365   return SendToOrWrite(buf, buf_len, NULL, callback);
366 }
367 
SendTo(IOBuffer * buf,int buf_len,const IPEndPoint & address,const CompletionCallback & callback)368 int UDPSocketWin::SendTo(IOBuffer* buf,
369                          int buf_len,
370                          const IPEndPoint& address,
371                          const CompletionCallback& callback) {
372   return SendToOrWrite(buf, buf_len, &address, callback);
373 }
374 
SendToOrWrite(IOBuffer * buf,int buf_len,const IPEndPoint * address,const CompletionCallback & callback)375 int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
376                                 int buf_len,
377                                 const IPEndPoint* address,
378                                 const CompletionCallback& callback) {
379   DCHECK(CalledOnValidThread());
380   DCHECK_NE(INVALID_SOCKET, socket_);
381   CHECK(write_callback_.is_null());
382   DCHECK(!callback.is_null());  // Synchronous operation not supported.
383   DCHECK_GT(buf_len, 0);
384   DCHECK(!send_to_address_.get());
385 
386   int nwrite = InternalSendTo(buf, buf_len, address);
387   if (nwrite != ERR_IO_PENDING)
388     return nwrite;
389 
390   if (address)
391     send_to_address_.reset(new IPEndPoint(*address));
392   write_callback_ = callback;
393   return ERR_IO_PENDING;
394 }
395 
Connect(const IPEndPoint & address)396 int UDPSocketWin::Connect(const IPEndPoint& address) {
397   net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
398                       CreateNetLogUDPConnectCallback(&address));
399   int rv = InternalConnect(address);
400   if (rv != OK)
401     Close();
402   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
403   return rv;
404 }
405 
InternalConnect(const IPEndPoint & address)406 int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
407   DCHECK(!is_connected());
408   DCHECK(!remote_address_.get());
409   int addr_family = address.GetSockAddrFamily();
410   int rv = CreateSocket(addr_family);
411   if (rv < 0)
412     return rv;
413 
414   if (bind_type_ == DatagramSocket::RANDOM_BIND) {
415     // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
416     // representing INADDR_ANY or in6addr_any.
417     size_t addr_size =
418         addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize;
419     IPAddressNumber addr_any(addr_size);
420     rv = RandomBind(addr_any);
421   }
422   // else connect() does the DatagramSocket::DEFAULT_BIND
423 
424   if (rv < 0) {
425     UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv);
426     Close();
427     return rv;
428   }
429 
430   SockaddrStorage storage;
431   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
432     return ERR_ADDRESS_INVALID;
433 
434   rv = connect(socket_, storage.addr, storage.addr_len);
435   if (rv < 0) {
436     // Close() may change the last error. Map it beforehand.
437     int result = MapSystemError(WSAGetLastError());
438     Close();
439     return result;
440   }
441 
442   remote_address_.reset(new IPEndPoint(address));
443   return rv;
444 }
445 
Bind(const IPEndPoint & address)446 int UDPSocketWin::Bind(const IPEndPoint& address) {
447   DCHECK(!is_connected());
448   int rv = CreateSocket(address.GetSockAddrFamily());
449   if (rv < 0)
450     return rv;
451   rv = SetSocketOptions();
452   if (rv < 0) {
453     Close();
454     return rv;
455   }
456   rv = DoBind(address);
457   if (rv < 0) {
458     Close();
459     return rv;
460   }
461   local_address_.reset();
462   return rv;
463 }
464 
CreateSocket(int addr_family)465 int UDPSocketWin::CreateSocket(int addr_family) {
466   addr_family_ = addr_family;
467   socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
468   if (socket_ == INVALID_SOCKET)
469     return MapSystemError(WSAGetLastError());
470   core_ = new Core(this);
471   return OK;
472 }
473 
SetReceiveBufferSize(int32 size)474 int UDPSocketWin::SetReceiveBufferSize(int32 size) {
475   DCHECK(CalledOnValidThread());
476   int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
477                       reinterpret_cast<const char*>(&size), sizeof(size));
478   if (rv != 0)
479     return MapSystemError(WSAGetLastError());
480 
481   // According to documentation, setsockopt may succeed, but we need to check
482   // the results via getsockopt to be sure it works on Windows.
483   int32 actual_size = 0;
484   int option_size = sizeof(actual_size);
485   rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
486                   reinterpret_cast<char*>(&actual_size), &option_size);
487   if (rv != 0)
488     return MapSystemError(WSAGetLastError());
489   if (actual_size >= size)
490     return OK;
491   UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
492                               actual_size, 1000, 1000000, 50);
493   return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE;
494 }
495 
SetSendBufferSize(int32 size)496 int UDPSocketWin::SetSendBufferSize(int32 size) {
497   DCHECK(CalledOnValidThread());
498   int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
499                       reinterpret_cast<const char*>(&size), sizeof(size));
500   if (rv != 0)
501     return MapSystemError(WSAGetLastError());
502   // According to documentation, setsockopt may succeed, but we need to check
503   // the results via getsockopt to be sure it works on Windows.
504   int32 actual_size = 0;
505   int option_size = sizeof(actual_size);
506   rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
507                   reinterpret_cast<char*>(&actual_size), &option_size);
508   if (rv != 0)
509     return MapSystemError(WSAGetLastError());
510   if (actual_size >= size)
511     return OK;
512   UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
513                               actual_size, 1000, 1000000, 50);
514   return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE;
515 }
516 
AllowAddressReuse()517 void UDPSocketWin::AllowAddressReuse() {
518   DCHECK(CalledOnValidThread());
519   DCHECK(!is_connected());
520 
521   socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
522 }
523 
AllowBroadcast()524 void UDPSocketWin::AllowBroadcast() {
525   DCHECK(CalledOnValidThread());
526   DCHECK(!is_connected());
527 
528   socket_options_ |= SOCKET_OPTION_BROADCAST;
529 }
530 
DoReadCallback(int rv)531 void UDPSocketWin::DoReadCallback(int rv) {
532   DCHECK_NE(rv, ERR_IO_PENDING);
533   DCHECK(!read_callback_.is_null());
534 
535   // since Run may result in Read being called, clear read_callback_ up front.
536   CompletionCallback c = read_callback_;
537   read_callback_.Reset();
538   c.Run(rv);
539 }
540 
DoWriteCallback(int rv)541 void UDPSocketWin::DoWriteCallback(int rv) {
542   DCHECK_NE(rv, ERR_IO_PENDING);
543   DCHECK(!write_callback_.is_null());
544 
545   // since Run may result in Write being called, clear write_callback_ up front.
546   CompletionCallback c = write_callback_;
547   write_callback_.Reset();
548   c.Run(rv);
549 }
550 
DidCompleteRead()551 void UDPSocketWin::DidCompleteRead() {
552   DWORD num_bytes, flags;
553   BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
554                                    &num_bytes, FALSE, &flags);
555   WSAResetEvent(core_->read_overlapped_.hEvent);
556   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
557   // Convert address.
558   if (recv_from_address_ && result >= 0) {
559     if (!ReceiveAddressToIPEndpoint(recv_from_address_))
560       result = ERR_ADDRESS_INVALID;
561   }
562   LogRead(result, core_->read_iobuffer_->data());
563   core_->read_iobuffer_ = NULL;
564   recv_from_address_ = NULL;
565   DoReadCallback(result);
566 }
567 
LogRead(int result,const char * bytes) const568 void UDPSocketWin::LogRead(int result, const char* bytes) const {
569   if (result < 0) {
570     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
571     return;
572   }
573 
574   if (net_log_.IsLogging()) {
575     // Get address for logging, if |address| is NULL.
576     IPEndPoint address;
577     bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
578     net_log_.AddEvent(
579         NetLog::TYPE_UDP_BYTES_RECEIVED,
580         CreateNetLogUDPDataTranferCallback(
581             result, bytes,
582             is_address_valid ? &address : NULL));
583   }
584 
585   base::StatsCounter read_bytes("udp.read_bytes");
586   read_bytes.Add(result);
587 }
588 
DidCompleteWrite()589 void UDPSocketWin::DidCompleteWrite() {
590   DWORD num_bytes, flags;
591   BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
592                                    &num_bytes, FALSE, &flags);
593   WSAResetEvent(core_->write_overlapped_.hEvent);
594   int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
595   LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
596 
597   send_to_address_.reset();
598   core_->write_iobuffer_ = NULL;
599   DoWriteCallback(result);
600 }
601 
LogWrite(int result,const char * bytes,const IPEndPoint * address) const602 void UDPSocketWin::LogWrite(int result,
603                             const char* bytes,
604                             const IPEndPoint* address) const {
605   if (result < 0) {
606     net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
607     return;
608   }
609 
610   if (net_log_.IsLogging()) {
611     net_log_.AddEvent(
612         NetLog::TYPE_UDP_BYTES_SENT,
613         CreateNetLogUDPDataTranferCallback(result, bytes, address));
614   }
615 
616   base::StatsCounter write_bytes("udp.write_bytes");
617   write_bytes.Add(result);
618 }
619 
InternalRecvFrom(IOBuffer * buf,int buf_len,IPEndPoint * address)620 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
621                                    IPEndPoint* address) {
622   DCHECK(!core_->read_iobuffer_);
623   SockaddrStorage& storage = core_->recv_addr_storage_;
624   storage.addr_len = sizeof(storage.addr_storage);
625 
626   WSABUF read_buffer;
627   read_buffer.buf = buf->data();
628   read_buffer.len = buf_len;
629 
630   DWORD flags = 0;
631   DWORD num;
632   CHECK_NE(INVALID_SOCKET, socket_);
633   AssertEventNotSignaled(core_->read_overlapped_.hEvent);
634   int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
635                        &storage.addr_len, &core_->read_overlapped_, NULL);
636   if (rv == 0) {
637     if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
638       int result = num;
639       // Convert address.
640       if (address && result >= 0) {
641         if (!ReceiveAddressToIPEndpoint(address))
642           result = ERR_ADDRESS_INVALID;
643       }
644       LogRead(result, buf->data());
645       return result;
646     }
647   } else {
648     int os_error = WSAGetLastError();
649     if (os_error != WSA_IO_PENDING) {
650       int result = MapSystemError(os_error);
651       LogRead(result, NULL);
652       return result;
653     }
654   }
655   core_->WatchForRead();
656   core_->read_iobuffer_ = buf;
657   return ERR_IO_PENDING;
658 }
659 
InternalSendTo(IOBuffer * buf,int buf_len,const IPEndPoint * address)660 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
661                                  const IPEndPoint* address) {
662   DCHECK(!core_->write_iobuffer_);
663   SockaddrStorage storage;
664   struct sockaddr* addr = storage.addr;
665   // Convert address.
666   if (!address) {
667     addr = NULL;
668     storage.addr_len = 0;
669   } else {
670     if (!address->ToSockAddr(addr, &storage.addr_len)) {
671       int result = ERR_ADDRESS_INVALID;
672       LogWrite(result, NULL, NULL);
673       return result;
674     }
675   }
676 
677   WSABUF write_buffer;
678   write_buffer.buf = buf->data();
679   write_buffer.len = buf_len;
680 
681   DWORD flags = 0;
682   DWORD num;
683   AssertEventNotSignaled(core_->write_overlapped_.hEvent);
684   int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
685                      addr, storage.addr_len, &core_->write_overlapped_, NULL);
686   if (rv == 0) {
687     if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
688       int result = num;
689       LogWrite(result, buf->data(), address);
690       return result;
691     }
692   } else {
693     int os_error = WSAGetLastError();
694     if (os_error != WSA_IO_PENDING) {
695       int result = MapSystemError(os_error);
696       LogWrite(result, NULL, NULL);
697       return result;
698     }
699   }
700 
701   core_->WatchForWrite();
702   core_->write_iobuffer_ = buf;
703   return ERR_IO_PENDING;
704 }
705 
SetSocketOptions()706 int UDPSocketWin::SetSocketOptions() {
707   BOOL true_value = 1;
708   if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
709     int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
710                         reinterpret_cast<const char*>(&true_value),
711                         sizeof(true_value));
712     if (rv < 0)
713       return MapSystemError(WSAGetLastError());
714   }
715   if (socket_options_ & SOCKET_OPTION_BROADCAST) {
716     int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
717                         reinterpret_cast<const char*>(&true_value),
718                         sizeof(true_value));
719     if (rv < 0)
720       return MapSystemError(WSAGetLastError());
721   }
722   if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
723     DWORD loop = 0;
724     int protocol_level =
725         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
726     int option =
727         addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
728     int rv = setsockopt(socket_, protocol_level, option,
729                         reinterpret_cast<const char*>(&loop), sizeof(loop));
730     if (rv < 0)
731       return MapSystemError(WSAGetLastError());
732   }
733   if (multicast_time_to_live_ != 1) {
734     DWORD hops = multicast_time_to_live_;
735     int protocol_level =
736         addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
737     int option =
738         addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
739     int rv = setsockopt(socket_, protocol_level, option,
740                         reinterpret_cast<const char*>(&hops), sizeof(hops));
741     if (rv < 0)
742       return MapSystemError(WSAGetLastError());
743   }
744   if (multicast_interface_ != 0) {
745     switch (addr_family_) {
746       case AF_INET: {
747         in_addr address;
748         address.s_addr = htonl(multicast_interface_);
749         int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
750                             reinterpret_cast<const char*>(&address),
751                             sizeof(address));
752         if (rv)
753           return MapSystemError(WSAGetLastError());
754         break;
755       }
756       case AF_INET6: {
757         uint32 interface_index = multicast_interface_;
758         int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
759                             reinterpret_cast<const char*>(&interface_index),
760                             sizeof(interface_index));
761         if (rv)
762           return MapSystemError(WSAGetLastError());
763         break;
764       }
765       default:
766         NOTREACHED() << "Invalid address family";
767         return ERR_ADDRESS_INVALID;
768     }
769   }
770   return OK;
771 }
772 
DoBind(const IPEndPoint & address)773 int UDPSocketWin::DoBind(const IPEndPoint& address) {
774   SockaddrStorage storage;
775   if (!address.ToSockAddr(storage.addr, &storage.addr_len))
776     return ERR_ADDRESS_INVALID;
777   int rv = bind(socket_, storage.addr, storage.addr_len);
778   if (rv == 0)
779     return OK;
780   int last_error = WSAGetLastError();
781   UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
782   // Map some codes that are special to bind() separately.
783   // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
784   //   returned instead of WSAEADDRINUSE, depending on whether the socket
785   //   option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
786   //   conflicting socket is owned by a different user account. See the MSDN
787   //   page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
788   if (last_error == WSAEACCES || last_error == WSAEADDRNOTAVAIL)
789     return ERR_ADDRESS_IN_USE;
790   return MapSystemError(last_error);
791 }
792 
RandomBind(const IPAddressNumber & address)793 int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
794   DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
795 
796   for (int i = 0; i < kBindRetries; ++i) {
797     int rv = DoBind(IPEndPoint(address,
798                                rand_int_cb_.Run(kPortStart, kPortEnd)));
799     if (rv == OK || rv != ERR_ADDRESS_IN_USE)
800       return rv;
801   }
802   return DoBind(IPEndPoint(address, 0));
803 }
804 
ReceiveAddressToIPEndpoint(IPEndPoint * address) const805 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
806   SockaddrStorage& storage = core_->recv_addr_storage_;
807   return address->FromSockAddr(storage.addr, storage.addr_len);
808 }
809 
JoinGroup(const IPAddressNumber & group_address) const810 int UDPSocketWin::JoinGroup(
811     const IPAddressNumber& group_address) const {
812   DCHECK(CalledOnValidThread());
813   if (!is_connected())
814     return ERR_SOCKET_NOT_CONNECTED;
815 
816   switch (group_address.size()) {
817     case kIPv4AddressSize: {
818       if (addr_family_ != AF_INET)
819         return ERR_ADDRESS_INVALID;
820       ip_mreq mreq;
821       mreq.imr_interface.s_addr = htonl(multicast_interface_);
822       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
823       int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
824                           reinterpret_cast<const char*>(&mreq),
825                           sizeof(mreq));
826       if (rv)
827         return MapSystemError(WSAGetLastError());
828       return OK;
829     }
830     case kIPv6AddressSize: {
831       if (addr_family_ != AF_INET6)
832         return ERR_ADDRESS_INVALID;
833       ipv6_mreq mreq;
834       mreq.ipv6mr_interface = multicast_interface_;
835       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
836       int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
837                           reinterpret_cast<const char*>(&mreq),
838                           sizeof(mreq));
839       if (rv)
840         return MapSystemError(WSAGetLastError());
841       return OK;
842     }
843     default:
844       NOTREACHED() << "Invalid address family";
845       return ERR_ADDRESS_INVALID;
846   }
847 }
848 
LeaveGroup(const IPAddressNumber & group_address) const849 int UDPSocketWin::LeaveGroup(
850     const IPAddressNumber& group_address) const {
851   DCHECK(CalledOnValidThread());
852   if (!is_connected())
853     return ERR_SOCKET_NOT_CONNECTED;
854 
855   switch (group_address.size()) {
856     case kIPv4AddressSize: {
857       if (addr_family_ != AF_INET)
858         return ERR_ADDRESS_INVALID;
859       ip_mreq mreq;
860       mreq.imr_interface.s_addr = htonl(multicast_interface_);
861       memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
862       int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
863                           reinterpret_cast<const char*>(&mreq), sizeof(mreq));
864       if (rv)
865         return MapSystemError(WSAGetLastError());
866       return OK;
867     }
868     case kIPv6AddressSize: {
869       if (addr_family_ != AF_INET6)
870         return ERR_ADDRESS_INVALID;
871       ipv6_mreq mreq;
872       mreq.ipv6mr_interface = multicast_interface_;
873       memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
874       int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
875                           reinterpret_cast<const char*>(&mreq), sizeof(mreq));
876       if (rv)
877         return MapSystemError(WSAGetLastError());
878       return OK;
879     }
880     default:
881       NOTREACHED() << "Invalid address family";
882       return ERR_ADDRESS_INVALID;
883   }
884 }
885 
SetMulticastInterface(uint32 interface_index)886 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
887   DCHECK(CalledOnValidThread());
888   if (is_connected())
889     return ERR_SOCKET_IS_CONNECTED;
890   multicast_interface_ = interface_index;
891   return OK;
892 }
893 
SetMulticastTimeToLive(int time_to_live)894 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
895   DCHECK(CalledOnValidThread());
896   if (is_connected())
897     return ERR_SOCKET_IS_CONNECTED;
898 
899   if (time_to_live < 0 || time_to_live > 255)
900     return ERR_INVALID_ARGUMENT;
901   multicast_time_to_live_ = time_to_live;
902   return OK;
903 }
904 
SetMulticastLoopbackMode(bool loopback)905 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
906   DCHECK(CalledOnValidThread());
907   if (is_connected())
908     return ERR_SOCKET_IS_CONNECTED;
909 
910   if (loopback)
911     socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
912   else
913     socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
914   return OK;
915 }
916 
SetDiffServCodePoint(DiffServCodePoint dscp)917 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
918   if (dscp == DSCP_NO_CHANGE) {
919     return OK;
920   }
921 
922   if (!is_connected())
923     return ERR_SOCKET_NOT_CONNECTED;
924 
925   QwaveAPI& qos(QwaveAPI::Get());
926 
927   if (!qos.qwave_supported())
928     return ERROR_NOT_SUPPORTED;
929 
930   if (qos_handle_ == NULL) {
931     QOS_VERSION version;
932     version.MajorVersion = 1;
933     version.MinorVersion = 0;
934     qos.CreateHandle(&version, &qos_handle_);
935     if (qos_handle_ == NULL)
936       return ERROR_NOT_SUPPORTED;
937   }
938 
939   QOS_TRAFFIC_TYPE traffic_type = QOSTrafficTypeBestEffort;
940   switch (dscp) {
941     case DSCP_CS0:
942       traffic_type = QOSTrafficTypeBestEffort;
943       break;
944     case DSCP_CS1:
945       traffic_type = QOSTrafficTypeBackground;
946       break;
947     case DSCP_AF11:
948     case DSCP_AF12:
949     case DSCP_AF13:
950     case DSCP_CS2:
951     case DSCP_AF21:
952     case DSCP_AF22:
953     case DSCP_AF23:
954     case DSCP_CS3:
955     case DSCP_AF31:
956     case DSCP_AF32:
957     case DSCP_AF33:
958     case DSCP_CS4:
959       traffic_type = QOSTrafficTypeExcellentEffort;
960       break;
961     case DSCP_AF41:
962     case DSCP_AF42:
963     case DSCP_AF43:
964     case DSCP_CS5:
965       traffic_type = QOSTrafficTypeAudioVideo;
966       break;
967     case DSCP_EF:
968     case DSCP_CS6:
969       traffic_type = QOSTrafficTypeVoice;
970       break;
971     case DSCP_CS7:
972       traffic_type = QOSTrafficTypeControl;
973       break;
974     case DSCP_NO_CHANGE:
975       NOTREACHED();
976       break;
977   }
978   if (qos_flow_id_ != 0) {
979     qos.RemoveSocketFromFlow(qos_handle_, NULL, qos_flow_id_, 0);
980     qos_flow_id_ = 0;
981   }
982   if (!qos.AddSocketToFlow(qos_handle_,
983                            socket_,
984                            NULL,
985                            traffic_type,
986                            QOS_NON_ADAPTIVE_FLOW,
987                            &qos_flow_id_)) {
988     DWORD err = GetLastError();
989     if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) {
990       qos.CloseHandle(qos_handle_);
991       qos_flow_id_ = 0;
992       qos_handle_ = 0;
993     }
994     return MapSystemError(err);
995   }
996   // This requires admin rights, and may fail, if so we ignore it
997   // as AddSocketToFlow should still do *approximately* the right thing.
998   DWORD buf = dscp;
999   qos.SetFlow(qos_handle_,
1000               qos_flow_id_,
1001               QOSSetOutgoingDSCPValue,
1002               sizeof(buf),
1003               &buf,
1004               0,
1005               NULL);
1006 
1007   return OK;
1008 }
1009 
DetachFromThread()1010 void UDPSocketWin::DetachFromThread() {
1011   base::NonThreadSafe::DetachFromThread();
1012 }
1013 
1014 }  // namespace net
1015