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_macros.h"
15 #include "base/metrics/sparse_histogram.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_util.h"
21 #include "net/base/network_activity_monitor.h"
22 #include "net/base/winsock_init.h"
23 #include "net/base/winsock_util.h"
24 #include "net/log/net_log.h"
25 #include "net/socket/socket_descriptor.h"
26 #include "net/udp/udp_net_log_parameters.h"
30 const int kBindRetries
= 10;
31 const int kPortStart
= 1024;
32 const int kPortEnd
= 65535;
38 // This class encapsulates all the state that has to be preserved as long as
39 // there is a network IO operation in progress. If the owner UDPSocketWin
40 // is destroyed while an operation is in progress, the Core is detached and it
41 // lives until the operation completes and the OS doesn't reference any resource
42 // declared on this class anymore.
43 class UDPSocketWin::Core
: public base::RefCounted
<Core
> {
45 explicit Core(UDPSocketWin
* socket
);
47 // Start watching for the end of a read or write operation.
51 // The UDPSocketWin is going away.
52 void Detach() { socket_
= NULL
; }
54 // The separate OVERLAPPED variables for asynchronous operation.
55 OVERLAPPED read_overlapped_
;
56 OVERLAPPED write_overlapped_
;
58 // The buffers used in Read() and Write().
59 scoped_refptr
<IOBuffer
> read_iobuffer_
;
60 scoped_refptr
<IOBuffer
> write_iobuffer_
;
62 // The address storage passed to WSARecvFrom().
63 SockaddrStorage recv_addr_storage_
;
66 friend class base::RefCounted
<Core
>;
68 class ReadDelegate
: public base::win::ObjectWatcher::Delegate
{
70 explicit ReadDelegate(Core
* core
) : core_(core
) {}
71 ~ReadDelegate() override
{}
73 // base::ObjectWatcher::Delegate methods:
74 void OnObjectSignaled(HANDLE object
) override
;
80 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
82 explicit WriteDelegate(Core
* core
) : core_(core
) {}
83 ~WriteDelegate() override
{}
85 // base::ObjectWatcher::Delegate methods:
86 void OnObjectSignaled(HANDLE object
) override
;
94 // The socket that created this object.
95 UDPSocketWin
* socket_
;
97 // |reader_| handles the signals from |read_watcher_|.
99 // |writer_| handles the signals from |write_watcher_|.
100 WriteDelegate writer_
;
102 // |read_watcher_| watches for events from Read().
103 base::win::ObjectWatcher read_watcher_
;
104 // |write_watcher_| watches for events from Write();
105 base::win::ObjectWatcher write_watcher_
;
107 DISALLOW_COPY_AND_ASSIGN(Core
);
110 UDPSocketWin::Core::Core(UDPSocketWin
* socket
)
114 memset(&read_overlapped_
, 0, sizeof(read_overlapped_
));
115 memset(&write_overlapped_
, 0, sizeof(write_overlapped_
));
117 read_overlapped_
.hEvent
= WSACreateEvent();
118 write_overlapped_
.hEvent
= WSACreateEvent();
121 UDPSocketWin::Core::~Core() {
122 // Make sure the message loop is not watching this object anymore.
123 read_watcher_
.StopWatching();
124 write_watcher_
.StopWatching();
126 WSACloseEvent(read_overlapped_
.hEvent
);
127 memset(&read_overlapped_
, 0xaf, sizeof(read_overlapped_
));
128 WSACloseEvent(write_overlapped_
.hEvent
);
129 memset(&write_overlapped_
, 0xaf, sizeof(write_overlapped_
));
132 void UDPSocketWin::Core::WatchForRead() {
133 // We grab an extra reference because there is an IO operation in progress.
134 // Balanced in ReadDelegate::OnObjectSignaled().
136 read_watcher_
.StartWatching(read_overlapped_
.hEvent
, &reader_
);
139 void UDPSocketWin::Core::WatchForWrite() {
140 // We grab an extra reference because there is an IO operation in progress.
141 // Balanced in WriteDelegate::OnObjectSignaled().
143 write_watcher_
.StartWatching(write_overlapped_
.hEvent
, &writer_
);
146 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object
) {
147 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
149 core_
->socket_
->DidCompleteRead();
154 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
155 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
157 core_
->socket_
->DidCompleteWrite();
161 //-----------------------------------------------------------------------------
163 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
164 HMODULE qwave
= LoadLibrary(L
"qwave.dll");
167 create_handle_func_
=
168 (CreateHandleFn
)GetProcAddress(qwave
, "QOSCreateHandle");
170 (CloseHandleFn
)GetProcAddress(qwave
, "QOSCloseHandle");
171 add_socket_to_flow_func_
=
172 (AddSocketToFlowFn
)GetProcAddress(qwave
, "QOSAddSocketToFlow");
173 remove_socket_from_flow_func_
=
174 (RemoveSocketFromFlowFn
)GetProcAddress(qwave
, "QOSRemoveSocketFromFlow");
175 set_flow_func_
= (SetFlowFn
)GetProcAddress(qwave
, "QOSSetFlow");
177 if (create_handle_func_
&& close_handle_func_
&&
178 add_socket_to_flow_func_
&& remove_socket_from_flow_func_
&&
180 qwave_supported_
= true;
184 QwaveAPI
& QwaveAPI::Get() {
185 static base::LazyInstance
<QwaveAPI
>::Leaky lazy_qwave
=
186 LAZY_INSTANCE_INITIALIZER
;
187 return lazy_qwave
.Get();
190 bool QwaveAPI::qwave_supported() const {
191 return qwave_supported_
;
193 BOOL
QwaveAPI::CreateHandle(PQOS_VERSION version
, PHANDLE handle
) {
194 return create_handle_func_(version
, handle
);
196 BOOL
QwaveAPI::CloseHandle(HANDLE handle
) {
197 return close_handle_func_(handle
);
200 BOOL
QwaveAPI::AddSocketToFlow(HANDLE handle
,
203 QOS_TRAFFIC_TYPE traffic_type
,
205 PQOS_FLOWID flow_id
) {
206 return add_socket_to_flow_func_(handle
,
214 BOOL
QwaveAPI::RemoveSocketFromFlow(HANDLE handle
,
218 return remove_socket_from_flow_func_(handle
, socket
, flow_id
, reserved
);
221 BOOL
QwaveAPI::SetFlow(HANDLE handle
,
227 LPOVERLAPPED overlapped
) {
228 return set_flow_func_(handle
,
238 //-----------------------------------------------------------------------------
240 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type
,
241 const RandIntCallback
& rand_int_cb
,
242 net::NetLog
* net_log
,
243 const net::NetLog::Source
& source
)
244 : socket_(INVALID_SOCKET
),
246 is_connected_(false),
247 socket_options_(SOCKET_OPTION_MULTICAST_LOOP
),
248 multicast_interface_(0),
249 multicast_time_to_live_(1),
250 bind_type_(bind_type
),
251 rand_int_cb_(rand_int_cb
),
252 use_non_blocking_io_(false),
253 read_iobuffer_len_(0),
254 write_iobuffer_len_(0),
255 recv_from_address_(NULL
),
256 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_UDP_SOCKET
)),
260 net_log_
.BeginEvent(NetLog::TYPE_SOCKET_ALIVE
,
261 source
.ToEventParametersCallback());
262 if (bind_type
== DatagramSocket::RANDOM_BIND
)
263 DCHECK(!rand_int_cb
.is_null());
266 UDPSocketWin::~UDPSocketWin() {
268 net_log_
.EndEvent(NetLog::TYPE_SOCKET_ALIVE
);
271 int UDPSocketWin::Open(AddressFamily address_family
) {
272 DCHECK(CalledOnValidThread());
273 DCHECK_EQ(socket_
, INVALID_SOCKET
);
275 addr_family_
= ConvertAddressFamily(address_family
);
276 socket_
= CreatePlatformSocket(addr_family_
, SOCK_DGRAM
, IPPROTO_UDP
);
277 if (socket_
== INVALID_SOCKET
)
278 return MapSystemError(WSAGetLastError());
279 if (!use_non_blocking_io_
) {
280 core_
= new Core(this);
282 read_write_event_
.Set(WSACreateEvent());
283 WSAEventSelect(socket_
, read_write_event_
.Get(), FD_READ
| FD_WRITE
);
288 void UDPSocketWin::Close() {
289 DCHECK(CalledOnValidThread());
291 if (socket_
== INVALID_SOCKET
)
295 QwaveAPI::Get().CloseHandle(qos_handle_
);
298 // Zero out any pending read/write callback state.
299 read_callback_
.Reset();
300 recv_from_address_
= NULL
;
301 write_callback_
.Reset();
303 base::TimeTicks start_time
= base::TimeTicks::Now();
304 closesocket(socket_
);
305 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
306 base::TimeTicks::Now() - start_time
);
307 socket_
= INVALID_SOCKET
;
309 is_connected_
= false;
311 read_write_watcher_
.StopWatching();
312 read_write_event_
.Close();
320 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
321 DCHECK(CalledOnValidThread());
324 return ERR_SOCKET_NOT_CONNECTED
;
326 // TODO(szym): Simplify. http://crbug.com/126152
327 if (!remote_address_
.get()) {
328 SockaddrStorage storage
;
329 if (getpeername(socket_
, storage
.addr
, &storage
.addr_len
))
330 return MapSystemError(WSAGetLastError());
331 scoped_ptr
<IPEndPoint
> remote_address(new IPEndPoint());
332 if (!remote_address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
333 return ERR_ADDRESS_INVALID
;
334 remote_address_
.reset(remote_address
.release());
337 *address
= *remote_address_
;
341 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
342 DCHECK(CalledOnValidThread());
345 return ERR_SOCKET_NOT_CONNECTED
;
347 // TODO(szym): Simplify. http://crbug.com/126152
348 if (!local_address_
.get()) {
349 SockaddrStorage storage
;
350 if (getsockname(socket_
, storage
.addr
, &storage
.addr_len
))
351 return MapSystemError(WSAGetLastError());
352 scoped_ptr
<IPEndPoint
> local_address(new IPEndPoint());
353 if (!local_address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
354 return ERR_ADDRESS_INVALID
;
355 local_address_
.reset(local_address
.release());
356 net_log_
.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS
,
357 CreateNetLogUDPConnectCallback(local_address_
.get()));
360 *address
= *local_address_
;
364 int UDPSocketWin::Read(IOBuffer
* buf
,
366 const CompletionCallback
& callback
) {
367 return RecvFrom(buf
, buf_len
, NULL
, callback
);
370 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
373 const CompletionCallback
& callback
) {
374 DCHECK(CalledOnValidThread());
375 DCHECK_NE(INVALID_SOCKET
, socket_
);
376 CHECK(read_callback_
.is_null());
377 DCHECK(!recv_from_address_
);
378 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
379 DCHECK_GT(buf_len
, 0);
381 int nread
= core_
? InternalRecvFromOverlapped(buf
, buf_len
, address
)
382 : InternalRecvFromNonBlocking(buf
, buf_len
, address
);
383 if (nread
!= ERR_IO_PENDING
)
386 read_callback_
= callback
;
387 recv_from_address_
= address
;
388 return ERR_IO_PENDING
;
391 int UDPSocketWin::Write(IOBuffer
* buf
,
393 const CompletionCallback
& callback
) {
394 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
397 int UDPSocketWin::SendTo(IOBuffer
* buf
,
399 const IPEndPoint
& address
,
400 const CompletionCallback
& callback
) {
401 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
404 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
406 const IPEndPoint
* address
,
407 const CompletionCallback
& callback
) {
408 DCHECK(CalledOnValidThread());
409 DCHECK_NE(INVALID_SOCKET
, socket_
);
410 CHECK(write_callback_
.is_null());
411 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
412 DCHECK_GT(buf_len
, 0);
413 DCHECK(!send_to_address_
.get());
415 int nwrite
= core_
? InternalSendToOverlapped(buf
, buf_len
, address
)
416 : InternalSendToNonBlocking(buf
, buf_len
, address
);
417 if (nwrite
!= ERR_IO_PENDING
)
421 send_to_address_
.reset(new IPEndPoint(*address
));
422 write_callback_
= callback
;
423 return ERR_IO_PENDING
;
426 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
427 DCHECK_NE(socket_
, INVALID_SOCKET
);
428 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
429 CreateNetLogUDPConnectCallback(&address
));
430 int rv
= InternalConnect(address
);
431 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
432 is_connected_
= (rv
== OK
);
436 int UDPSocketWin::InternalConnect(const IPEndPoint
& address
) {
437 DCHECK(!is_connected());
438 DCHECK(!remote_address_
.get());
441 if (bind_type_
== DatagramSocket::RANDOM_BIND
) {
442 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
443 // representing INADDR_ANY or in6addr_any.
444 size_t addr_size
= (address
.GetSockAddrFamily() == AF_INET
) ?
445 kIPv4AddressSize
: kIPv6AddressSize
;
446 IPAddressNumber
addr_any(addr_size
);
447 rv
= RandomBind(addr_any
);
449 // else connect() does the DatagramSocket::DEFAULT_BIND
452 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
456 SockaddrStorage storage
;
457 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
458 return ERR_ADDRESS_INVALID
;
460 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
462 return MapSystemError(WSAGetLastError());
464 remote_address_
.reset(new IPEndPoint(address
));
468 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
469 DCHECK_NE(socket_
, INVALID_SOCKET
);
470 DCHECK(!is_connected());
472 int rv
= SetMulticastOptions();
476 rv
= DoBind(address
);
480 local_address_
.reset();
481 is_connected_
= true;
485 int UDPSocketWin::SetReceiveBufferSize(int32 size
) {
486 DCHECK_NE(socket_
, INVALID_SOCKET
);
487 DCHECK(CalledOnValidThread());
488 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
489 reinterpret_cast<const char*>(&size
), sizeof(size
));
491 return MapSystemError(WSAGetLastError());
493 // According to documentation, setsockopt may succeed, but we need to check
494 // the results via getsockopt to be sure it works on Windows.
495 int32 actual_size
= 0;
496 int option_size
= sizeof(actual_size
);
497 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
498 reinterpret_cast<char*>(&actual_size
), &option_size
);
500 return MapSystemError(WSAGetLastError());
501 if (actual_size
>= size
)
503 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
504 actual_size
, 1000, 1000000, 50);
505 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
508 int UDPSocketWin::SetSendBufferSize(int32 size
) {
509 DCHECK_NE(socket_
, INVALID_SOCKET
);
510 DCHECK(CalledOnValidThread());
511 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
512 reinterpret_cast<const char*>(&size
), sizeof(size
));
514 return MapSystemError(WSAGetLastError());
515 // According to documentation, setsockopt may succeed, but we need to check
516 // the results via getsockopt to be sure it works on Windows.
517 int32 actual_size
= 0;
518 int option_size
= sizeof(actual_size
);
519 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
520 reinterpret_cast<char*>(&actual_size
), &option_size
);
522 return MapSystemError(WSAGetLastError());
523 if (actual_size
>= size
)
525 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
526 actual_size
, 1000, 1000000, 50);
527 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
530 int UDPSocketWin::AllowAddressReuse() {
531 DCHECK_NE(socket_
, INVALID_SOCKET
);
532 DCHECK(CalledOnValidThread());
533 DCHECK(!is_connected());
535 BOOL true_value
= TRUE
;
536 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
537 reinterpret_cast<const char*>(&true_value
),
539 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
542 int UDPSocketWin::SetBroadcast(bool broadcast
) {
543 DCHECK_NE(socket_
, INVALID_SOCKET
);
544 DCHECK(CalledOnValidThread());
546 BOOL value
= broadcast
? TRUE
: FALSE
;
547 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
548 reinterpret_cast<const char*>(&value
), sizeof(value
));
549 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
552 void UDPSocketWin::DoReadCallback(int rv
) {
553 DCHECK_NE(rv
, ERR_IO_PENDING
);
554 DCHECK(!read_callback_
.is_null());
556 // since Run may result in Read being called, clear read_callback_ up front.
557 CompletionCallback c
= read_callback_
;
558 read_callback_
.Reset();
562 void UDPSocketWin::DoWriteCallback(int rv
) {
563 DCHECK_NE(rv
, ERR_IO_PENDING
);
564 DCHECK(!write_callback_
.is_null());
566 // since Run may result in Write being called, clear write_callback_ up front.
567 CompletionCallback c
= write_callback_
;
568 write_callback_
.Reset();
572 void UDPSocketWin::DidCompleteRead() {
573 DWORD num_bytes
, flags
;
574 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
575 &num_bytes
, FALSE
, &flags
);
576 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
577 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
580 IPEndPoint
* address_to_log
= NULL
;
582 if (address
.FromSockAddr(core_
->recv_addr_storage_
.addr
,
583 core_
->recv_addr_storage_
.addr_len
)) {
584 if (recv_from_address_
)
585 *recv_from_address_
= address
;
586 address_to_log
= &address
;
588 result
= ERR_ADDRESS_INVALID
;
591 LogRead(result
, core_
->read_iobuffer_
->data(), address_to_log
);
592 core_
->read_iobuffer_
= NULL
;
593 recv_from_address_
= NULL
;
594 DoReadCallback(result
);
597 void UDPSocketWin::DidCompleteWrite() {
598 DWORD num_bytes
, flags
;
599 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
600 &num_bytes
, FALSE
, &flags
);
601 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
602 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
603 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
605 send_to_address_
.reset();
606 core_
->write_iobuffer_
= NULL
;
607 DoWriteCallback(result
);
610 void UDPSocketWin::OnObjectSignaled(HANDLE object
) {
611 DCHECK(object
== read_write_event_
.Get());
612 WSANETWORKEVENTS network_events
;
615 WSAEnumNetworkEvents(socket_
, read_write_event_
.Get(), &network_events
);
616 if (rv
== SOCKET_ERROR
) {
617 os_error
= WSAGetLastError();
618 rv
= MapSystemError(os_error
);
619 if (read_iobuffer_
) {
620 read_iobuffer_
= NULL
;
621 read_iobuffer_len_
= 0;
622 recv_from_address_
= NULL
;
625 if (write_iobuffer_
) {
626 write_iobuffer_
= NULL
;
627 write_iobuffer_len_
= 0;
628 send_to_address_
.reset();
633 if ((network_events
.lNetworkEvents
& FD_READ
) && read_iobuffer_
) {
636 if ((network_events
.lNetworkEvents
& FD_WRITE
) && write_iobuffer_
) {
640 // There's still pending read / write. Watch for further events.
641 if (read_iobuffer_
|| write_iobuffer_
) {
646 void UDPSocketWin::OnReadSignaled() {
647 int rv
= InternalRecvFromNonBlocking(read_iobuffer_
.get(), read_iobuffer_len_
,
649 if (rv
== ERR_IO_PENDING
)
651 read_iobuffer_
= NULL
;
652 read_iobuffer_len_
= 0;
653 recv_from_address_
= NULL
;
657 void UDPSocketWin::OnWriteSignaled() {
658 int rv
= InternalSendToNonBlocking(write_iobuffer_
.get(), write_iobuffer_len_
,
659 send_to_address_
.get());
660 if (rv
== ERR_IO_PENDING
)
662 write_iobuffer_
= NULL
;
663 write_iobuffer_len_
= 0;
664 send_to_address_
.reset();
668 void UDPSocketWin::WatchForReadWrite() {
669 if (read_write_watcher_
.IsWatching())
672 read_write_watcher_
.StartWatching(read_write_event_
.Get(), this);
676 void UDPSocketWin::LogRead(int result
,
678 const IPEndPoint
* address
) const {
680 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
684 if (net_log_
.IsCapturing()) {
686 NetLog::TYPE_UDP_BYTES_RECEIVED
,
687 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
690 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result
);
693 void UDPSocketWin::LogWrite(int result
,
695 const IPEndPoint
* address
) const {
697 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
701 if (net_log_
.IsCapturing()) {
703 NetLog::TYPE_UDP_BYTES_SENT
,
704 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
707 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result
);
710 int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer
* buf
,
712 IPEndPoint
* address
) {
713 DCHECK(!core_
->read_iobuffer_
.get());
714 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
715 storage
.addr_len
= sizeof(storage
.addr_storage
);
718 read_buffer
.buf
= buf
->data();
719 read_buffer
.len
= buf_len
;
723 CHECK_NE(INVALID_SOCKET
, socket_
);
724 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
725 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
726 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
728 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
731 IPEndPoint address_storage
;
732 IPEndPoint
* address_to_log
= NULL
;
734 if (address_storage
.FromSockAddr(core_
->recv_addr_storage_
.addr
,
735 core_
->recv_addr_storage_
.addr_len
)) {
737 *address
= address_storage
;
738 address_to_log
= &address_storage
;
740 result
= ERR_ADDRESS_INVALID
;
743 LogRead(result
, buf
->data(), address_to_log
);
747 int os_error
= WSAGetLastError();
748 if (os_error
!= WSA_IO_PENDING
) {
749 int result
= MapSystemError(os_error
);
750 LogRead(result
, NULL
, NULL
);
754 core_
->WatchForRead();
755 core_
->read_iobuffer_
= buf
;
756 return ERR_IO_PENDING
;
759 int UDPSocketWin::InternalSendToOverlapped(IOBuffer
* buf
,
761 const IPEndPoint
* address
) {
762 DCHECK(!core_
->write_iobuffer_
.get());
763 SockaddrStorage storage
;
764 struct sockaddr
* addr
= storage
.addr
;
768 storage
.addr_len
= 0;
770 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
771 int result
= ERR_ADDRESS_INVALID
;
772 LogWrite(result
, NULL
, NULL
);
778 write_buffer
.buf
= buf
->data();
779 write_buffer
.len
= buf_len
;
783 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
784 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
785 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
787 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
789 LogWrite(result
, buf
->data(), address
);
793 int os_error
= WSAGetLastError();
794 if (os_error
!= WSA_IO_PENDING
) {
795 int result
= MapSystemError(os_error
);
796 LogWrite(result
, NULL
, NULL
);
801 core_
->WatchForWrite();
802 core_
->write_iobuffer_
= buf
;
803 return ERR_IO_PENDING
;
806 int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer
* buf
,
808 IPEndPoint
* address
) {
809 DCHECK(!read_iobuffer_
|| read_iobuffer_
.get() == buf
);
810 SockaddrStorage storage
;
811 storage
.addr_len
= sizeof(storage
.addr_storage
);
813 CHECK_NE(INVALID_SOCKET
, socket_
);
814 int rv
= recvfrom(socket_
, buf
->data(), buf_len
, 0, storage
.addr
,
816 if (rv
== SOCKET_ERROR
) {
817 int os_error
= WSAGetLastError();
818 if (os_error
== WSAEWOULDBLOCK
) {
819 read_iobuffer_
= buf
;
820 read_iobuffer_len_
= buf_len
;
822 return ERR_IO_PENDING
;
824 rv
= MapSystemError(os_error
);
825 LogRead(rv
, NULL
, NULL
);
828 IPEndPoint address_storage
;
829 IPEndPoint
* address_to_log
= NULL
;
831 if (address_storage
.FromSockAddr(storage
.addr
, storage
.addr_len
)) {
833 *address
= address_storage
;
834 address_to_log
= &address_storage
;
836 rv
= ERR_ADDRESS_INVALID
;
839 LogRead(rv
, buf
->data(), address_to_log
);
843 int UDPSocketWin::InternalSendToNonBlocking(IOBuffer
* buf
,
845 const IPEndPoint
* address
) {
846 DCHECK(!write_iobuffer_
|| write_iobuffer_
.get() == buf
);
847 SockaddrStorage storage
;
848 struct sockaddr
* addr
= storage
.addr
;
851 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
852 int result
= ERR_ADDRESS_INVALID
;
853 LogWrite(result
, NULL
, NULL
);
858 storage
.addr_len
= 0;
861 int rv
= sendto(socket_
, buf
->data(), buf_len
, 0, addr
, storage
.addr_len
);
862 if (rv
== SOCKET_ERROR
) {
863 int os_error
= WSAGetLastError();
864 if (os_error
== WSAEWOULDBLOCK
) {
865 write_iobuffer_
= buf
;
866 write_iobuffer_len_
= buf_len
;
868 return ERR_IO_PENDING
;
870 rv
= MapSystemError(os_error
);
871 LogWrite(rv
, NULL
, NULL
);
874 LogWrite(rv
, buf
->data(), address
);
878 int UDPSocketWin::SetMulticastOptions() {
879 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
882 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
884 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
885 int rv
= setsockopt(socket_
, protocol_level
, option
,
886 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
888 return MapSystemError(WSAGetLastError());
890 if (multicast_time_to_live_
!= 1) {
891 DWORD hops
= multicast_time_to_live_
;
893 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
895 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
896 int rv
= setsockopt(socket_
, protocol_level
, option
,
897 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
899 return MapSystemError(WSAGetLastError());
901 if (multicast_interface_
!= 0) {
902 switch (addr_family_
) {
905 address
.s_addr
= htonl(multicast_interface_
);
906 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
907 reinterpret_cast<const char*>(&address
),
910 return MapSystemError(WSAGetLastError());
914 uint32 interface_index
= multicast_interface_
;
915 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
916 reinterpret_cast<const char*>(&interface_index
),
917 sizeof(interface_index
));
919 return MapSystemError(WSAGetLastError());
923 NOTREACHED() << "Invalid address family";
924 return ERR_ADDRESS_INVALID
;
930 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
931 SockaddrStorage storage
;
932 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
933 return ERR_ADDRESS_INVALID
;
934 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
937 int last_error
= WSAGetLastError();
938 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
939 // Map some codes that are special to bind() separately.
940 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
941 // returned instead of WSAEADDRINUSE, depending on whether the socket
942 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
943 // conflicting socket is owned by a different user account. See the MSDN
944 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
945 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
946 return ERR_ADDRESS_IN_USE
;
947 return MapSystemError(last_error
);
950 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
951 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
953 for (int i
= 0; i
< kBindRetries
; ++i
) {
954 int rv
= DoBind(IPEndPoint(
955 address
, static_cast<uint16
>(rand_int_cb_
.Run(kPortStart
, kPortEnd
))));
956 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
959 return DoBind(IPEndPoint(address
, 0));
962 int UDPSocketWin::JoinGroup(
963 const IPAddressNumber
& group_address
) const {
964 DCHECK(CalledOnValidThread());
966 return ERR_SOCKET_NOT_CONNECTED
;
968 switch (group_address
.size()) {
969 case kIPv4AddressSize
: {
970 if (addr_family_
!= AF_INET
)
971 return ERR_ADDRESS_INVALID
;
973 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
974 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
975 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
976 reinterpret_cast<const char*>(&mreq
),
979 return MapSystemError(WSAGetLastError());
982 case kIPv6AddressSize
: {
983 if (addr_family_
!= AF_INET6
)
984 return ERR_ADDRESS_INVALID
;
986 mreq
.ipv6mr_interface
= multicast_interface_
;
987 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
988 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
989 reinterpret_cast<const char*>(&mreq
),
992 return MapSystemError(WSAGetLastError());
996 NOTREACHED() << "Invalid address family";
997 return ERR_ADDRESS_INVALID
;
1001 int UDPSocketWin::LeaveGroup(
1002 const IPAddressNumber
& group_address
) const {
1003 DCHECK(CalledOnValidThread());
1004 if (!is_connected())
1005 return ERR_SOCKET_NOT_CONNECTED
;
1007 switch (group_address
.size()) {
1008 case kIPv4AddressSize
: {
1009 if (addr_family_
!= AF_INET
)
1010 return ERR_ADDRESS_INVALID
;
1012 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
1013 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
1014 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
1015 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
1017 return MapSystemError(WSAGetLastError());
1020 case kIPv6AddressSize
: {
1021 if (addr_family_
!= AF_INET6
)
1022 return ERR_ADDRESS_INVALID
;
1024 mreq
.ipv6mr_interface
= multicast_interface_
;
1025 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
1026 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
1027 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
1029 return MapSystemError(WSAGetLastError());
1033 NOTREACHED() << "Invalid address family";
1034 return ERR_ADDRESS_INVALID
;
1038 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
1039 DCHECK(CalledOnValidThread());
1041 return ERR_SOCKET_IS_CONNECTED
;
1042 multicast_interface_
= interface_index
;
1046 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
1047 DCHECK(CalledOnValidThread());
1049 return ERR_SOCKET_IS_CONNECTED
;
1051 if (time_to_live
< 0 || time_to_live
> 255)
1052 return ERR_INVALID_ARGUMENT
;
1053 multicast_time_to_live_
= time_to_live
;
1057 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
1058 DCHECK(CalledOnValidThread());
1060 return ERR_SOCKET_IS_CONNECTED
;
1063 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
1065 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
1069 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
1070 if (dscp
== DSCP_NO_CHANGE
) {
1074 if (!is_connected())
1075 return ERR_SOCKET_NOT_CONNECTED
;
1077 QwaveAPI
& qos(QwaveAPI::Get());
1079 if (!qos
.qwave_supported())
1080 return ERROR_NOT_SUPPORTED
;
1082 if (qos_handle_
== NULL
) {
1083 QOS_VERSION version
;
1084 version
.MajorVersion
= 1;
1085 version
.MinorVersion
= 0;
1086 qos
.CreateHandle(&version
, &qos_handle_
);
1087 if (qos_handle_
== NULL
)
1088 return ERROR_NOT_SUPPORTED
;
1091 QOS_TRAFFIC_TYPE traffic_type
= QOSTrafficTypeBestEffort
;
1094 traffic_type
= QOSTrafficTypeBestEffort
;
1097 traffic_type
= QOSTrafficTypeBackground
;
1111 traffic_type
= QOSTrafficTypeExcellentEffort
;
1117 traffic_type
= QOSTrafficTypeAudioVideo
;
1121 traffic_type
= QOSTrafficTypeVoice
;
1124 traffic_type
= QOSTrafficTypeControl
;
1126 case DSCP_NO_CHANGE
:
1130 if (qos_flow_id_
!= 0) {
1131 qos
.RemoveSocketFromFlow(qos_handle_
, NULL
, qos_flow_id_
, 0);
1134 if (!qos
.AddSocketToFlow(qos_handle_
,
1138 QOS_NON_ADAPTIVE_FLOW
,
1140 DWORD err
= GetLastError();
1141 if (err
== ERROR_DEVICE_REINITIALIZATION_NEEDED
) {
1142 qos
.CloseHandle(qos_handle_
);
1146 return MapSystemError(err
);
1148 // This requires admin rights, and may fail, if so we ignore it
1149 // as AddSocketToFlow should still do *approximately* the right thing.
1151 qos
.SetFlow(qos_handle_
,
1153 QOSSetOutgoingDSCPValue
,
1162 void UDPSocketWin::DetachFromThread() {
1163 base::NonThreadSafe::DetachFromThread();
1166 void UDPSocketWin::UseNonBlockingIO() {
1168 use_non_blocking_io_
= true;