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.
5 #include "net/udp/udp_socket_win.h"
9 #include "base/basictypes.h"
10 #include "base/callback.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/histogram.h"
15 #include "base/metrics/sparse_histogram.h"
16 #include "base/profiler/scoped_tracker.h"
17 #include "base/rand_util.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/ip_endpoint.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_log.h"
22 #include "net/base/net_util.h"
23 #include "net/base/network_activity_monitor.h"
24 #include "net/base/winsock_init.h"
25 #include "net/base/winsock_util.h"
26 #include "net/socket/socket_descriptor.h"
27 #include "net/udp/udp_net_log_parameters.h"
31 const int kBindRetries
= 10;
32 const int kPortStart
= 1024;
33 const int kPortEnd
= 65535;
39 // This class encapsulates all the state that has to be preserved as long as
40 // there is a network IO operation in progress. If the owner UDPSocketWin
41 // is destroyed while an operation is in progress, the Core is detached and it
42 // lives until the operation completes and the OS doesn't reference any resource
43 // declared on this class anymore.
44 class UDPSocketWin::Core
: public base::RefCounted
<Core
> {
46 explicit Core(UDPSocketWin
* socket
);
48 // Start watching for the end of a read or write operation.
52 // The UDPSocketWin is going away.
53 void Detach() { socket_
= NULL
; }
55 // The separate OVERLAPPED variables for asynchronous operation.
56 OVERLAPPED read_overlapped_
;
57 OVERLAPPED write_overlapped_
;
59 // The buffers used in Read() and Write().
60 scoped_refptr
<IOBuffer
> read_iobuffer_
;
61 scoped_refptr
<IOBuffer
> write_iobuffer_
;
63 // The address storage passed to WSARecvFrom().
64 SockaddrStorage recv_addr_storage_
;
67 friend class base::RefCounted
<Core
>;
69 class ReadDelegate
: public base::win::ObjectWatcher::Delegate
{
71 explicit ReadDelegate(Core
* core
) : core_(core
) {}
72 virtual ~ReadDelegate() {}
74 // base::ObjectWatcher::Delegate methods:
75 virtual void OnObjectSignaled(HANDLE object
);
81 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
83 explicit WriteDelegate(Core
* core
) : core_(core
) {}
84 virtual ~WriteDelegate() {}
86 // base::ObjectWatcher::Delegate methods:
87 virtual void OnObjectSignaled(HANDLE object
);
95 // The socket that created this object.
96 UDPSocketWin
* socket_
;
98 // |reader_| handles the signals from |read_watcher_|.
100 // |writer_| handles the signals from |write_watcher_|.
101 WriteDelegate writer_
;
103 // |read_watcher_| watches for events from Read().
104 base::win::ObjectWatcher read_watcher_
;
105 // |write_watcher_| watches for events from Write();
106 base::win::ObjectWatcher write_watcher_
;
108 DISALLOW_COPY_AND_ASSIGN(Core
);
111 UDPSocketWin::Core::Core(UDPSocketWin
* socket
)
115 memset(&read_overlapped_
, 0, sizeof(read_overlapped_
));
116 memset(&write_overlapped_
, 0, sizeof(write_overlapped_
));
118 read_overlapped_
.hEvent
= WSACreateEvent();
119 write_overlapped_
.hEvent
= WSACreateEvent();
122 UDPSocketWin::Core::~Core() {
123 // Make sure the message loop is not watching this object anymore.
124 read_watcher_
.StopWatching();
125 write_watcher_
.StopWatching();
127 WSACloseEvent(read_overlapped_
.hEvent
);
128 memset(&read_overlapped_
, 0xaf, sizeof(read_overlapped_
));
129 WSACloseEvent(write_overlapped_
.hEvent
);
130 memset(&write_overlapped_
, 0xaf, sizeof(write_overlapped_
));
133 void UDPSocketWin::Core::WatchForRead() {
134 // We grab an extra reference because there is an IO operation in progress.
135 // Balanced in ReadDelegate::OnObjectSignaled().
137 read_watcher_
.StartWatching(read_overlapped_
.hEvent
, &reader_
);
140 void UDPSocketWin::Core::WatchForWrite() {
141 // We grab an extra reference because there is an IO operation in progress.
142 // Balanced in WriteDelegate::OnObjectSignaled().
144 write_watcher_
.StartWatching(write_overlapped_
.hEvent
, &writer_
);
147 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object
) {
148 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/462789 is fixed.
149 tracked_objects::ScopedTracker
tracking_profile(
150 FROM_HERE_WITH_EXPLICIT_FUNCTION(
151 "462789 UDPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
153 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
155 core_
->socket_
->DidCompleteRead();
160 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
161 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
163 core_
->socket_
->DidCompleteWrite();
167 //-----------------------------------------------------------------------------
169 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
170 HMODULE qwave
= LoadLibrary(L
"qwave.dll");
173 create_handle_func_
=
174 (CreateHandleFn
)GetProcAddress(qwave
, "QOSCreateHandle");
176 (CloseHandleFn
)GetProcAddress(qwave
, "QOSCloseHandle");
177 add_socket_to_flow_func_
=
178 (AddSocketToFlowFn
)GetProcAddress(qwave
, "QOSAddSocketToFlow");
179 remove_socket_from_flow_func_
=
180 (RemoveSocketFromFlowFn
)GetProcAddress(qwave
, "QOSRemoveSocketFromFlow");
181 set_flow_func_
= (SetFlowFn
)GetProcAddress(qwave
, "QOSSetFlow");
183 if (create_handle_func_
&& close_handle_func_
&&
184 add_socket_to_flow_func_
&& remove_socket_from_flow_func_
&&
186 qwave_supported_
= true;
190 QwaveAPI
& QwaveAPI::Get() {
191 static base::LazyInstance
<QwaveAPI
>::Leaky lazy_qwave
=
192 LAZY_INSTANCE_INITIALIZER
;
193 return lazy_qwave
.Get();
196 bool QwaveAPI::qwave_supported() const {
197 return qwave_supported_
;
199 BOOL
QwaveAPI::CreateHandle(PQOS_VERSION version
, PHANDLE handle
) {
200 return create_handle_func_(version
, handle
);
202 BOOL
QwaveAPI::CloseHandle(HANDLE handle
) {
203 return close_handle_func_(handle
);
206 BOOL
QwaveAPI::AddSocketToFlow(HANDLE handle
,
209 QOS_TRAFFIC_TYPE traffic_type
,
211 PQOS_FLOWID flow_id
) {
212 return add_socket_to_flow_func_(handle
,
220 BOOL
QwaveAPI::RemoveSocketFromFlow(HANDLE handle
,
224 return remove_socket_from_flow_func_(handle
, socket
, flow_id
, reserved
);
227 BOOL
QwaveAPI::SetFlow(HANDLE handle
,
233 LPOVERLAPPED overlapped
) {
234 return set_flow_func_(handle
,
244 //-----------------------------------------------------------------------------
246 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type
,
247 const RandIntCallback
& rand_int_cb
,
248 net::NetLog
* net_log
,
249 const net::NetLog::Source
& source
)
250 : socket_(INVALID_SOCKET
),
252 is_connected_(false),
253 socket_options_(SOCKET_OPTION_MULTICAST_LOOP
),
254 multicast_interface_(0),
255 multicast_time_to_live_(1),
256 bind_type_(bind_type
),
257 rand_int_cb_(rand_int_cb
),
258 use_non_blocking_io_(false),
259 read_iobuffer_len_(0),
260 write_iobuffer_len_(0),
261 recv_from_address_(NULL
),
262 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_UDP_SOCKET
)),
266 net_log_
.BeginEvent(NetLog::TYPE_SOCKET_ALIVE
,
267 source
.ToEventParametersCallback());
268 if (bind_type
== DatagramSocket::RANDOM_BIND
)
269 DCHECK(!rand_int_cb
.is_null());
272 UDPSocketWin::~UDPSocketWin() {
274 net_log_
.EndEvent(NetLog::TYPE_SOCKET_ALIVE
);
277 int UDPSocketWin::Open(AddressFamily address_family
) {
278 DCHECK(CalledOnValidThread());
279 DCHECK_EQ(socket_
, INVALID_SOCKET
);
281 addr_family_
= ConvertAddressFamily(address_family
);
282 socket_
= CreatePlatformSocket(addr_family_
, SOCK_DGRAM
, IPPROTO_UDP
);
283 if (socket_
== INVALID_SOCKET
)
284 return MapSystemError(WSAGetLastError());
285 if (!use_non_blocking_io_
) {
286 core_
= new Core(this);
288 read_write_event_
.Set(WSACreateEvent());
289 WSAEventSelect(socket_
, read_write_event_
.Get(), FD_READ
| FD_WRITE
);
294 void UDPSocketWin::Close() {
295 DCHECK(CalledOnValidThread());
297 if (socket_
== INVALID_SOCKET
)
301 QwaveAPI::Get().CloseHandle(qos_handle_
);
304 // Zero out any pending read/write callback state.
305 read_callback_
.Reset();
306 recv_from_address_
= NULL
;
307 write_callback_
.Reset();
309 base::TimeTicks start_time
= base::TimeTicks::Now();
310 closesocket(socket_
);
311 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
312 base::TimeTicks::Now() - start_time
);
313 socket_
= INVALID_SOCKET
;
315 is_connected_
= false;
317 read_write_watcher_
.StopWatching();
318 read_write_event_
.Close();
326 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
327 DCHECK(CalledOnValidThread());
330 return ERR_SOCKET_NOT_CONNECTED
;
332 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/462789 is fixed.
333 tracked_objects::ScopedTracker
tracking_profile(
334 FROM_HERE_WITH_EXPLICIT_FUNCTION("462789 UDPSocketWin::GetPeerAddress"));
336 // TODO(szym): Simplify. http://crbug.com/126152
337 if (!remote_address_
.get()) {
338 SockaddrStorage storage
;
339 if (getpeername(socket_
, storage
.addr
, &storage
.addr_len
))
340 return MapSystemError(WSAGetLastError());
341 scoped_ptr
<IPEndPoint
> remote_address(new IPEndPoint());
342 if (!remote_address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
343 return ERR_ADDRESS_INVALID
;
344 remote_address_
.reset(remote_address
.release());
347 *address
= *remote_address_
;
351 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
352 DCHECK(CalledOnValidThread());
355 return ERR_SOCKET_NOT_CONNECTED
;
357 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/462789 is fixed.
358 tracked_objects::ScopedTracker
tracking_profile(
359 FROM_HERE_WITH_EXPLICIT_FUNCTION("462789 UDPSocketWin::GetLocalAddress"));
361 // TODO(szym): Simplify. http://crbug.com/126152
362 if (!local_address_
.get()) {
363 SockaddrStorage storage
;
364 if (getsockname(socket_
, storage
.addr
, &storage
.addr_len
))
365 return MapSystemError(WSAGetLastError());
366 scoped_ptr
<IPEndPoint
> local_address(new IPEndPoint());
367 if (!local_address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
368 return ERR_ADDRESS_INVALID
;
369 local_address_
.reset(local_address
.release());
370 net_log_
.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS
,
371 CreateNetLogUDPConnectCallback(local_address_
.get()));
374 *address
= *local_address_
;
378 int UDPSocketWin::Read(IOBuffer
* buf
,
380 const CompletionCallback
& callback
) {
381 return RecvFrom(buf
, buf_len
, NULL
, callback
);
384 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
387 const CompletionCallback
& callback
) {
388 DCHECK(CalledOnValidThread());
389 DCHECK_NE(INVALID_SOCKET
, socket_
);
390 CHECK(read_callback_
.is_null());
391 DCHECK(!recv_from_address_
);
392 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
393 DCHECK_GT(buf_len
, 0);
395 int nread
= core_
? InternalRecvFromOverlapped(buf
, buf_len
, address
)
396 : InternalRecvFromNonBlocking(buf
, buf_len
, address
);
397 if (nread
!= ERR_IO_PENDING
)
400 read_callback_
= callback
;
401 recv_from_address_
= address
;
402 return ERR_IO_PENDING
;
405 int UDPSocketWin::Write(IOBuffer
* buf
,
407 const CompletionCallback
& callback
) {
408 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
411 int UDPSocketWin::SendTo(IOBuffer
* buf
,
413 const IPEndPoint
& address
,
414 const CompletionCallback
& callback
) {
415 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
418 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
420 const IPEndPoint
* address
,
421 const CompletionCallback
& callback
) {
422 DCHECK(CalledOnValidThread());
423 DCHECK_NE(INVALID_SOCKET
, socket_
);
424 CHECK(write_callback_
.is_null());
425 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
426 DCHECK_GT(buf_len
, 0);
427 DCHECK(!send_to_address_
.get());
429 int nwrite
= core_
? InternalSendToOverlapped(buf
, buf_len
, address
)
430 : InternalSendToNonBlocking(buf
, buf_len
, address
);
431 if (nwrite
!= ERR_IO_PENDING
)
435 send_to_address_
.reset(new IPEndPoint(*address
));
436 write_callback_
= callback
;
437 return ERR_IO_PENDING
;
440 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
441 DCHECK_NE(socket_
, INVALID_SOCKET
);
442 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
443 CreateNetLogUDPConnectCallback(&address
));
444 int rv
= InternalConnect(address
);
445 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
446 is_connected_
= (rv
== OK
);
450 int UDPSocketWin::InternalConnect(const IPEndPoint
& address
) {
451 DCHECK(!is_connected());
452 DCHECK(!remote_address_
.get());
455 if (bind_type_
== DatagramSocket::RANDOM_BIND
) {
456 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
457 // representing INADDR_ANY or in6addr_any.
458 size_t addr_size
= (address
.GetSockAddrFamily() == AF_INET
) ?
459 kIPv4AddressSize
: kIPv6AddressSize
;
460 IPAddressNumber
addr_any(addr_size
);
461 rv
= RandomBind(addr_any
);
463 // else connect() does the DatagramSocket::DEFAULT_BIND
466 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
470 SockaddrStorage storage
;
471 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
472 return ERR_ADDRESS_INVALID
;
474 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
476 return MapSystemError(WSAGetLastError());
478 remote_address_
.reset(new IPEndPoint(address
));
482 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
483 DCHECK_NE(socket_
, INVALID_SOCKET
);
484 DCHECK(!is_connected());
486 int rv
= SetMulticastOptions();
490 rv
= DoBind(address
);
494 local_address_
.reset();
495 is_connected_
= true;
499 int UDPSocketWin::SetReceiveBufferSize(int32 size
) {
500 DCHECK_NE(socket_
, INVALID_SOCKET
);
501 DCHECK(CalledOnValidThread());
502 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
503 reinterpret_cast<const char*>(&size
), sizeof(size
));
505 return MapSystemError(WSAGetLastError());
507 // According to documentation, setsockopt may succeed, but we need to check
508 // the results via getsockopt to be sure it works on Windows.
509 int32 actual_size
= 0;
510 int option_size
= sizeof(actual_size
);
511 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
512 reinterpret_cast<char*>(&actual_size
), &option_size
);
514 return MapSystemError(WSAGetLastError());
515 if (actual_size
>= size
)
517 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
518 actual_size
, 1000, 1000000, 50);
519 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
522 int UDPSocketWin::SetSendBufferSize(int32 size
) {
523 DCHECK_NE(socket_
, INVALID_SOCKET
);
524 DCHECK(CalledOnValidThread());
525 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
526 reinterpret_cast<const char*>(&size
), sizeof(size
));
528 return MapSystemError(WSAGetLastError());
529 // According to documentation, setsockopt may succeed, but we need to check
530 // the results via getsockopt to be sure it works on Windows.
531 int32 actual_size
= 0;
532 int option_size
= sizeof(actual_size
);
533 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
534 reinterpret_cast<char*>(&actual_size
), &option_size
);
536 return MapSystemError(WSAGetLastError());
537 if (actual_size
>= size
)
539 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
540 actual_size
, 1000, 1000000, 50);
541 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
544 int UDPSocketWin::AllowAddressReuse() {
545 DCHECK_NE(socket_
, INVALID_SOCKET
);
546 DCHECK(CalledOnValidThread());
547 DCHECK(!is_connected());
549 BOOL true_value
= TRUE
;
550 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
551 reinterpret_cast<const char*>(&true_value
),
553 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
556 int UDPSocketWin::SetBroadcast(bool broadcast
) {
557 DCHECK_NE(socket_
, INVALID_SOCKET
);
558 DCHECK(CalledOnValidThread());
560 BOOL value
= broadcast
? TRUE
: FALSE
;
561 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
562 reinterpret_cast<const char*>(&value
), sizeof(value
));
563 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
566 void UDPSocketWin::DoReadCallback(int rv
) {
567 DCHECK_NE(rv
, ERR_IO_PENDING
);
568 DCHECK(!read_callback_
.is_null());
570 // since Run may result in Read being called, clear read_callback_ up front.
571 CompletionCallback c
= read_callback_
;
572 read_callback_
.Reset();
574 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/462789 is fixed.
575 tracked_objects::ScopedTracker
tracking_profile(
576 FROM_HERE_WITH_EXPLICIT_FUNCTION("462789 UDPSocketWin::DoReadCallback"));
581 void UDPSocketWin::DoWriteCallback(int rv
) {
582 DCHECK_NE(rv
, ERR_IO_PENDING
);
583 DCHECK(!write_callback_
.is_null());
585 // since Run may result in Write being called, clear write_callback_ up front.
586 CompletionCallback c
= write_callback_
;
587 write_callback_
.Reset();
591 void UDPSocketWin::DidCompleteRead() {
592 DWORD num_bytes
, flags
;
593 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
594 &num_bytes
, FALSE
, &flags
);
595 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
596 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
599 IPEndPoint
* address_to_log
= NULL
;
601 if (address
.FromSockAddr(core_
->recv_addr_storage_
.addr
,
602 core_
->recv_addr_storage_
.addr_len
)) {
603 if (recv_from_address_
)
604 *recv_from_address_
= address
;
605 address_to_log
= &address
;
607 result
= ERR_ADDRESS_INVALID
;
610 LogRead(result
, core_
->read_iobuffer_
->data(), address_to_log
);
611 core_
->read_iobuffer_
= NULL
;
612 recv_from_address_
= NULL
;
613 DoReadCallback(result
);
616 void UDPSocketWin::DidCompleteWrite() {
617 DWORD num_bytes
, flags
;
618 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
619 &num_bytes
, FALSE
, &flags
);
620 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
621 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
622 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
624 send_to_address_
.reset();
625 core_
->write_iobuffer_
= NULL
;
626 DoWriteCallback(result
);
629 void UDPSocketWin::OnObjectSignaled(HANDLE object
) {
630 DCHECK(object
== read_write_event_
.Get());
631 WSANETWORKEVENTS network_events
;
634 WSAEnumNetworkEvents(socket_
, read_write_event_
.Get(), &network_events
);
635 if (rv
== SOCKET_ERROR
) {
636 os_error
= WSAGetLastError();
637 rv
= MapSystemError(os_error
);
638 if (read_iobuffer_
) {
639 read_iobuffer_
= NULL
;
640 read_iobuffer_len_
= 0;
641 recv_from_address_
= NULL
;
644 if (write_iobuffer_
) {
645 write_iobuffer_
= NULL
;
646 write_iobuffer_len_
= 0;
647 send_to_address_
.reset();
652 if ((network_events
.lNetworkEvents
& FD_READ
) && read_iobuffer_
) {
655 if ((network_events
.lNetworkEvents
& FD_WRITE
) && write_iobuffer_
) {
659 // There's still pending read / write. Watch for further events.
660 if (read_iobuffer_
|| write_iobuffer_
) {
665 void UDPSocketWin::OnReadSignaled() {
666 int rv
= InternalRecvFromNonBlocking(read_iobuffer_
.get(), read_iobuffer_len_
,
668 if (rv
== ERR_IO_PENDING
)
670 read_iobuffer_
= NULL
;
671 read_iobuffer_len_
= 0;
672 recv_from_address_
= NULL
;
676 void UDPSocketWin::OnWriteSignaled() {
677 int rv
= InternalSendToNonBlocking(write_iobuffer_
.get(), write_iobuffer_len_
,
678 send_to_address_
.get());
679 if (rv
== ERR_IO_PENDING
)
681 write_iobuffer_
= NULL
;
682 write_iobuffer_len_
= 0;
683 send_to_address_
.reset();
687 void UDPSocketWin::WatchForReadWrite() {
688 if (read_write_watcher_
.IsWatching())
691 read_write_watcher_
.StartWatching(read_write_event_
.Get(), this);
695 void UDPSocketWin::LogRead(int result
,
697 const IPEndPoint
* address
) const {
699 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
703 if (net_log_
.IsLogging()) {
705 NetLog::TYPE_UDP_BYTES_RECEIVED
,
706 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
709 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result
);
712 void UDPSocketWin::LogWrite(int result
,
714 const IPEndPoint
* address
) const {
716 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
720 if (net_log_
.IsLogging()) {
722 NetLog::TYPE_UDP_BYTES_SENT
,
723 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
726 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result
);
729 int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer
* buf
,
731 IPEndPoint
* address
) {
732 DCHECK(!core_
->read_iobuffer_
.get());
733 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
734 storage
.addr_len
= sizeof(storage
.addr_storage
);
737 read_buffer
.buf
= buf
->data();
738 read_buffer
.len
= buf_len
;
742 CHECK_NE(INVALID_SOCKET
, socket_
);
743 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
744 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
745 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
747 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
750 IPEndPoint address_storage
;
751 IPEndPoint
* address_to_log
= NULL
;
753 if (address_storage
.FromSockAddr(core_
->recv_addr_storage_
.addr
,
754 core_
->recv_addr_storage_
.addr_len
)) {
756 *address
= address_storage
;
757 address_to_log
= &address_storage
;
759 result
= ERR_ADDRESS_INVALID
;
762 LogRead(result
, buf
->data(), address_to_log
);
766 int os_error
= WSAGetLastError();
767 if (os_error
!= WSA_IO_PENDING
) {
768 int result
= MapSystemError(os_error
);
769 LogRead(result
, NULL
, NULL
);
773 core_
->WatchForRead();
774 core_
->read_iobuffer_
= buf
;
775 return ERR_IO_PENDING
;
778 int UDPSocketWin::InternalSendToOverlapped(IOBuffer
* buf
,
780 const IPEndPoint
* address
) {
781 DCHECK(!core_
->write_iobuffer_
.get());
782 SockaddrStorage storage
;
783 struct sockaddr
* addr
= storage
.addr
;
787 storage
.addr_len
= 0;
789 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
790 int result
= ERR_ADDRESS_INVALID
;
791 LogWrite(result
, NULL
, NULL
);
797 write_buffer
.buf
= buf
->data();
798 write_buffer
.len
= buf_len
;
802 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
803 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
804 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
806 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
808 LogWrite(result
, buf
->data(), address
);
812 int os_error
= WSAGetLastError();
813 if (os_error
!= WSA_IO_PENDING
) {
814 int result
= MapSystemError(os_error
);
815 LogWrite(result
, NULL
, NULL
);
820 core_
->WatchForWrite();
821 core_
->write_iobuffer_
= buf
;
822 return ERR_IO_PENDING
;
825 int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer
* buf
,
827 IPEndPoint
* address
) {
828 DCHECK(!read_iobuffer_
|| read_iobuffer_
.get() == buf
);
829 SockaddrStorage storage
;
830 storage
.addr_len
= sizeof(storage
.addr_storage
);
832 CHECK_NE(INVALID_SOCKET
, socket_
);
833 int rv
= recvfrom(socket_
, buf
->data(), buf_len
, 0, storage
.addr
,
835 if (rv
== SOCKET_ERROR
) {
836 int os_error
= WSAGetLastError();
837 if (os_error
== WSAEWOULDBLOCK
) {
838 read_iobuffer_
= buf
;
839 read_iobuffer_len_
= buf_len
;
841 return ERR_IO_PENDING
;
843 rv
= MapSystemError(os_error
);
844 LogRead(rv
, NULL
, NULL
);
847 IPEndPoint address_storage
;
848 IPEndPoint
* address_to_log
= NULL
;
850 if (address_storage
.FromSockAddr(storage
.addr
, storage
.addr_len
)) {
852 *address
= address_storage
;
853 address_to_log
= &address_storage
;
855 rv
= ERR_ADDRESS_INVALID
;
858 LogRead(rv
, buf
->data(), address_to_log
);
862 int UDPSocketWin::InternalSendToNonBlocking(IOBuffer
* buf
,
864 const IPEndPoint
* address
) {
865 DCHECK(!write_iobuffer_
|| write_iobuffer_
.get() == buf
);
866 SockaddrStorage storage
;
867 struct sockaddr
* addr
= storage
.addr
;
870 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
871 int result
= ERR_ADDRESS_INVALID
;
872 LogWrite(result
, NULL
, NULL
);
877 storage
.addr_len
= 0;
880 int rv
= sendto(socket_
, buf
->data(), buf_len
, 0, addr
, storage
.addr_len
);
881 if (rv
== SOCKET_ERROR
) {
882 int os_error
= WSAGetLastError();
883 if (os_error
== WSAEWOULDBLOCK
) {
884 write_iobuffer_
= buf
;
885 write_iobuffer_len_
= buf_len
;
887 return ERR_IO_PENDING
;
889 rv
= MapSystemError(os_error
);
890 LogWrite(rv
, NULL
, NULL
);
893 LogWrite(rv
, buf
->data(), address
);
897 int UDPSocketWin::SetMulticastOptions() {
898 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
901 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
903 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
904 int rv
= setsockopt(socket_
, protocol_level
, option
,
905 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
907 return MapSystemError(WSAGetLastError());
909 if (multicast_time_to_live_
!= 1) {
910 DWORD hops
= multicast_time_to_live_
;
912 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
914 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
915 int rv
= setsockopt(socket_
, protocol_level
, option
,
916 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
918 return MapSystemError(WSAGetLastError());
920 if (multicast_interface_
!= 0) {
921 switch (addr_family_
) {
924 address
.s_addr
= htonl(multicast_interface_
);
925 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
926 reinterpret_cast<const char*>(&address
),
929 return MapSystemError(WSAGetLastError());
933 uint32 interface_index
= multicast_interface_
;
934 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
935 reinterpret_cast<const char*>(&interface_index
),
936 sizeof(interface_index
));
938 return MapSystemError(WSAGetLastError());
942 NOTREACHED() << "Invalid address family";
943 return ERR_ADDRESS_INVALID
;
949 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
950 SockaddrStorage storage
;
951 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
952 return ERR_ADDRESS_INVALID
;
953 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
956 int last_error
= WSAGetLastError();
957 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
958 // Map some codes that are special to bind() separately.
959 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
960 // returned instead of WSAEADDRINUSE, depending on whether the socket
961 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
962 // conflicting socket is owned by a different user account. See the MSDN
963 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
964 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
965 return ERR_ADDRESS_IN_USE
;
966 return MapSystemError(last_error
);
969 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
970 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
972 for (int i
= 0; i
< kBindRetries
; ++i
) {
973 int rv
= DoBind(IPEndPoint(
974 address
, static_cast<uint16
>(rand_int_cb_
.Run(kPortStart
, kPortEnd
))));
975 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
978 return DoBind(IPEndPoint(address
, 0));
981 int UDPSocketWin::JoinGroup(
982 const IPAddressNumber
& group_address
) const {
983 DCHECK(CalledOnValidThread());
985 return ERR_SOCKET_NOT_CONNECTED
;
987 switch (group_address
.size()) {
988 case kIPv4AddressSize
: {
989 if (addr_family_
!= AF_INET
)
990 return ERR_ADDRESS_INVALID
;
992 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
993 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
994 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
995 reinterpret_cast<const char*>(&mreq
),
998 return MapSystemError(WSAGetLastError());
1001 case kIPv6AddressSize
: {
1002 if (addr_family_
!= AF_INET6
)
1003 return ERR_ADDRESS_INVALID
;
1005 mreq
.ipv6mr_interface
= multicast_interface_
;
1006 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
1007 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
1008 reinterpret_cast<const char*>(&mreq
),
1011 return MapSystemError(WSAGetLastError());
1015 NOTREACHED() << "Invalid address family";
1016 return ERR_ADDRESS_INVALID
;
1020 int UDPSocketWin::LeaveGroup(
1021 const IPAddressNumber
& group_address
) const {
1022 DCHECK(CalledOnValidThread());
1023 if (!is_connected())
1024 return ERR_SOCKET_NOT_CONNECTED
;
1026 switch (group_address
.size()) {
1027 case kIPv4AddressSize
: {
1028 if (addr_family_
!= AF_INET
)
1029 return ERR_ADDRESS_INVALID
;
1031 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
1032 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
1033 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
1034 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
1036 return MapSystemError(WSAGetLastError());
1039 case kIPv6AddressSize
: {
1040 if (addr_family_
!= AF_INET6
)
1041 return ERR_ADDRESS_INVALID
;
1043 mreq
.ipv6mr_interface
= multicast_interface_
;
1044 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
1045 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
1046 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
1048 return MapSystemError(WSAGetLastError());
1052 NOTREACHED() << "Invalid address family";
1053 return ERR_ADDRESS_INVALID
;
1057 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
1058 DCHECK(CalledOnValidThread());
1060 return ERR_SOCKET_IS_CONNECTED
;
1061 multicast_interface_
= interface_index
;
1065 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
1066 DCHECK(CalledOnValidThread());
1068 return ERR_SOCKET_IS_CONNECTED
;
1070 if (time_to_live
< 0 || time_to_live
> 255)
1071 return ERR_INVALID_ARGUMENT
;
1072 multicast_time_to_live_
= time_to_live
;
1076 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
1077 DCHECK(CalledOnValidThread());
1079 return ERR_SOCKET_IS_CONNECTED
;
1082 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
1084 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
1088 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
1089 if (dscp
== DSCP_NO_CHANGE
) {
1093 if (!is_connected())
1094 return ERR_SOCKET_NOT_CONNECTED
;
1096 QwaveAPI
& qos(QwaveAPI::Get());
1098 if (!qos
.qwave_supported())
1099 return ERROR_NOT_SUPPORTED
;
1101 if (qos_handle_
== NULL
) {
1102 QOS_VERSION version
;
1103 version
.MajorVersion
= 1;
1104 version
.MinorVersion
= 0;
1105 qos
.CreateHandle(&version
, &qos_handle_
);
1106 if (qos_handle_
== NULL
)
1107 return ERROR_NOT_SUPPORTED
;
1110 QOS_TRAFFIC_TYPE traffic_type
= QOSTrafficTypeBestEffort
;
1113 traffic_type
= QOSTrafficTypeBestEffort
;
1116 traffic_type
= QOSTrafficTypeBackground
;
1130 traffic_type
= QOSTrafficTypeExcellentEffort
;
1136 traffic_type
= QOSTrafficTypeAudioVideo
;
1140 traffic_type
= QOSTrafficTypeVoice
;
1143 traffic_type
= QOSTrafficTypeControl
;
1145 case DSCP_NO_CHANGE
:
1149 if (qos_flow_id_
!= 0) {
1150 qos
.RemoveSocketFromFlow(qos_handle_
, NULL
, qos_flow_id_
, 0);
1153 if (!qos
.AddSocketToFlow(qos_handle_
,
1157 QOS_NON_ADAPTIVE_FLOW
,
1159 DWORD err
= GetLastError();
1160 if (err
== ERROR_DEVICE_REINITIALIZATION_NEEDED
) {
1161 qos
.CloseHandle(qos_handle_
);
1165 return MapSystemError(err
);
1167 // This requires admin rights, and may fail, if so we ignore it
1168 // as AddSocketToFlow should still do *approximately* the right thing.
1170 qos
.SetFlow(qos_handle_
,
1172 QOSSetOutgoingDSCPValue
,
1181 void UDPSocketWin::DetachFromThread() {
1182 base::NonThreadSafe::DetachFromThread();
1185 void UDPSocketWin::UseNonBlockingIO() {
1187 use_non_blocking_io_
= true;