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/metrics/stats_counters.h"
17 #include "base/profiler/scoped_tracker.h"
18 #include "base/rand_util.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/ip_endpoint.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/net_log.h"
23 #include "net/base/net_util.h"
24 #include "net/base/network_activity_monitor.h"
25 #include "net/base/winsock_init.h"
26 #include "net/base/winsock_util.h"
27 #include "net/socket/socket_descriptor.h"
28 #include "net/udp/udp_net_log_parameters.h"
32 const int kBindRetries
= 10;
33 const int kPortStart
= 1024;
34 const int kPortEnd
= 65535;
40 // This class encapsulates all the state that has to be preserved as long as
41 // there is a network IO operation in progress. If the owner UDPSocketWin
42 // is destroyed while an operation is in progress, the Core is detached and it
43 // lives until the operation completes and the OS doesn't reference any resource
44 // declared on this class anymore.
45 class UDPSocketWin::Core
: public base::RefCounted
<Core
> {
47 explicit Core(UDPSocketWin
* socket
);
49 // Start watching for the end of a read or write operation.
53 // The UDPSocketWin is going away.
54 void Detach() { socket_
= NULL
; }
56 // The separate OVERLAPPED variables for asynchronous operation.
57 OVERLAPPED read_overlapped_
;
58 OVERLAPPED write_overlapped_
;
60 // The buffers used in Read() and Write().
61 scoped_refptr
<IOBuffer
> read_iobuffer_
;
62 scoped_refptr
<IOBuffer
> write_iobuffer_
;
64 // The address storage passed to WSARecvFrom().
65 SockaddrStorage recv_addr_storage_
;
68 friend class base::RefCounted
<Core
>;
70 class ReadDelegate
: public base::win::ObjectWatcher::Delegate
{
72 explicit ReadDelegate(Core
* core
) : core_(core
) {}
73 virtual ~ReadDelegate() {}
75 // base::ObjectWatcher::Delegate methods:
76 virtual void OnObjectSignaled(HANDLE object
);
82 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
84 explicit WriteDelegate(Core
* core
) : core_(core
) {}
85 virtual ~WriteDelegate() {}
87 // base::ObjectWatcher::Delegate methods:
88 virtual void OnObjectSignaled(HANDLE object
);
96 // The socket that created this object.
97 UDPSocketWin
* socket_
;
99 // |reader_| handles the signals from |read_watcher_|.
100 ReadDelegate reader_
;
101 // |writer_| handles the signals from |write_watcher_|.
102 WriteDelegate writer_
;
104 // |read_watcher_| watches for events from Read().
105 base::win::ObjectWatcher read_watcher_
;
106 // |write_watcher_| watches for events from Write();
107 base::win::ObjectWatcher write_watcher_
;
109 DISALLOW_COPY_AND_ASSIGN(Core
);
112 UDPSocketWin::Core::Core(UDPSocketWin
* socket
)
116 memset(&read_overlapped_
, 0, sizeof(read_overlapped_
));
117 memset(&write_overlapped_
, 0, sizeof(write_overlapped_
));
119 read_overlapped_
.hEvent
= WSACreateEvent();
120 write_overlapped_
.hEvent
= WSACreateEvent();
123 UDPSocketWin::Core::~Core() {
124 // Make sure the message loop is not watching this object anymore.
125 read_watcher_
.StopWatching();
126 write_watcher_
.StopWatching();
128 WSACloseEvent(read_overlapped_
.hEvent
);
129 memset(&read_overlapped_
, 0xaf, sizeof(read_overlapped_
));
130 WSACloseEvent(write_overlapped_
.hEvent
);
131 memset(&write_overlapped_
, 0xaf, sizeof(write_overlapped_
));
134 void UDPSocketWin::Core::WatchForRead() {
135 // We grab an extra reference because there is an IO operation in progress.
136 // Balanced in ReadDelegate::OnObjectSignaled().
138 read_watcher_
.StartWatching(read_overlapped_
.hEvent
, &reader_
);
141 void UDPSocketWin::Core::WatchForWrite() {
142 // We grab an extra reference because there is an IO operation in progress.
143 // Balanced in WriteDelegate::OnObjectSignaled().
145 write_watcher_
.StartWatching(write_overlapped_
.hEvent
, &writer_
);
148 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object
) {
149 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
150 tracked_objects::ScopedTracker
tracking_profile(
151 FROM_HERE_WITH_EXPLICIT_FUNCTION(
152 "UDPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
154 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
156 core_
->socket_
->DidCompleteRead();
161 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
162 // TODO(vadimt): Remove ScopedTracker below once crbug.com/418183 is fixed.
163 tracked_objects::ScopedTracker
tracking_profile(
164 FROM_HERE_WITH_EXPLICIT_FUNCTION(
165 "UDPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
167 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
169 core_
->socket_
->DidCompleteWrite();
173 //-----------------------------------------------------------------------------
175 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
176 HMODULE qwave
= LoadLibrary(L
"qwave.dll");
179 create_handle_func_
=
180 (CreateHandleFn
)GetProcAddress(qwave
, "QOSCreateHandle");
182 (CloseHandleFn
)GetProcAddress(qwave
, "QOSCloseHandle");
183 add_socket_to_flow_func_
=
184 (AddSocketToFlowFn
)GetProcAddress(qwave
, "QOSAddSocketToFlow");
185 remove_socket_from_flow_func_
=
186 (RemoveSocketFromFlowFn
)GetProcAddress(qwave
, "QOSRemoveSocketFromFlow");
187 set_flow_func_
= (SetFlowFn
)GetProcAddress(qwave
, "QOSSetFlow");
189 if (create_handle_func_
&& close_handle_func_
&&
190 add_socket_to_flow_func_
&& remove_socket_from_flow_func_
&&
192 qwave_supported_
= true;
196 QwaveAPI
& QwaveAPI::Get() {
197 static base::LazyInstance
<QwaveAPI
>::Leaky lazy_qwave
=
198 LAZY_INSTANCE_INITIALIZER
;
199 return lazy_qwave
.Get();
202 bool QwaveAPI::qwave_supported() const {
203 return qwave_supported_
;
205 BOOL
QwaveAPI::CreateHandle(PQOS_VERSION version
, PHANDLE handle
) {
206 return create_handle_func_(version
, handle
);
208 BOOL
QwaveAPI::CloseHandle(HANDLE handle
) {
209 return close_handle_func_(handle
);
212 BOOL
QwaveAPI::AddSocketToFlow(HANDLE handle
,
215 QOS_TRAFFIC_TYPE traffic_type
,
217 PQOS_FLOWID flow_id
) {
218 return add_socket_to_flow_func_(handle
,
226 BOOL
QwaveAPI::RemoveSocketFromFlow(HANDLE handle
,
230 return remove_socket_from_flow_func_(handle
, socket
, flow_id
, reserved
);
233 BOOL
QwaveAPI::SetFlow(HANDLE handle
,
239 LPOVERLAPPED overlapped
) {
240 return set_flow_func_(handle
,
250 //-----------------------------------------------------------------------------
252 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type
,
253 const RandIntCallback
& rand_int_cb
,
254 net::NetLog
* net_log
,
255 const net::NetLog::Source
& source
)
256 : socket_(INVALID_SOCKET
),
258 is_connected_(false),
259 socket_options_(SOCKET_OPTION_MULTICAST_LOOP
),
260 multicast_interface_(0),
261 multicast_time_to_live_(1),
262 bind_type_(bind_type
),
263 rand_int_cb_(rand_int_cb
),
264 recv_from_address_(NULL
),
265 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_UDP_SOCKET
)),
269 net_log_
.BeginEvent(NetLog::TYPE_SOCKET_ALIVE
,
270 source
.ToEventParametersCallback());
271 if (bind_type
== DatagramSocket::RANDOM_BIND
)
272 DCHECK(!rand_int_cb
.is_null());
275 UDPSocketWin::~UDPSocketWin() {
277 net_log_
.EndEvent(NetLog::TYPE_SOCKET_ALIVE
);
280 int UDPSocketWin::Open(AddressFamily address_family
) {
281 DCHECK(CalledOnValidThread());
282 DCHECK_EQ(socket_
, INVALID_SOCKET
);
284 addr_family_
= ConvertAddressFamily(address_family
);
285 socket_
= CreatePlatformSocket(addr_family_
, SOCK_DGRAM
, IPPROTO_UDP
);
286 if (socket_
== INVALID_SOCKET
)
287 return MapSystemError(WSAGetLastError());
288 core_
= new Core(this);
292 void UDPSocketWin::Close() {
293 DCHECK(CalledOnValidThread());
295 if (socket_
== INVALID_SOCKET
)
299 QwaveAPI::Get().CloseHandle(qos_handle_
);
302 // Zero out any pending read/write callback state.
303 read_callback_
.Reset();
304 recv_from_address_
= NULL
;
305 write_callback_
.Reset();
307 base::TimeTicks start_time
= base::TimeTicks::Now();
308 closesocket(socket_
);
309 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
310 base::TimeTicks::Now() - start_time
);
311 socket_
= INVALID_SOCKET
;
313 is_connected_
= false;
319 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
320 DCHECK(CalledOnValidThread());
323 return ERR_SOCKET_NOT_CONNECTED
;
325 // TODO(szym): Simplify. http://crbug.com/126152
326 if (!remote_address_
.get()) {
327 SockaddrStorage storage
;
328 if (getpeername(socket_
, storage
.addr
, &storage
.addr_len
))
329 return MapSystemError(WSAGetLastError());
330 scoped_ptr
<IPEndPoint
> address(new IPEndPoint());
331 if (!address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
332 return ERR_ADDRESS_INVALID
;
333 remote_address_
.reset(address
.release());
336 *address
= *remote_address_
;
340 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
341 DCHECK(CalledOnValidThread());
344 return ERR_SOCKET_NOT_CONNECTED
;
346 // TODO(szym): Simplify. http://crbug.com/126152
347 if (!local_address_
.get()) {
348 SockaddrStorage storage
;
349 if (getsockname(socket_
, storage
.addr
, &storage
.addr_len
))
350 return MapSystemError(WSAGetLastError());
351 scoped_ptr
<IPEndPoint
> address(new IPEndPoint());
352 if (!address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
353 return ERR_ADDRESS_INVALID
;
354 local_address_
.reset(address
.release());
355 net_log_
.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS
,
356 CreateNetLogUDPConnectCallback(local_address_
.get()));
359 *address
= *local_address_
;
363 int UDPSocketWin::Read(IOBuffer
* buf
,
365 const CompletionCallback
& callback
) {
366 return RecvFrom(buf
, buf_len
, NULL
, callback
);
369 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
372 const CompletionCallback
& callback
) {
373 DCHECK(CalledOnValidThread());
374 DCHECK_NE(INVALID_SOCKET
, socket_
);
375 CHECK(read_callback_
.is_null());
376 DCHECK(!recv_from_address_
);
377 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
378 DCHECK_GT(buf_len
, 0);
380 int nread
= InternalRecvFrom(buf
, buf_len
, address
);
381 if (nread
!= ERR_IO_PENDING
)
384 read_callback_
= callback
;
385 recv_from_address_
= address
;
386 return ERR_IO_PENDING
;
389 int UDPSocketWin::Write(IOBuffer
* buf
,
391 const CompletionCallback
& callback
) {
392 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
395 int UDPSocketWin::SendTo(IOBuffer
* buf
,
397 const IPEndPoint
& address
,
398 const CompletionCallback
& callback
) {
399 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
402 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
404 const IPEndPoint
* address
,
405 const CompletionCallback
& callback
) {
406 DCHECK(CalledOnValidThread());
407 DCHECK_NE(INVALID_SOCKET
, socket_
);
408 CHECK(write_callback_
.is_null());
409 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
410 DCHECK_GT(buf_len
, 0);
411 DCHECK(!send_to_address_
.get());
413 int nwrite
= InternalSendTo(buf
, buf_len
, address
);
414 if (nwrite
!= ERR_IO_PENDING
)
418 send_to_address_
.reset(new IPEndPoint(*address
));
419 write_callback_
= callback
;
420 return ERR_IO_PENDING
;
423 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
424 DCHECK_NE(socket_
, INVALID_SOCKET
);
425 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
426 CreateNetLogUDPConnectCallback(&address
));
427 int rv
= InternalConnect(address
);
428 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
429 is_connected_
= (rv
== OK
);
433 int UDPSocketWin::InternalConnect(const IPEndPoint
& address
) {
434 DCHECK(!is_connected());
435 DCHECK(!remote_address_
.get());
438 if (bind_type_
== DatagramSocket::RANDOM_BIND
) {
439 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
440 // representing INADDR_ANY or in6addr_any.
441 size_t addr_size
= (address
.GetSockAddrFamily() == AF_INET
) ?
442 kIPv4AddressSize
: kIPv6AddressSize
;
443 IPAddressNumber
addr_any(addr_size
);
444 rv
= RandomBind(addr_any
);
446 // else connect() does the DatagramSocket::DEFAULT_BIND
449 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
453 SockaddrStorage storage
;
454 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
455 return ERR_ADDRESS_INVALID
;
457 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
459 return MapSystemError(WSAGetLastError());
461 remote_address_
.reset(new IPEndPoint(address
));
465 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
466 DCHECK_NE(socket_
, INVALID_SOCKET
);
467 DCHECK(!is_connected());
469 int rv
= SetMulticastOptions();
473 rv
= DoBind(address
);
477 local_address_
.reset();
478 is_connected_
= true;
482 int UDPSocketWin::SetReceiveBufferSize(int32 size
) {
483 DCHECK_NE(socket_
, INVALID_SOCKET
);
484 DCHECK(CalledOnValidThread());
485 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
486 reinterpret_cast<const char*>(&size
), sizeof(size
));
488 return MapSystemError(WSAGetLastError());
490 // According to documentation, setsockopt may succeed, but we need to check
491 // the results via getsockopt to be sure it works on Windows.
492 int32 actual_size
= 0;
493 int option_size
= sizeof(actual_size
);
494 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
495 reinterpret_cast<char*>(&actual_size
), &option_size
);
497 return MapSystemError(WSAGetLastError());
498 if (actual_size
>= size
)
500 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
501 actual_size
, 1000, 1000000, 50);
502 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
505 int UDPSocketWin::SetSendBufferSize(int32 size
) {
506 DCHECK_NE(socket_
, INVALID_SOCKET
);
507 DCHECK(CalledOnValidThread());
508 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
509 reinterpret_cast<const char*>(&size
), sizeof(size
));
511 return MapSystemError(WSAGetLastError());
512 // According to documentation, setsockopt may succeed, but we need to check
513 // the results via getsockopt to be sure it works on Windows.
514 int32 actual_size
= 0;
515 int option_size
= sizeof(actual_size
);
516 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
517 reinterpret_cast<char*>(&actual_size
), &option_size
);
519 return MapSystemError(WSAGetLastError());
520 if (actual_size
>= size
)
522 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
523 actual_size
, 1000, 1000000, 50);
524 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
527 int UDPSocketWin::AllowAddressReuse() {
528 DCHECK_NE(socket_
, INVALID_SOCKET
);
529 DCHECK(CalledOnValidThread());
530 DCHECK(!is_connected());
532 BOOL true_value
= TRUE
;
533 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
534 reinterpret_cast<const char*>(&true_value
),
536 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
539 int UDPSocketWin::SetBroadcast(bool broadcast
) {
540 DCHECK_NE(socket_
, INVALID_SOCKET
);
541 DCHECK(CalledOnValidThread());
543 BOOL value
= broadcast
? TRUE
: FALSE
;
544 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
545 reinterpret_cast<const char*>(&value
), sizeof(value
));
546 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
549 void UDPSocketWin::DoReadCallback(int rv
) {
550 DCHECK_NE(rv
, ERR_IO_PENDING
);
551 DCHECK(!read_callback_
.is_null());
553 // since Run may result in Read being called, clear read_callback_ up front.
554 CompletionCallback c
= read_callback_
;
555 read_callback_
.Reset();
559 void UDPSocketWin::DoWriteCallback(int rv
) {
560 DCHECK_NE(rv
, ERR_IO_PENDING
);
561 DCHECK(!write_callback_
.is_null());
563 // since Run may result in Write being called, clear write_callback_ up front.
564 CompletionCallback c
= write_callback_
;
565 write_callback_
.Reset();
569 void UDPSocketWin::DidCompleteRead() {
570 DWORD num_bytes
, flags
;
571 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
572 &num_bytes
, FALSE
, &flags
);
573 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
574 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
576 if (recv_from_address_
&& result
>= 0) {
577 if (!ReceiveAddressToIPEndpoint(recv_from_address_
))
578 result
= ERR_ADDRESS_INVALID
;
580 LogRead(result
, core_
->read_iobuffer_
->data());
581 core_
->read_iobuffer_
= NULL
;
582 recv_from_address_
= NULL
;
583 DoReadCallback(result
);
586 void UDPSocketWin::LogRead(int result
, const char* bytes
) const {
588 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
592 if (net_log_
.IsLogging()) {
593 // Get address for logging, if |address| is NULL.
595 bool is_address_valid
= ReceiveAddressToIPEndpoint(&address
);
597 NetLog::TYPE_UDP_BYTES_RECEIVED
,
598 CreateNetLogUDPDataTranferCallback(
600 is_address_valid
? &address
: NULL
));
603 base::StatsCounter
read_bytes("udp.read_bytes");
604 read_bytes
.Add(result
);
605 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result
);
608 void UDPSocketWin::DidCompleteWrite() {
609 DWORD num_bytes
, flags
;
610 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
611 &num_bytes
, FALSE
, &flags
);
612 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
613 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
614 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
616 send_to_address_
.reset();
617 core_
->write_iobuffer_
= NULL
;
618 DoWriteCallback(result
);
621 void UDPSocketWin::LogWrite(int result
,
623 const IPEndPoint
* address
) const {
625 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
629 if (net_log_
.IsLogging()) {
631 NetLog::TYPE_UDP_BYTES_SENT
,
632 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
635 base::StatsCounter
write_bytes("udp.write_bytes");
636 write_bytes
.Add(result
);
637 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result
);
640 int UDPSocketWin::InternalRecvFrom(IOBuffer
* buf
, int buf_len
,
641 IPEndPoint
* address
) {
642 DCHECK(!core_
->read_iobuffer_
.get());
643 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
644 storage
.addr_len
= sizeof(storage
.addr_storage
);
647 read_buffer
.buf
= buf
->data();
648 read_buffer
.len
= buf_len
;
652 CHECK_NE(INVALID_SOCKET
, socket_
);
653 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
654 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
655 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
657 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
660 if (address
&& result
>= 0) {
661 if (!ReceiveAddressToIPEndpoint(address
))
662 result
= ERR_ADDRESS_INVALID
;
664 LogRead(result
, buf
->data());
668 int os_error
= WSAGetLastError();
669 if (os_error
!= WSA_IO_PENDING
) {
670 int result
= MapSystemError(os_error
);
671 LogRead(result
, NULL
);
675 core_
->WatchForRead();
676 core_
->read_iobuffer_
= buf
;
677 return ERR_IO_PENDING
;
680 int UDPSocketWin::InternalSendTo(IOBuffer
* buf
, int buf_len
,
681 const IPEndPoint
* address
) {
682 DCHECK(!core_
->write_iobuffer_
.get());
683 SockaddrStorage storage
;
684 struct sockaddr
* addr
= storage
.addr
;
688 storage
.addr_len
= 0;
690 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
691 int result
= ERR_ADDRESS_INVALID
;
692 LogWrite(result
, NULL
, NULL
);
698 write_buffer
.buf
= buf
->data();
699 write_buffer
.len
= buf_len
;
703 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
704 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
705 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
707 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
709 LogWrite(result
, buf
->data(), address
);
713 int os_error
= WSAGetLastError();
714 if (os_error
!= WSA_IO_PENDING
) {
715 int result
= MapSystemError(os_error
);
716 LogWrite(result
, NULL
, NULL
);
721 core_
->WatchForWrite();
722 core_
->write_iobuffer_
= buf
;
723 return ERR_IO_PENDING
;
726 int UDPSocketWin::SetMulticastOptions() {
727 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
730 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
732 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
733 int rv
= setsockopt(socket_
, protocol_level
, option
,
734 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
736 return MapSystemError(WSAGetLastError());
738 if (multicast_time_to_live_
!= 1) {
739 DWORD hops
= multicast_time_to_live_
;
741 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
743 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
744 int rv
= setsockopt(socket_
, protocol_level
, option
,
745 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
747 return MapSystemError(WSAGetLastError());
749 if (multicast_interface_
!= 0) {
750 switch (addr_family_
) {
753 address
.s_addr
= htonl(multicast_interface_
);
754 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
755 reinterpret_cast<const char*>(&address
),
758 return MapSystemError(WSAGetLastError());
762 uint32 interface_index
= multicast_interface_
;
763 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
764 reinterpret_cast<const char*>(&interface_index
),
765 sizeof(interface_index
));
767 return MapSystemError(WSAGetLastError());
771 NOTREACHED() << "Invalid address family";
772 return ERR_ADDRESS_INVALID
;
778 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
779 SockaddrStorage storage
;
780 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
781 return ERR_ADDRESS_INVALID
;
782 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
785 int last_error
= WSAGetLastError();
786 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
787 // Map some codes that are special to bind() separately.
788 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
789 // returned instead of WSAEADDRINUSE, depending on whether the socket
790 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
791 // conflicting socket is owned by a different user account. See the MSDN
792 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
793 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
794 return ERR_ADDRESS_IN_USE
;
795 return MapSystemError(last_error
);
798 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
799 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
801 for (int i
= 0; i
< kBindRetries
; ++i
) {
802 int rv
= DoBind(IPEndPoint(
803 address
, static_cast<uint16
>(rand_int_cb_
.Run(kPortStart
, kPortEnd
))));
804 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
807 return DoBind(IPEndPoint(address
, 0));
810 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint
* address
) const {
811 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
812 return address
->FromSockAddr(storage
.addr
, storage
.addr_len
);
815 int UDPSocketWin::JoinGroup(
816 const IPAddressNumber
& group_address
) const {
817 DCHECK(CalledOnValidThread());
819 return ERR_SOCKET_NOT_CONNECTED
;
821 switch (group_address
.size()) {
822 case kIPv4AddressSize
: {
823 if (addr_family_
!= AF_INET
)
824 return ERR_ADDRESS_INVALID
;
826 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
827 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
828 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
829 reinterpret_cast<const char*>(&mreq
),
832 return MapSystemError(WSAGetLastError());
835 case kIPv6AddressSize
: {
836 if (addr_family_
!= AF_INET6
)
837 return ERR_ADDRESS_INVALID
;
839 mreq
.ipv6mr_interface
= multicast_interface_
;
840 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
841 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
842 reinterpret_cast<const char*>(&mreq
),
845 return MapSystemError(WSAGetLastError());
849 NOTREACHED() << "Invalid address family";
850 return ERR_ADDRESS_INVALID
;
854 int UDPSocketWin::LeaveGroup(
855 const IPAddressNumber
& group_address
) const {
856 DCHECK(CalledOnValidThread());
858 return ERR_SOCKET_NOT_CONNECTED
;
860 switch (group_address
.size()) {
861 case kIPv4AddressSize
: {
862 if (addr_family_
!= AF_INET
)
863 return ERR_ADDRESS_INVALID
;
865 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
866 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
867 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
868 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
870 return MapSystemError(WSAGetLastError());
873 case kIPv6AddressSize
: {
874 if (addr_family_
!= AF_INET6
)
875 return ERR_ADDRESS_INVALID
;
877 mreq
.ipv6mr_interface
= multicast_interface_
;
878 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
879 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
880 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
882 return MapSystemError(WSAGetLastError());
886 NOTREACHED() << "Invalid address family";
887 return ERR_ADDRESS_INVALID
;
891 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
892 DCHECK(CalledOnValidThread());
894 return ERR_SOCKET_IS_CONNECTED
;
895 multicast_interface_
= interface_index
;
899 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
900 DCHECK(CalledOnValidThread());
902 return ERR_SOCKET_IS_CONNECTED
;
904 if (time_to_live
< 0 || time_to_live
> 255)
905 return ERR_INVALID_ARGUMENT
;
906 multicast_time_to_live_
= time_to_live
;
910 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
911 DCHECK(CalledOnValidThread());
913 return ERR_SOCKET_IS_CONNECTED
;
916 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
918 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
922 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
923 if (dscp
== DSCP_NO_CHANGE
) {
928 return ERR_SOCKET_NOT_CONNECTED
;
930 QwaveAPI
& qos(QwaveAPI::Get());
932 if (!qos
.qwave_supported())
933 return ERROR_NOT_SUPPORTED
;
935 if (qos_handle_
== NULL
) {
937 version
.MajorVersion
= 1;
938 version
.MinorVersion
= 0;
939 qos
.CreateHandle(&version
, &qos_handle_
);
940 if (qos_handle_
== NULL
)
941 return ERROR_NOT_SUPPORTED
;
944 QOS_TRAFFIC_TYPE traffic_type
= QOSTrafficTypeBestEffort
;
947 traffic_type
= QOSTrafficTypeBestEffort
;
950 traffic_type
= QOSTrafficTypeBackground
;
964 traffic_type
= QOSTrafficTypeExcellentEffort
;
970 traffic_type
= QOSTrafficTypeAudioVideo
;
974 traffic_type
= QOSTrafficTypeVoice
;
977 traffic_type
= QOSTrafficTypeControl
;
983 if (qos_flow_id_
!= 0) {
984 qos
.RemoveSocketFromFlow(qos_handle_
, NULL
, qos_flow_id_
, 0);
987 if (!qos
.AddSocketToFlow(qos_handle_
,
991 QOS_NON_ADAPTIVE_FLOW
,
993 DWORD err
= GetLastError();
994 if (err
== ERROR_DEVICE_REINITIALIZATION_NEEDED
) {
995 qos
.CloseHandle(qos_handle_
);
999 return MapSystemError(err
);
1001 // This requires admin rights, and may fail, if so we ignore it
1002 // as AddSocketToFlow should still do *approximately* the right thing.
1004 qos
.SetFlow(qos_handle_
,
1006 QOSSetOutgoingDSCPValue
,
1015 void UDPSocketWin::DetachFromThread() {
1016 base::NonThreadSafe::DetachFromThread();