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/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"
29 const int kBindRetries
= 10;
30 const int kPortStart
= 1024;
31 const int kPortEnd
= 65535;
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
> {
44 explicit Core(UDPSocketWin
* socket
);
46 // Start watching for the end of a read or write operation.
50 // The UDPSocketWin is going away.
51 void Detach() { socket_
= NULL
; }
53 // The separate OVERLAPPED variables for asynchronous operation.
54 OVERLAPPED read_overlapped_
;
55 OVERLAPPED write_overlapped_
;
57 // The buffers used in Read() and Write().
58 scoped_refptr
<IOBuffer
> read_iobuffer_
;
59 scoped_refptr
<IOBuffer
> write_iobuffer_
;
61 // The address storage passed to WSARecvFrom().
62 SockaddrStorage recv_addr_storage_
;
65 friend class base::RefCounted
<Core
>;
67 class ReadDelegate
: public base::win::ObjectWatcher::Delegate
{
69 explicit ReadDelegate(Core
* core
) : core_(core
) {}
70 virtual ~ReadDelegate() {}
72 // base::ObjectWatcher::Delegate methods:
73 virtual void OnObjectSignaled(HANDLE object
);
79 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
81 explicit WriteDelegate(Core
* core
) : core_(core
) {}
82 virtual ~WriteDelegate() {}
84 // base::ObjectWatcher::Delegate methods:
85 virtual void OnObjectSignaled(HANDLE object
);
93 // The socket that created this object.
94 UDPSocketWin
* socket_
;
96 // |reader_| handles the signals from |read_watcher_|.
98 // |writer_| handles the signals from |write_watcher_|.
99 WriteDelegate writer_
;
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_
;
106 DISALLOW_COPY_AND_ASSIGN(Core
);
109 UDPSocketWin::Core::Core(UDPSocketWin
* socket
)
113 memset(&read_overlapped_
, 0, sizeof(read_overlapped_
));
114 memset(&write_overlapped_
, 0, sizeof(write_overlapped_
));
116 read_overlapped_
.hEvent
= WSACreateEvent();
117 write_overlapped_
.hEvent
= WSACreateEvent();
120 UDPSocketWin::Core::~Core() {
121 // Make sure the message loop is not watching this object anymore.
122 read_watcher_
.StopWatching();
123 write_watcher_
.StopWatching();
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_
));
131 void UDPSocketWin::Core::WatchForRead() {
132 // We grab an extra reference because there is an IO operation in progress.
133 // Balanced in ReadDelegate::OnObjectSignaled().
135 read_watcher_
.StartWatching(read_overlapped_
.hEvent
, &reader_
);
138 void UDPSocketWin::Core::WatchForWrite() {
139 // We grab an extra reference because there is an IO operation in progress.
140 // Balanced in WriteDelegate::OnObjectSignaled().
142 write_watcher_
.StartWatching(write_overlapped_
.hEvent
, &writer_
);
145 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object
) {
146 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
148 core_
->socket_
->DidCompleteRead();
153 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
154 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
156 core_
->socket_
->DidCompleteWrite();
160 //-----------------------------------------------------------------------------
162 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
163 HMODULE qwave
= LoadLibrary(L
"qwave.dll");
166 create_handle_func_
=
167 (CreateHandleFn
)GetProcAddress(qwave
, "QOSCreateHandle");
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");
176 if (create_handle_func_
&& close_handle_func_
&&
177 add_socket_to_flow_func_
&& remove_socket_from_flow_func_
&&
179 qwave_supported_
= true;
183 QwaveAPI
& QwaveAPI::Get() {
184 static base::LazyInstance
<QwaveAPI
>::Leaky lazy_qwave
=
185 LAZY_INSTANCE_INITIALIZER
;
186 return lazy_qwave
.Get();
189 bool QwaveAPI::qwave_supported() const {
190 return qwave_supported_
;
192 BOOL
QwaveAPI::CreateHandle(PQOS_VERSION version
, PHANDLE handle
) {
193 return create_handle_func_(version
, handle
);
195 BOOL
QwaveAPI::CloseHandle(HANDLE handle
) {
196 return close_handle_func_(handle
);
199 BOOL
QwaveAPI::AddSocketToFlow(HANDLE handle
,
202 QOS_TRAFFIC_TYPE traffic_type
,
204 PQOS_FLOWID flow_id
) {
205 return add_socket_to_flow_func_(handle
,
213 BOOL
QwaveAPI::RemoveSocketFromFlow(HANDLE handle
,
217 return remove_socket_from_flow_func_(handle
, socket
, flow_id
, reserved
);
220 BOOL
QwaveAPI::SetFlow(HANDLE handle
,
226 LPOVERLAPPED overlapped
) {
227 return set_flow_func_(handle
,
237 //-----------------------------------------------------------------------------
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
),
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
)),
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());
261 UDPSocketWin::~UDPSocketWin() {
263 net_log_
.EndEvent(NetLog::TYPE_SOCKET_ALIVE
);
266 void UDPSocketWin::Close() {
267 DCHECK(CalledOnValidThread());
273 QwaveAPI::Get().CloseHandle(qos_handle_
);
276 // Zero out any pending read/write callback state.
277 read_callback_
.Reset();
278 recv_from_address_
= NULL
;
279 write_callback_
.Reset();
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
;
292 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
293 DCHECK(CalledOnValidThread());
296 return ERR_SOCKET_NOT_CONNECTED
;
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());
309 *address
= *remote_address_
;
313 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
314 DCHECK(CalledOnValidThread());
317 return ERR_SOCKET_NOT_CONNECTED
;
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()));
332 *address
= *local_address_
;
336 int UDPSocketWin::Read(IOBuffer
* buf
,
338 const CompletionCallback
& callback
) {
339 return RecvFrom(buf
, buf_len
, NULL
, callback
);
342 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
345 const CompletionCallback
& callback
) {
346 DCHECK(CalledOnValidThread());
347 DCHECK_NE(INVALID_SOCKET
, socket_
);
348 DCHECK(read_callback_
.is_null());
349 DCHECK(!recv_from_address_
);
350 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
351 DCHECK_GT(buf_len
, 0);
353 int nread
= InternalRecvFrom(buf
, buf_len
, address
);
354 if (nread
!= ERR_IO_PENDING
)
357 read_callback_
= callback
;
358 recv_from_address_
= address
;
359 return ERR_IO_PENDING
;
362 int UDPSocketWin::Write(IOBuffer
* buf
,
364 const CompletionCallback
& callback
) {
365 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
368 int UDPSocketWin::SendTo(IOBuffer
* buf
,
370 const IPEndPoint
& address
,
371 const CompletionCallback
& callback
) {
372 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
375 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
377 const IPEndPoint
* address
,
378 const CompletionCallback
& callback
) {
379 DCHECK(CalledOnValidThread());
380 DCHECK_NE(INVALID_SOCKET
, socket_
);
381 DCHECK(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());
386 int nwrite
= InternalSendTo(buf
, buf_len
, address
);
387 if (nwrite
!= ERR_IO_PENDING
)
391 send_to_address_
.reset(new IPEndPoint(*address
));
392 write_callback_
= callback
;
393 return ERR_IO_PENDING
;
396 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
397 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
398 CreateNetLogUDPConnectCallback(&address
));
399 int rv
= InternalConnect(address
);
402 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
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
);
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.
418 addr_family
== AF_INET
? kIPv4AddressSize
: kIPv6AddressSize
;
419 IPAddressNumber
addr_any(addr_size
);
420 rv
= RandomBind(addr_any
);
422 // else connect() does the DatagramSocket::DEFAULT_BIND
425 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
430 SockaddrStorage storage
;
431 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
432 return ERR_ADDRESS_INVALID
;
434 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
436 // Close() may change the last error. Map it beforehand.
437 int result
= MapSystemError(WSAGetLastError());
442 remote_address_
.reset(new IPEndPoint(address
));
446 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
447 DCHECK(!is_connected());
448 int rv
= CreateSocket(address
.GetSockAddrFamily());
451 rv
= SetSocketOptions();
456 rv
= DoBind(address
);
461 local_address_
.reset();
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);
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
));
479 return MapSystemError(WSAGetLastError());
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
);
488 return MapSystemError(WSAGetLastError());
489 if (actual_size
>= size
)
491 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
492 actual_size
, 1000, 1000000, 50);
493 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
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
));
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
);
509 return MapSystemError(WSAGetLastError());
510 if (actual_size
>= size
)
512 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
513 actual_size
, 1000, 1000000, 50);
514 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
517 void UDPSocketWin::AllowAddressReuse() {
518 DCHECK(CalledOnValidThread());
519 DCHECK(!is_connected());
521 socket_options_
|= SOCKET_OPTION_REUSE_ADDRESS
;
524 void UDPSocketWin::AllowBroadcast() {
525 DCHECK(CalledOnValidThread());
526 DCHECK(!is_connected());
528 socket_options_
|= SOCKET_OPTION_BROADCAST
;
531 void UDPSocketWin::DoReadCallback(int rv
) {
532 DCHECK_NE(rv
, ERR_IO_PENDING
);
533 DCHECK(!read_callback_
.is_null());
535 // since Run may result in Read being called, clear read_callback_ up front.
536 CompletionCallback c
= read_callback_
;
537 read_callback_
.Reset();
541 void UDPSocketWin::DoWriteCallback(int rv
) {
542 DCHECK_NE(rv
, ERR_IO_PENDING
);
543 DCHECK(!write_callback_
.is_null());
545 // since Run may result in Write being called, clear write_callback_ up front.
546 CompletionCallback c
= write_callback_
;
547 write_callback_
.Reset();
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());
558 if (recv_from_address_
&& result
>= 0) {
559 if (!ReceiveAddressToIPEndpoint(recv_from_address_
))
560 result
= ERR_ADDRESS_INVALID
;
562 LogRead(result
, core_
->read_iobuffer_
->data());
563 core_
->read_iobuffer_
= NULL
;
564 recv_from_address_
= NULL
;
565 DoReadCallback(result
);
568 void UDPSocketWin::LogRead(int result
, const char* bytes
) const {
570 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
574 if (net_log_
.IsLogging()) {
575 // Get address for logging, if |address| is NULL.
577 bool is_address_valid
= ReceiveAddressToIPEndpoint(&address
);
579 NetLog::TYPE_UDP_BYTES_RECEIVED
,
580 CreateNetLogUDPDataTranferCallback(
582 is_address_valid
? &address
: NULL
));
585 base::StatsCounter
read_bytes("udp.read_bytes");
586 read_bytes
.Add(result
);
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());
597 send_to_address_
.reset();
598 core_
->write_iobuffer_
= NULL
;
599 DoWriteCallback(result
);
602 void UDPSocketWin::LogWrite(int result
,
604 const IPEndPoint
* address
) const {
606 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
610 if (net_log_
.IsLogging()) {
612 NetLog::TYPE_UDP_BYTES_SENT
,
613 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
616 base::StatsCounter
write_bytes("udp.write_bytes");
617 write_bytes
.Add(result
);
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
);
627 read_buffer
.buf
= buf
->data();
628 read_buffer
.len
= buf_len
;
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
);
637 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
640 if (address
&& result
>= 0) {
641 if (!ReceiveAddressToIPEndpoint(address
))
642 result
= ERR_ADDRESS_INVALID
;
644 LogRead(result
, buf
->data());
648 int os_error
= WSAGetLastError();
649 if (os_error
!= WSA_IO_PENDING
) {
650 int result
= MapSystemError(os_error
);
651 LogRead(result
, NULL
);
655 core_
->WatchForRead();
656 core_
->read_iobuffer_
= buf
;
657 return ERR_IO_PENDING
;
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
;
668 storage
.addr_len
= 0;
670 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
671 int result
= ERR_ADDRESS_INVALID
;
672 LogWrite(result
, NULL
, NULL
);
678 write_buffer
.buf
= buf
->data();
679 write_buffer
.len
= buf_len
;
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
);
687 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
689 LogWrite(result
, buf
->data(), address
);
693 int os_error
= WSAGetLastError();
694 if (os_error
!= WSA_IO_PENDING
) {
695 int result
= MapSystemError(os_error
);
696 LogWrite(result
, NULL
, NULL
);
701 core_
->WatchForWrite();
702 core_
->write_iobuffer_
= buf
;
703 return ERR_IO_PENDING
;
706 int UDPSocketWin::SetSocketOptions() {
708 if (socket_options_
& SOCKET_OPTION_REUSE_ADDRESS
) {
709 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
710 reinterpret_cast<const char*>(&true_value
),
713 return MapSystemError(WSAGetLastError());
715 if (socket_options_
& SOCKET_OPTION_BROADCAST
) {
716 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
717 reinterpret_cast<const char*>(&true_value
),
720 return MapSystemError(WSAGetLastError());
722 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
725 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
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
));
731 return MapSystemError(WSAGetLastError());
733 if (multicast_time_to_live_
!= 1) {
734 DWORD hops
= multicast_time_to_live_
;
736 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
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
));
742 return MapSystemError(WSAGetLastError());
744 if (multicast_interface_
!= 0) {
745 switch (addr_family_
) {
748 address
.s_addr
= htonl(multicast_interface_
);
749 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
750 reinterpret_cast<const char*>(&address
),
753 return MapSystemError(WSAGetLastError());
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
));
762 return MapSystemError(WSAGetLastError());
766 NOTREACHED() << "Invalid address family";
767 return ERR_ADDRESS_INVALID
;
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
);
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
);
793 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
794 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
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
)
802 return DoBind(IPEndPoint(address
, 0));
805 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint
* address
) const {
806 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
807 return address
->FromSockAddr(storage
.addr
, storage
.addr_len
);
810 int UDPSocketWin::JoinGroup(
811 const IPAddressNumber
& group_address
) const {
812 DCHECK(CalledOnValidThread());
814 return ERR_SOCKET_NOT_CONNECTED
;
816 switch (group_address
.size()) {
817 case kIPv4AddressSize
: {
818 if (addr_family_
!= AF_INET
)
819 return ERR_ADDRESS_INVALID
;
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
),
827 return MapSystemError(WSAGetLastError());
830 case kIPv6AddressSize
: {
831 if (addr_family_
!= AF_INET6
)
832 return ERR_ADDRESS_INVALID
;
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
),
840 return MapSystemError(WSAGetLastError());
844 NOTREACHED() << "Invalid address family";
845 return ERR_ADDRESS_INVALID
;
849 int UDPSocketWin::LeaveGroup(
850 const IPAddressNumber
& group_address
) const {
851 DCHECK(CalledOnValidThread());
853 return ERR_SOCKET_NOT_CONNECTED
;
855 switch (group_address
.size()) {
856 case kIPv4AddressSize
: {
857 if (addr_family_
!= AF_INET
)
858 return ERR_ADDRESS_INVALID
;
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
));
865 return MapSystemError(WSAGetLastError());
868 case kIPv6AddressSize
: {
869 if (addr_family_
!= AF_INET6
)
870 return ERR_ADDRESS_INVALID
;
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
));
877 return MapSystemError(WSAGetLastError());
881 NOTREACHED() << "Invalid address family";
882 return ERR_ADDRESS_INVALID
;
886 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
887 DCHECK(CalledOnValidThread());
889 return ERR_SOCKET_IS_CONNECTED
;
890 multicast_interface_
= interface_index
;
894 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
895 DCHECK(CalledOnValidThread());
897 return ERR_SOCKET_IS_CONNECTED
;
899 if (time_to_live
< 0 || time_to_live
> 255)
900 return ERR_INVALID_ARGUMENT
;
901 multicast_time_to_live_
= time_to_live
;
905 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
906 DCHECK(CalledOnValidThread());
908 return ERR_SOCKET_IS_CONNECTED
;
911 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
913 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
917 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
918 if (dscp
== DSCP_NO_CHANGE
) {
923 return ERR_SOCKET_NOT_CONNECTED
;
925 QwaveAPI
& qos(QwaveAPI::Get());
927 if (!qos
.qwave_supported())
928 return ERROR_NOT_SUPPORTED
;
930 if (qos_handle_
== NULL
) {
932 version
.MajorVersion
= 1;
933 version
.MinorVersion
= 0;
934 qos
.CreateHandle(&version
, &qos_handle_
);
935 if (qos_handle_
== NULL
)
936 return ERROR_NOT_SUPPORTED
;
939 QOS_TRAFFIC_TYPE traffic_type
= QOSTrafficTypeBestEffort
;
942 traffic_type
= QOSTrafficTypeBestEffort
;
945 traffic_type
= QOSTrafficTypeBackground
;
959 traffic_type
= QOSTrafficTypeExcellentEffort
;
965 traffic_type
= QOSTrafficTypeAudioVideo
;
969 traffic_type
= QOSTrafficTypeVoice
;
972 traffic_type
= QOSTrafficTypeControl
;
978 if (qos_flow_id_
!= 0) {
979 qos
.RemoveSocketFromFlow(qos_handle_
, NULL
, qos_flow_id_
, 0);
982 if (!qos
.AddSocketToFlow(qos_handle_
,
986 QOS_NON_ADAPTIVE_FLOW
,
988 DWORD err
= GetLastError();
989 if (err
== ERROR_DEVICE_REINITIALIZATION_NEEDED
) {
990 qos
.CloseHandle(qos_handle_
);
994 return MapSystemError(err
);
996 // This requires admin rights, and may fail, if so we ignore it
997 // as AddSocketToFlow should still do *approximately* the right thing.
999 qos
.SetFlow(qos_handle_
,
1001 QOSSetOutgoingDSCPValue
,
1010 void UDPSocketWin::DetachFromThread() {
1011 base::NonThreadSafe::DetachFromThread();