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/profiler/scoped_profile.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/winsock_init.h"
24 #include "net/base/winsock_util.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 virtual ~ReadDelegate() {}
73 // base::ObjectWatcher::Delegate methods:
74 virtual void OnObjectSignaled(HANDLE object
);
80 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
82 explicit WriteDelegate(Core
* core
) : core_(core
) {}
83 virtual ~WriteDelegate() {}
85 // base::ObjectWatcher::Delegate methods:
86 virtual void OnObjectSignaled(HANDLE object
);
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 // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed.
148 tracked_objects::ScopedProfile
tracking_profile(
149 FROM_HERE_WITH_EXPLICIT_FUNCTION(
150 "UDPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
152 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
154 core_
->socket_
->DidCompleteRead();
159 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
160 // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed.
161 tracked_objects::ScopedProfile
tracking_profile(
162 FROM_HERE_WITH_EXPLICIT_FUNCTION(
163 "UDPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
165 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
167 core_
->socket_
->DidCompleteWrite();
171 //-----------------------------------------------------------------------------
173 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
174 HMODULE qwave
= LoadLibrary(L
"qwave.dll");
177 create_handle_func_
=
178 (CreateHandleFn
)GetProcAddress(qwave
, "QOSCreateHandle");
180 (CloseHandleFn
)GetProcAddress(qwave
, "QOSCloseHandle");
181 add_socket_to_flow_func_
=
182 (AddSocketToFlowFn
)GetProcAddress(qwave
, "QOSAddSocketToFlow");
183 remove_socket_from_flow_func_
=
184 (RemoveSocketFromFlowFn
)GetProcAddress(qwave
, "QOSRemoveSocketFromFlow");
185 set_flow_func_
= (SetFlowFn
)GetProcAddress(qwave
, "QOSSetFlow");
187 if (create_handle_func_
&& close_handle_func_
&&
188 add_socket_to_flow_func_
&& remove_socket_from_flow_func_
&&
190 qwave_supported_
= true;
194 QwaveAPI
& QwaveAPI::Get() {
195 static base::LazyInstance
<QwaveAPI
>::Leaky lazy_qwave
=
196 LAZY_INSTANCE_INITIALIZER
;
197 return lazy_qwave
.Get();
200 bool QwaveAPI::qwave_supported() const {
201 return qwave_supported_
;
203 BOOL
QwaveAPI::CreateHandle(PQOS_VERSION version
, PHANDLE handle
) {
204 return create_handle_func_(version
, handle
);
206 BOOL
QwaveAPI::CloseHandle(HANDLE handle
) {
207 return close_handle_func_(handle
);
210 BOOL
QwaveAPI::AddSocketToFlow(HANDLE handle
,
213 QOS_TRAFFIC_TYPE traffic_type
,
215 PQOS_FLOWID flow_id
) {
216 return add_socket_to_flow_func_(handle
,
224 BOOL
QwaveAPI::RemoveSocketFromFlow(HANDLE handle
,
228 return remove_socket_from_flow_func_(handle
, socket
, flow_id
, reserved
);
231 BOOL
QwaveAPI::SetFlow(HANDLE handle
,
237 LPOVERLAPPED overlapped
) {
238 return set_flow_func_(handle
,
248 //-----------------------------------------------------------------------------
250 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type
,
251 const RandIntCallback
& rand_int_cb
,
252 net::NetLog
* net_log
,
253 const net::NetLog::Source
& source
)
254 : socket_(INVALID_SOCKET
),
256 socket_options_(SOCKET_OPTION_MULTICAST_LOOP
),
257 multicast_interface_(0),
258 multicast_time_to_live_(1),
259 bind_type_(bind_type
),
260 rand_int_cb_(rand_int_cb
),
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 void UDPSocketWin::Close() {
278 DCHECK(CalledOnValidThread());
284 QwaveAPI::Get().CloseHandle(qos_handle_
);
287 // Zero out any pending read/write callback state.
288 read_callback_
.Reset();
289 recv_from_address_
= NULL
;
290 write_callback_
.Reset();
292 base::TimeTicks start_time
= base::TimeTicks::Now();
293 closesocket(socket_
);
294 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
295 base::TimeTicks::Now() - start_time
);
296 socket_
= INVALID_SOCKET
;
303 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
304 DCHECK(CalledOnValidThread());
307 return ERR_SOCKET_NOT_CONNECTED
;
309 // TODO(szym): Simplify. http://crbug.com/126152
310 if (!remote_address_
.get()) {
311 SockaddrStorage storage
;
312 if (getpeername(socket_
, storage
.addr
, &storage
.addr_len
))
313 return MapSystemError(WSAGetLastError());
314 scoped_ptr
<IPEndPoint
> address(new IPEndPoint());
315 if (!address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
316 return ERR_ADDRESS_INVALID
;
317 remote_address_
.reset(address
.release());
320 *address
= *remote_address_
;
324 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
325 DCHECK(CalledOnValidThread());
328 return ERR_SOCKET_NOT_CONNECTED
;
330 // TODO(szym): Simplify. http://crbug.com/126152
331 if (!local_address_
.get()) {
332 SockaddrStorage storage
;
333 if (getsockname(socket_
, storage
.addr
, &storage
.addr_len
))
334 return MapSystemError(WSAGetLastError());
335 scoped_ptr
<IPEndPoint
> address(new IPEndPoint());
336 if (!address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
337 return ERR_ADDRESS_INVALID
;
338 local_address_
.reset(address
.release());
339 net_log_
.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS
,
340 CreateNetLogUDPConnectCallback(local_address_
.get()));
343 *address
= *local_address_
;
347 int UDPSocketWin::Read(IOBuffer
* buf
,
349 const CompletionCallback
& callback
) {
350 return RecvFrom(buf
, buf_len
, NULL
, callback
);
353 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
356 const CompletionCallback
& callback
) {
357 DCHECK(CalledOnValidThread());
358 DCHECK_NE(INVALID_SOCKET
, socket_
);
359 CHECK(read_callback_
.is_null());
360 DCHECK(!recv_from_address_
);
361 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
362 DCHECK_GT(buf_len
, 0);
364 int nread
= InternalRecvFrom(buf
, buf_len
, address
);
365 if (nread
!= ERR_IO_PENDING
)
368 read_callback_
= callback
;
369 recv_from_address_
= address
;
370 return ERR_IO_PENDING
;
373 int UDPSocketWin::Write(IOBuffer
* buf
,
375 const CompletionCallback
& callback
) {
376 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
379 int UDPSocketWin::SendTo(IOBuffer
* buf
,
381 const IPEndPoint
& address
,
382 const CompletionCallback
& callback
) {
383 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
386 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
388 const IPEndPoint
* address
,
389 const CompletionCallback
& callback
) {
390 DCHECK(CalledOnValidThread());
391 DCHECK_NE(INVALID_SOCKET
, socket_
);
392 CHECK(write_callback_
.is_null());
393 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
394 DCHECK_GT(buf_len
, 0);
395 DCHECK(!send_to_address_
.get());
397 int nwrite
= InternalSendTo(buf
, buf_len
, address
);
398 if (nwrite
!= ERR_IO_PENDING
)
402 send_to_address_
.reset(new IPEndPoint(*address
));
403 write_callback_
= callback
;
404 return ERR_IO_PENDING
;
407 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
408 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
409 CreateNetLogUDPConnectCallback(&address
));
410 int rv
= InternalConnect(address
);
413 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
417 int UDPSocketWin::InternalConnect(const IPEndPoint
& address
) {
418 DCHECK(!is_connected());
419 DCHECK(!remote_address_
.get());
420 int addr_family
= address
.GetSockAddrFamily();
421 int rv
= CreateSocket(addr_family
);
425 if (bind_type_
== DatagramSocket::RANDOM_BIND
) {
426 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
427 // representing INADDR_ANY or in6addr_any.
429 addr_family
== AF_INET
? kIPv4AddressSize
: kIPv6AddressSize
;
430 IPAddressNumber
addr_any(addr_size
);
431 rv
= RandomBind(addr_any
);
433 // else connect() does the DatagramSocket::DEFAULT_BIND
436 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
441 SockaddrStorage storage
;
442 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
443 return ERR_ADDRESS_INVALID
;
445 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
447 // Close() may change the last error. Map it beforehand.
448 int result
= MapSystemError(WSAGetLastError());
453 remote_address_
.reset(new IPEndPoint(address
));
457 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
458 DCHECK(!is_connected());
459 int rv
= CreateSocket(address
.GetSockAddrFamily());
462 rv
= SetSocketOptions();
467 rv
= DoBind(address
);
472 local_address_
.reset();
476 int UDPSocketWin::CreateSocket(int addr_family
) {
477 addr_family_
= addr_family
;
478 socket_
= CreatePlatformSocket(addr_family_
, SOCK_DGRAM
, IPPROTO_UDP
);
479 if (socket_
== INVALID_SOCKET
)
480 return MapSystemError(WSAGetLastError());
481 core_
= new Core(this);
485 int UDPSocketWin::SetReceiveBufferSize(int32 size
) {
486 DCHECK(CalledOnValidThread());
487 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
488 reinterpret_cast<const char*>(&size
), sizeof(size
));
490 return MapSystemError(WSAGetLastError());
492 // According to documentation, setsockopt may succeed, but we need to check
493 // the results via getsockopt to be sure it works on Windows.
494 int32 actual_size
= 0;
495 int option_size
= sizeof(actual_size
);
496 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
497 reinterpret_cast<char*>(&actual_size
), &option_size
);
499 return MapSystemError(WSAGetLastError());
500 if (actual_size
>= size
)
502 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
503 actual_size
, 1000, 1000000, 50);
504 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
507 int UDPSocketWin::SetSendBufferSize(int32 size
) {
508 DCHECK(CalledOnValidThread());
509 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
510 reinterpret_cast<const char*>(&size
), sizeof(size
));
512 return MapSystemError(WSAGetLastError());
513 // According to documentation, setsockopt may succeed, but we need to check
514 // the results via getsockopt to be sure it works on Windows.
515 int32 actual_size
= 0;
516 int option_size
= sizeof(actual_size
);
517 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
518 reinterpret_cast<char*>(&actual_size
), &option_size
);
520 return MapSystemError(WSAGetLastError());
521 if (actual_size
>= size
)
523 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
524 actual_size
, 1000, 1000000, 50);
525 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
528 void UDPSocketWin::AllowAddressReuse() {
529 DCHECK(CalledOnValidThread());
530 DCHECK(!is_connected());
532 socket_options_
|= SOCKET_OPTION_REUSE_ADDRESS
;
535 void UDPSocketWin::AllowBroadcast() {
536 DCHECK(CalledOnValidThread());
537 DCHECK(!is_connected());
539 socket_options_
|= SOCKET_OPTION_BROADCAST
;
542 void UDPSocketWin::DoReadCallback(int rv
) {
543 DCHECK_NE(rv
, ERR_IO_PENDING
);
544 DCHECK(!read_callback_
.is_null());
546 // since Run may result in Read being called, clear read_callback_ up front.
547 CompletionCallback c
= read_callback_
;
548 read_callback_
.Reset();
552 void UDPSocketWin::DoWriteCallback(int rv
) {
553 DCHECK_NE(rv
, ERR_IO_PENDING
);
554 DCHECK(!write_callback_
.is_null());
556 // since Run may result in Write being called, clear write_callback_ up front.
557 CompletionCallback c
= write_callback_
;
558 write_callback_
.Reset();
562 void UDPSocketWin::DidCompleteRead() {
563 DWORD num_bytes
, flags
;
564 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
565 &num_bytes
, FALSE
, &flags
);
566 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
567 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
569 if (recv_from_address_
&& result
>= 0) {
570 if (!ReceiveAddressToIPEndpoint(recv_from_address_
))
571 result
= ERR_ADDRESS_INVALID
;
573 LogRead(result
, core_
->read_iobuffer_
->data());
574 core_
->read_iobuffer_
= NULL
;
575 recv_from_address_
= NULL
;
576 DoReadCallback(result
);
579 void UDPSocketWin::LogRead(int result
, const char* bytes
) const {
581 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
585 if (net_log_
.IsLogging()) {
586 // Get address for logging, if |address| is NULL.
588 bool is_address_valid
= ReceiveAddressToIPEndpoint(&address
);
590 NetLog::TYPE_UDP_BYTES_RECEIVED
,
591 CreateNetLogUDPDataTranferCallback(
593 is_address_valid
? &address
: NULL
));
596 base::StatsCounter
read_bytes("udp.read_bytes");
597 read_bytes
.Add(result
);
600 void UDPSocketWin::DidCompleteWrite() {
601 DWORD num_bytes
, flags
;
602 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
603 &num_bytes
, FALSE
, &flags
);
604 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
605 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
606 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
608 send_to_address_
.reset();
609 core_
->write_iobuffer_
= NULL
;
610 DoWriteCallback(result
);
613 void UDPSocketWin::LogWrite(int result
,
615 const IPEndPoint
* address
) const {
617 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
621 if (net_log_
.IsLogging()) {
623 NetLog::TYPE_UDP_BYTES_SENT
,
624 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
627 base::StatsCounter
write_bytes("udp.write_bytes");
628 write_bytes
.Add(result
);
631 int UDPSocketWin::InternalRecvFrom(IOBuffer
* buf
, int buf_len
,
632 IPEndPoint
* address
) {
633 DCHECK(!core_
->read_iobuffer_
);
634 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
635 storage
.addr_len
= sizeof(storage
.addr_storage
);
638 read_buffer
.buf
= buf
->data();
639 read_buffer
.len
= buf_len
;
643 CHECK_NE(INVALID_SOCKET
, socket_
);
644 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
645 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
646 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
648 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
651 if (address
&& result
>= 0) {
652 if (!ReceiveAddressToIPEndpoint(address
))
653 result
= ERR_ADDRESS_INVALID
;
655 LogRead(result
, buf
->data());
659 int os_error
= WSAGetLastError();
660 if (os_error
!= WSA_IO_PENDING
) {
661 int result
= MapSystemError(os_error
);
662 LogRead(result
, NULL
);
666 core_
->WatchForRead();
667 core_
->read_iobuffer_
= buf
;
668 return ERR_IO_PENDING
;
671 int UDPSocketWin::InternalSendTo(IOBuffer
* buf
, int buf_len
,
672 const IPEndPoint
* address
) {
673 DCHECK(!core_
->write_iobuffer_
);
674 SockaddrStorage storage
;
675 struct sockaddr
* addr
= storage
.addr
;
679 storage
.addr_len
= 0;
681 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
682 int result
= ERR_ADDRESS_INVALID
;
683 LogWrite(result
, NULL
, NULL
);
689 write_buffer
.buf
= buf
->data();
690 write_buffer
.len
= buf_len
;
694 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
695 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
696 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
698 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
700 LogWrite(result
, buf
->data(), address
);
704 int os_error
= WSAGetLastError();
705 if (os_error
!= WSA_IO_PENDING
) {
706 int result
= MapSystemError(os_error
);
707 LogWrite(result
, NULL
, NULL
);
712 core_
->WatchForWrite();
713 core_
->write_iobuffer_
= buf
;
714 return ERR_IO_PENDING
;
717 int UDPSocketWin::SetSocketOptions() {
719 if (socket_options_
& SOCKET_OPTION_REUSE_ADDRESS
) {
720 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
721 reinterpret_cast<const char*>(&true_value
),
724 return MapSystemError(WSAGetLastError());
726 if (socket_options_
& SOCKET_OPTION_BROADCAST
) {
727 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
728 reinterpret_cast<const char*>(&true_value
),
731 return MapSystemError(WSAGetLastError());
733 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
736 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
738 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
739 int rv
= setsockopt(socket_
, protocol_level
, option
,
740 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
742 return MapSystemError(WSAGetLastError());
744 if (multicast_time_to_live_
!= 1) {
745 DWORD hops
= multicast_time_to_live_
;
747 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
749 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
750 int rv
= setsockopt(socket_
, protocol_level
, option
,
751 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
753 return MapSystemError(WSAGetLastError());
755 if (multicast_interface_
!= 0) {
756 switch (addr_family_
) {
759 address
.s_addr
= htonl(multicast_interface_
);
760 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
761 reinterpret_cast<const char*>(&address
),
764 return MapSystemError(WSAGetLastError());
768 uint32 interface_index
= multicast_interface_
;
769 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
770 reinterpret_cast<const char*>(&interface_index
),
771 sizeof(interface_index
));
773 return MapSystemError(WSAGetLastError());
777 NOTREACHED() << "Invalid address family";
778 return ERR_ADDRESS_INVALID
;
784 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
785 SockaddrStorage storage
;
786 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
787 return ERR_ADDRESS_INVALID
;
788 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
791 int last_error
= WSAGetLastError();
792 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
793 // Map some codes that are special to bind() separately.
794 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
795 // returned instead of WSAEADDRINUSE, depending on whether the socket
796 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
797 // conflicting socket is owned by a different user account. See the MSDN
798 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
799 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
800 return ERR_ADDRESS_IN_USE
;
801 return MapSystemError(last_error
);
804 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
805 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
807 for (int i
= 0; i
< kBindRetries
; ++i
) {
808 int rv
= DoBind(IPEndPoint(address
,
809 rand_int_cb_
.Run(kPortStart
, kPortEnd
)));
810 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
813 return DoBind(IPEndPoint(address
, 0));
816 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint
* address
) const {
817 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
818 return address
->FromSockAddr(storage
.addr
, storage
.addr_len
);
821 int UDPSocketWin::JoinGroup(
822 const IPAddressNumber
& group_address
) const {
823 DCHECK(CalledOnValidThread());
825 return ERR_SOCKET_NOT_CONNECTED
;
827 switch (group_address
.size()) {
828 case kIPv4AddressSize
: {
829 if (addr_family_
!= AF_INET
)
830 return ERR_ADDRESS_INVALID
;
832 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
833 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
834 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
835 reinterpret_cast<const char*>(&mreq
),
838 return MapSystemError(WSAGetLastError());
841 case kIPv6AddressSize
: {
842 if (addr_family_
!= AF_INET6
)
843 return ERR_ADDRESS_INVALID
;
845 mreq
.ipv6mr_interface
= multicast_interface_
;
846 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
847 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
848 reinterpret_cast<const char*>(&mreq
),
851 return MapSystemError(WSAGetLastError());
855 NOTREACHED() << "Invalid address family";
856 return ERR_ADDRESS_INVALID
;
860 int UDPSocketWin::LeaveGroup(
861 const IPAddressNumber
& group_address
) const {
862 DCHECK(CalledOnValidThread());
864 return ERR_SOCKET_NOT_CONNECTED
;
866 switch (group_address
.size()) {
867 case kIPv4AddressSize
: {
868 if (addr_family_
!= AF_INET
)
869 return ERR_ADDRESS_INVALID
;
871 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
872 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
873 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
874 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
876 return MapSystemError(WSAGetLastError());
879 case kIPv6AddressSize
: {
880 if (addr_family_
!= AF_INET6
)
881 return ERR_ADDRESS_INVALID
;
883 mreq
.ipv6mr_interface
= multicast_interface_
;
884 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
885 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
886 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
888 return MapSystemError(WSAGetLastError());
892 NOTREACHED() << "Invalid address family";
893 return ERR_ADDRESS_INVALID
;
897 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
898 DCHECK(CalledOnValidThread());
900 return ERR_SOCKET_IS_CONNECTED
;
901 multicast_interface_
= interface_index
;
905 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
906 DCHECK(CalledOnValidThread());
908 return ERR_SOCKET_IS_CONNECTED
;
910 if (time_to_live
< 0 || time_to_live
> 255)
911 return ERR_INVALID_ARGUMENT
;
912 multicast_time_to_live_
= time_to_live
;
916 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
917 DCHECK(CalledOnValidThread());
919 return ERR_SOCKET_IS_CONNECTED
;
922 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
924 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
928 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
929 if (dscp
== DSCP_NO_CHANGE
) {
934 return ERR_SOCKET_NOT_CONNECTED
;
936 QwaveAPI
& qos(QwaveAPI::Get());
938 if (!qos
.qwave_supported())
939 return ERROR_NOT_SUPPORTED
;
941 if (qos_handle_
== NULL
) {
943 version
.MajorVersion
= 1;
944 version
.MinorVersion
= 0;
945 qos
.CreateHandle(&version
, &qos_handle_
);
946 if (qos_handle_
== NULL
)
947 return ERROR_NOT_SUPPORTED
;
950 QOS_TRAFFIC_TYPE traffic_type
= QOSTrafficTypeBestEffort
;
953 traffic_type
= QOSTrafficTypeBestEffort
;
956 traffic_type
= QOSTrafficTypeBackground
;
970 traffic_type
= QOSTrafficTypeExcellentEffort
;
976 traffic_type
= QOSTrafficTypeAudioVideo
;
980 traffic_type
= QOSTrafficTypeVoice
;
983 traffic_type
= QOSTrafficTypeControl
;
989 if (qos_flow_id_
!= 0) {
990 qos
.RemoveSocketFromFlow(qos_handle_
, NULL
, qos_flow_id_
, 0);
993 if (!qos
.AddSocketToFlow(qos_handle_
,
997 QOS_NON_ADAPTIVE_FLOW
,
999 DWORD err
= GetLastError();
1000 if (err
== ERROR_DEVICE_REINITIALIZATION_NEEDED
) {
1001 qos
.CloseHandle(qos_handle_
);
1005 return MapSystemError(err
);
1007 // This requires admin rights, and may fail, if so we ignore it
1008 // as AddSocketToFlow should still do *approximately* the right thing.
1010 qos
.SetFlow(qos_handle_
,
1012 QOSSetOutgoingDSCPValue
,
1021 void UDPSocketWin::DetachFromThread() {
1022 base::NonThreadSafe::DetachFromThread();