1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/udp/udp_socket_win.h"
9 #include "base/basictypes.h"
10 #include "base/callback.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/histogram.h"
15 #include "base/metrics/sparse_histogram.h"
16 #include "base/profiler/scoped_tracker.h"
17 #include "base/rand_util.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/ip_endpoint.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_log.h"
22 #include "net/base/net_util.h"
23 #include "net/base/network_activity_monitor.h"
24 #include "net/base/winsock_init.h"
25 #include "net/base/winsock_util.h"
26 #include "net/socket/socket_descriptor.h"
27 #include "net/udp/udp_net_log_parameters.h"
31 const int kBindRetries
= 10;
32 const int kPortStart
= 1024;
33 const int kPortEnd
= 65535;
39 // This class encapsulates all the state that has to be preserved as long as
40 // there is a network IO operation in progress. If the owner UDPSocketWin
41 // is destroyed while an operation is in progress, the Core is detached and it
42 // lives until the operation completes and the OS doesn't reference any resource
43 // declared on this class anymore.
44 class UDPSocketWin::Core
: public base::RefCounted
<Core
> {
46 explicit Core(UDPSocketWin
* socket
);
48 // Start watching for the end of a read or write operation.
52 // The UDPSocketWin is going away.
53 void Detach() { socket_
= NULL
; }
55 // The separate OVERLAPPED variables for asynchronous operation.
56 OVERLAPPED read_overlapped_
;
57 OVERLAPPED write_overlapped_
;
59 // The buffers used in Read() and Write().
60 scoped_refptr
<IOBuffer
> read_iobuffer_
;
61 scoped_refptr
<IOBuffer
> write_iobuffer_
;
63 // The address storage passed to WSARecvFrom().
64 SockaddrStorage recv_addr_storage_
;
67 friend class base::RefCounted
<Core
>;
69 class ReadDelegate
: public base::win::ObjectWatcher::Delegate
{
71 explicit ReadDelegate(Core
* core
) : core_(core
) {}
72 virtual ~ReadDelegate() {}
74 // base::ObjectWatcher::Delegate methods:
75 virtual void OnObjectSignaled(HANDLE object
);
81 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
83 explicit WriteDelegate(Core
* core
) : core_(core
) {}
84 virtual ~WriteDelegate() {}
86 // base::ObjectWatcher::Delegate methods:
87 virtual void OnObjectSignaled(HANDLE object
);
95 // The socket that created this object.
96 UDPSocketWin
* socket_
;
98 // |reader_| handles the signals from |read_watcher_|.
100 // |writer_| handles the signals from |write_watcher_|.
101 WriteDelegate writer_
;
103 // |read_watcher_| watches for events from Read().
104 base::win::ObjectWatcher read_watcher_
;
105 // |write_watcher_| watches for events from Write();
106 base::win::ObjectWatcher write_watcher_
;
108 DISALLOW_COPY_AND_ASSIGN(Core
);
111 UDPSocketWin::Core::Core(UDPSocketWin
* socket
)
115 memset(&read_overlapped_
, 0, sizeof(read_overlapped_
));
116 memset(&write_overlapped_
, 0, sizeof(write_overlapped_
));
118 read_overlapped_
.hEvent
= WSACreateEvent();
119 write_overlapped_
.hEvent
= WSACreateEvent();
122 UDPSocketWin::Core::~Core() {
123 // Make sure the message loop is not watching this object anymore.
124 read_watcher_
.StopWatching();
125 write_watcher_
.StopWatching();
127 WSACloseEvent(read_overlapped_
.hEvent
);
128 memset(&read_overlapped_
, 0xaf, sizeof(read_overlapped_
));
129 WSACloseEvent(write_overlapped_
.hEvent
);
130 memset(&write_overlapped_
, 0xaf, sizeof(write_overlapped_
));
133 void UDPSocketWin::Core::WatchForRead() {
134 // We grab an extra reference because there is an IO operation in progress.
135 // Balanced in ReadDelegate::OnObjectSignaled().
137 read_watcher_
.StartWatching(read_overlapped_
.hEvent
, &reader_
);
140 void UDPSocketWin::Core::WatchForWrite() {
141 // We grab an extra reference because there is an IO operation in progress.
142 // Balanced in WriteDelegate::OnObjectSignaled().
144 write_watcher_
.StartWatching(write_overlapped_
.hEvent
, &writer_
);
147 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object
) {
148 // TODO(pkasting): Remove ScopedTracker below once crbug.com/462789 is fixed.
149 tracked_objects::ScopedTracker
tracking_profile(
150 FROM_HERE_WITH_EXPLICIT_FUNCTION(
151 "462789 UDPSocketWin::Core::ReadDelegate::OnObjectSignaled"));
153 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
155 core_
->socket_
->DidCompleteRead();
160 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
161 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
163 core_
->socket_
->DidCompleteWrite();
167 //-----------------------------------------------------------------------------
169 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
170 HMODULE qwave
= LoadLibrary(L
"qwave.dll");
173 create_handle_func_
=
174 (CreateHandleFn
)GetProcAddress(qwave
, "QOSCreateHandle");
176 (CloseHandleFn
)GetProcAddress(qwave
, "QOSCloseHandle");
177 add_socket_to_flow_func_
=
178 (AddSocketToFlowFn
)GetProcAddress(qwave
, "QOSAddSocketToFlow");
179 remove_socket_from_flow_func_
=
180 (RemoveSocketFromFlowFn
)GetProcAddress(qwave
, "QOSRemoveSocketFromFlow");
181 set_flow_func_
= (SetFlowFn
)GetProcAddress(qwave
, "QOSSetFlow");
183 if (create_handle_func_
&& close_handle_func_
&&
184 add_socket_to_flow_func_
&& remove_socket_from_flow_func_
&&
186 qwave_supported_
= true;
190 QwaveAPI
& QwaveAPI::Get() {
191 static base::LazyInstance
<QwaveAPI
>::Leaky lazy_qwave
=
192 LAZY_INSTANCE_INITIALIZER
;
193 return lazy_qwave
.Get();
196 bool QwaveAPI::qwave_supported() const {
197 return qwave_supported_
;
199 BOOL
QwaveAPI::CreateHandle(PQOS_VERSION version
, PHANDLE handle
) {
200 return create_handle_func_(version
, handle
);
202 BOOL
QwaveAPI::CloseHandle(HANDLE handle
) {
203 return close_handle_func_(handle
);
206 BOOL
QwaveAPI::AddSocketToFlow(HANDLE handle
,
209 QOS_TRAFFIC_TYPE traffic_type
,
211 PQOS_FLOWID flow_id
) {
212 return add_socket_to_flow_func_(handle
,
220 BOOL
QwaveAPI::RemoveSocketFromFlow(HANDLE handle
,
224 return remove_socket_from_flow_func_(handle
, socket
, flow_id
, reserved
);
227 BOOL
QwaveAPI::SetFlow(HANDLE handle
,
233 LPOVERLAPPED overlapped
) {
234 return set_flow_func_(handle
,
244 //-----------------------------------------------------------------------------
246 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type
,
247 const RandIntCallback
& rand_int_cb
,
248 net::NetLog
* net_log
,
249 const net::NetLog::Source
& source
)
250 : socket_(INVALID_SOCKET
),
252 is_connected_(false),
253 socket_options_(SOCKET_OPTION_MULTICAST_LOOP
),
254 multicast_interface_(0),
255 multicast_time_to_live_(1),
256 bind_type_(bind_type
),
257 rand_int_cb_(rand_int_cb
),
258 use_non_blocking_io_(false),
259 read_iobuffer_len_(0),
260 write_iobuffer_len_(0),
261 recv_from_address_(NULL
),
262 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_UDP_SOCKET
)),
266 net_log_
.BeginEvent(NetLog::TYPE_SOCKET_ALIVE
,
267 source
.ToEventParametersCallback());
268 if (bind_type
== DatagramSocket::RANDOM_BIND
)
269 DCHECK(!rand_int_cb
.is_null());
272 UDPSocketWin::~UDPSocketWin() {
274 net_log_
.EndEvent(NetLog::TYPE_SOCKET_ALIVE
);
277 int UDPSocketWin::Open(AddressFamily address_family
) {
278 DCHECK(CalledOnValidThread());
279 DCHECK_EQ(socket_
, INVALID_SOCKET
);
281 addr_family_
= ConvertAddressFamily(address_family
);
282 socket_
= CreatePlatformSocket(addr_family_
, SOCK_DGRAM
, IPPROTO_UDP
);
283 if (socket_
== INVALID_SOCKET
)
284 return MapSystemError(WSAGetLastError());
285 if (!use_non_blocking_io_
) {
286 core_
= new Core(this);
288 read_write_event_
.Set(WSACreateEvent());
289 WSAEventSelect(socket_
, read_write_event_
.Get(), FD_READ
| FD_WRITE
);
294 void UDPSocketWin::Close() {
295 DCHECK(CalledOnValidThread());
297 if (socket_
== INVALID_SOCKET
)
301 QwaveAPI::Get().CloseHandle(qos_handle_
);
304 // Zero out any pending read/write callback state.
305 read_callback_
.Reset();
306 recv_from_address_
= NULL
;
307 write_callback_
.Reset();
309 base::TimeTicks start_time
= base::TimeTicks::Now();
310 closesocket(socket_
);
311 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
312 base::TimeTicks::Now() - start_time
);
313 socket_
= INVALID_SOCKET
;
315 is_connected_
= false;
317 read_write_watcher_
.StopWatching();
318 read_write_event_
.Close();
326 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
327 DCHECK(CalledOnValidThread());
330 return ERR_SOCKET_NOT_CONNECTED
;
332 // TODO(szym): Simplify. http://crbug.com/126152
333 if (!remote_address_
.get()) {
334 SockaddrStorage storage
;
335 if (getpeername(socket_
, storage
.addr
, &storage
.addr_len
))
336 return MapSystemError(WSAGetLastError());
337 scoped_ptr
<IPEndPoint
> remote_address(new IPEndPoint());
338 if (!remote_address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
339 return ERR_ADDRESS_INVALID
;
340 remote_address_
.reset(remote_address
.release());
343 *address
= *remote_address_
;
347 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
348 DCHECK(CalledOnValidThread());
351 return ERR_SOCKET_NOT_CONNECTED
;
353 // TODO(szym): Simplify. http://crbug.com/126152
354 if (!local_address_
.get()) {
355 SockaddrStorage storage
;
356 if (getsockname(socket_
, storage
.addr
, &storage
.addr_len
))
357 return MapSystemError(WSAGetLastError());
358 scoped_ptr
<IPEndPoint
> local_address(new IPEndPoint());
359 if (!local_address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
360 return ERR_ADDRESS_INVALID
;
361 local_address_
.reset(local_address
.release());
362 net_log_
.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS
,
363 CreateNetLogUDPConnectCallback(local_address_
.get()));
366 *address
= *local_address_
;
370 int UDPSocketWin::Read(IOBuffer
* buf
,
372 const CompletionCallback
& callback
) {
373 return RecvFrom(buf
, buf_len
, NULL
, callback
);
376 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
379 const CompletionCallback
& callback
) {
380 DCHECK(CalledOnValidThread());
381 DCHECK_NE(INVALID_SOCKET
, socket_
);
382 CHECK(read_callback_
.is_null());
383 DCHECK(!recv_from_address_
);
384 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
385 DCHECK_GT(buf_len
, 0);
387 int nread
= core_
? InternalRecvFromOverlapped(buf
, buf_len
, address
)
388 : InternalRecvFromNonBlocking(buf
, buf_len
, address
);
389 if (nread
!= ERR_IO_PENDING
)
392 read_callback_
= callback
;
393 recv_from_address_
= address
;
394 return ERR_IO_PENDING
;
397 int UDPSocketWin::Write(IOBuffer
* buf
,
399 const CompletionCallback
& callback
) {
400 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
403 int UDPSocketWin::SendTo(IOBuffer
* buf
,
405 const IPEndPoint
& address
,
406 const CompletionCallback
& callback
) {
407 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
410 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
412 const IPEndPoint
* address
,
413 const CompletionCallback
& callback
) {
414 DCHECK(CalledOnValidThread());
415 DCHECK_NE(INVALID_SOCKET
, socket_
);
416 CHECK(write_callback_
.is_null());
417 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
418 DCHECK_GT(buf_len
, 0);
419 DCHECK(!send_to_address_
.get());
421 int nwrite
= core_
? InternalSendToOverlapped(buf
, buf_len
, address
)
422 : InternalSendToNonBlocking(buf
, buf_len
, address
);
423 if (nwrite
!= ERR_IO_PENDING
)
427 send_to_address_
.reset(new IPEndPoint(*address
));
428 write_callback_
= callback
;
429 return ERR_IO_PENDING
;
432 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
433 DCHECK_NE(socket_
, INVALID_SOCKET
);
434 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
435 CreateNetLogUDPConnectCallback(&address
));
436 int rv
= InternalConnect(address
);
437 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
438 is_connected_
= (rv
== OK
);
442 int UDPSocketWin::InternalConnect(const IPEndPoint
& address
) {
443 DCHECK(!is_connected());
444 DCHECK(!remote_address_
.get());
447 if (bind_type_
== DatagramSocket::RANDOM_BIND
) {
448 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
449 // representing INADDR_ANY or in6addr_any.
450 size_t addr_size
= (address
.GetSockAddrFamily() == AF_INET
) ?
451 kIPv4AddressSize
: kIPv6AddressSize
;
452 IPAddressNumber
addr_any(addr_size
);
453 rv
= RandomBind(addr_any
);
455 // else connect() does the DatagramSocket::DEFAULT_BIND
458 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
462 SockaddrStorage storage
;
463 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
464 return ERR_ADDRESS_INVALID
;
466 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
468 return MapSystemError(WSAGetLastError());
470 remote_address_
.reset(new IPEndPoint(address
));
474 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
475 DCHECK_NE(socket_
, INVALID_SOCKET
);
476 DCHECK(!is_connected());
478 int rv
= SetMulticastOptions();
482 rv
= DoBind(address
);
486 local_address_
.reset();
487 is_connected_
= true;
491 int UDPSocketWin::SetReceiveBufferSize(int32 size
) {
492 DCHECK_NE(socket_
, INVALID_SOCKET
);
493 DCHECK(CalledOnValidThread());
494 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
495 reinterpret_cast<const char*>(&size
), sizeof(size
));
497 return MapSystemError(WSAGetLastError());
499 // According to documentation, setsockopt may succeed, but we need to check
500 // the results via getsockopt to be sure it works on Windows.
501 int32 actual_size
= 0;
502 int option_size
= sizeof(actual_size
);
503 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
504 reinterpret_cast<char*>(&actual_size
), &option_size
);
506 return MapSystemError(WSAGetLastError());
507 if (actual_size
>= size
)
509 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
510 actual_size
, 1000, 1000000, 50);
511 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
514 int UDPSocketWin::SetSendBufferSize(int32 size
) {
515 DCHECK_NE(socket_
, INVALID_SOCKET
);
516 DCHECK(CalledOnValidThread());
517 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
518 reinterpret_cast<const char*>(&size
), sizeof(size
));
520 return MapSystemError(WSAGetLastError());
521 // According to documentation, setsockopt may succeed, but we need to check
522 // the results via getsockopt to be sure it works on Windows.
523 int32 actual_size
= 0;
524 int option_size
= sizeof(actual_size
);
525 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
526 reinterpret_cast<char*>(&actual_size
), &option_size
);
528 return MapSystemError(WSAGetLastError());
529 if (actual_size
>= size
)
531 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
532 actual_size
, 1000, 1000000, 50);
533 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
536 int UDPSocketWin::AllowAddressReuse() {
537 DCHECK_NE(socket_
, INVALID_SOCKET
);
538 DCHECK(CalledOnValidThread());
539 DCHECK(!is_connected());
541 BOOL true_value
= TRUE
;
542 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
543 reinterpret_cast<const char*>(&true_value
),
545 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
548 int UDPSocketWin::SetBroadcast(bool broadcast
) {
549 DCHECK_NE(socket_
, INVALID_SOCKET
);
550 DCHECK(CalledOnValidThread());
552 BOOL value
= broadcast
? TRUE
: FALSE
;
553 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
554 reinterpret_cast<const char*>(&value
), sizeof(value
));
555 return rv
== 0 ? OK
: MapSystemError(WSAGetLastError());
558 void UDPSocketWin::DoReadCallback(int rv
) {
559 DCHECK_NE(rv
, ERR_IO_PENDING
);
560 DCHECK(!read_callback_
.is_null());
562 // since Run may result in Read being called, clear read_callback_ up front.
563 CompletionCallback c
= read_callback_
;
564 read_callback_
.Reset();
568 void UDPSocketWin::DoWriteCallback(int rv
) {
569 DCHECK_NE(rv
, ERR_IO_PENDING
);
570 DCHECK(!write_callback_
.is_null());
572 // since Run may result in Write being called, clear write_callback_ up front.
573 CompletionCallback c
= write_callback_
;
574 write_callback_
.Reset();
578 void UDPSocketWin::DidCompleteRead() {
579 DWORD num_bytes
, flags
;
580 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
581 &num_bytes
, FALSE
, &flags
);
582 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
583 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
586 IPEndPoint
* address_to_log
= NULL
;
588 if (address
.FromSockAddr(core_
->recv_addr_storage_
.addr
,
589 core_
->recv_addr_storage_
.addr_len
)) {
590 if (recv_from_address_
)
591 *recv_from_address_
= address
;
592 address_to_log
= &address
;
594 result
= ERR_ADDRESS_INVALID
;
597 LogRead(result
, core_
->read_iobuffer_
->data(), address_to_log
);
598 core_
->read_iobuffer_
= NULL
;
599 recv_from_address_
= NULL
;
600 DoReadCallback(result
);
603 void UDPSocketWin::DidCompleteWrite() {
604 DWORD num_bytes
, flags
;
605 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
606 &num_bytes
, FALSE
, &flags
);
607 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
608 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
609 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
611 send_to_address_
.reset();
612 core_
->write_iobuffer_
= NULL
;
613 DoWriteCallback(result
);
616 void UDPSocketWin::OnObjectSignaled(HANDLE object
) {
617 DCHECK(object
== read_write_event_
.Get());
618 WSANETWORKEVENTS network_events
;
621 WSAEnumNetworkEvents(socket_
, read_write_event_
.Get(), &network_events
);
622 if (rv
== SOCKET_ERROR
) {
623 os_error
= WSAGetLastError();
624 rv
= MapSystemError(os_error
);
625 if (read_iobuffer_
) {
626 read_iobuffer_
= NULL
;
627 read_iobuffer_len_
= 0;
628 recv_from_address_
= NULL
;
631 if (write_iobuffer_
) {
632 write_iobuffer_
= NULL
;
633 write_iobuffer_len_
= 0;
634 send_to_address_
.reset();
639 if ((network_events
.lNetworkEvents
& FD_READ
) && read_iobuffer_
) {
642 if ((network_events
.lNetworkEvents
& FD_WRITE
) && write_iobuffer_
) {
646 // There's still pending read / write. Watch for further events.
647 if (read_iobuffer_
|| write_iobuffer_
) {
652 void UDPSocketWin::OnReadSignaled() {
653 int rv
= InternalRecvFromNonBlocking(read_iobuffer_
.get(), read_iobuffer_len_
,
655 if (rv
== ERR_IO_PENDING
)
657 read_iobuffer_
= NULL
;
658 read_iobuffer_len_
= 0;
659 recv_from_address_
= NULL
;
663 void UDPSocketWin::OnWriteSignaled() {
664 int rv
= InternalSendToNonBlocking(write_iobuffer_
.get(), write_iobuffer_len_
,
665 send_to_address_
.get());
666 if (rv
== ERR_IO_PENDING
)
668 write_iobuffer_
= NULL
;
669 write_iobuffer_len_
= 0;
670 send_to_address_
.reset();
674 void UDPSocketWin::WatchForReadWrite() {
675 if (read_write_watcher_
.IsWatching())
678 read_write_watcher_
.StartWatching(read_write_event_
.Get(), this);
682 void UDPSocketWin::LogRead(int result
,
684 const IPEndPoint
* address
) const {
686 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
690 if (net_log_
.IsLogging()) {
692 NetLog::TYPE_UDP_BYTES_RECEIVED
,
693 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
696 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result
);
699 void UDPSocketWin::LogWrite(int result
,
701 const IPEndPoint
* address
) const {
703 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
707 if (net_log_
.IsLogging()) {
709 NetLog::TYPE_UDP_BYTES_SENT
,
710 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
713 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result
);
716 int UDPSocketWin::InternalRecvFromOverlapped(IOBuffer
* buf
,
718 IPEndPoint
* address
) {
719 DCHECK(!core_
->read_iobuffer_
.get());
720 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
721 storage
.addr_len
= sizeof(storage
.addr_storage
);
724 read_buffer
.buf
= buf
->data();
725 read_buffer
.len
= buf_len
;
729 CHECK_NE(INVALID_SOCKET
, socket_
);
730 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
731 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
732 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
734 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
737 IPEndPoint address_storage
;
738 IPEndPoint
* address_to_log
= NULL
;
740 if (address_storage
.FromSockAddr(core_
->recv_addr_storage_
.addr
,
741 core_
->recv_addr_storage_
.addr_len
)) {
743 *address
= address_storage
;
744 address_to_log
= &address_storage
;
746 result
= ERR_ADDRESS_INVALID
;
749 LogRead(result
, buf
->data(), address_to_log
);
753 int os_error
= WSAGetLastError();
754 if (os_error
!= WSA_IO_PENDING
) {
755 int result
= MapSystemError(os_error
);
756 LogRead(result
, NULL
, NULL
);
760 core_
->WatchForRead();
761 core_
->read_iobuffer_
= buf
;
762 return ERR_IO_PENDING
;
765 int UDPSocketWin::InternalSendToOverlapped(IOBuffer
* buf
,
767 const IPEndPoint
* address
) {
768 DCHECK(!core_
->write_iobuffer_
.get());
769 SockaddrStorage storage
;
770 struct sockaddr
* addr
= storage
.addr
;
774 storage
.addr_len
= 0;
776 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
777 int result
= ERR_ADDRESS_INVALID
;
778 LogWrite(result
, NULL
, NULL
);
784 write_buffer
.buf
= buf
->data();
785 write_buffer
.len
= buf_len
;
789 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
790 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
791 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
793 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
795 LogWrite(result
, buf
->data(), address
);
799 int os_error
= WSAGetLastError();
800 if (os_error
!= WSA_IO_PENDING
) {
801 int result
= MapSystemError(os_error
);
802 LogWrite(result
, NULL
, NULL
);
807 core_
->WatchForWrite();
808 core_
->write_iobuffer_
= buf
;
809 return ERR_IO_PENDING
;
812 int UDPSocketWin::InternalRecvFromNonBlocking(IOBuffer
* buf
,
814 IPEndPoint
* address
) {
815 DCHECK(!read_iobuffer_
|| read_iobuffer_
.get() == buf
);
816 SockaddrStorage storage
;
817 storage
.addr_len
= sizeof(storage
.addr_storage
);
819 CHECK_NE(INVALID_SOCKET
, socket_
);
820 int rv
= recvfrom(socket_
, buf
->data(), buf_len
, 0, storage
.addr
,
822 if (rv
== SOCKET_ERROR
) {
823 int os_error
= WSAGetLastError();
824 if (os_error
== WSAEWOULDBLOCK
) {
825 read_iobuffer_
= buf
;
826 read_iobuffer_len_
= buf_len
;
828 return ERR_IO_PENDING
;
830 rv
= MapSystemError(os_error
);
831 LogRead(rv
, NULL
, NULL
);
834 IPEndPoint address_storage
;
835 IPEndPoint
* address_to_log
= NULL
;
837 if (address_storage
.FromSockAddr(storage
.addr
, storage
.addr_len
)) {
839 *address
= address_storage
;
840 address_to_log
= &address_storage
;
842 rv
= ERR_ADDRESS_INVALID
;
845 LogRead(rv
, buf
->data(), address_to_log
);
849 int UDPSocketWin::InternalSendToNonBlocking(IOBuffer
* buf
,
851 const IPEndPoint
* address
) {
852 DCHECK(!write_iobuffer_
|| write_iobuffer_
.get() == buf
);
853 SockaddrStorage storage
;
854 struct sockaddr
* addr
= storage
.addr
;
857 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
858 int result
= ERR_ADDRESS_INVALID
;
859 LogWrite(result
, NULL
, NULL
);
864 storage
.addr_len
= 0;
867 int rv
= sendto(socket_
, buf
->data(), buf_len
, 0, addr
, storage
.addr_len
);
868 if (rv
== SOCKET_ERROR
) {
869 int os_error
= WSAGetLastError();
870 if (os_error
== WSAEWOULDBLOCK
) {
871 write_iobuffer_
= buf
;
872 write_iobuffer_len_
= buf_len
;
874 return ERR_IO_PENDING
;
876 rv
= MapSystemError(os_error
);
877 LogWrite(rv
, NULL
, NULL
);
880 LogWrite(rv
, buf
->data(), address
);
884 int UDPSocketWin::SetMulticastOptions() {
885 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
888 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
890 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
891 int rv
= setsockopt(socket_
, protocol_level
, option
,
892 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
894 return MapSystemError(WSAGetLastError());
896 if (multicast_time_to_live_
!= 1) {
897 DWORD hops
= multicast_time_to_live_
;
899 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
901 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
902 int rv
= setsockopt(socket_
, protocol_level
, option
,
903 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
905 return MapSystemError(WSAGetLastError());
907 if (multicast_interface_
!= 0) {
908 switch (addr_family_
) {
911 address
.s_addr
= htonl(multicast_interface_
);
912 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
913 reinterpret_cast<const char*>(&address
),
916 return MapSystemError(WSAGetLastError());
920 uint32 interface_index
= multicast_interface_
;
921 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
922 reinterpret_cast<const char*>(&interface_index
),
923 sizeof(interface_index
));
925 return MapSystemError(WSAGetLastError());
929 NOTREACHED() << "Invalid address family";
930 return ERR_ADDRESS_INVALID
;
936 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
937 SockaddrStorage storage
;
938 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
939 return ERR_ADDRESS_INVALID
;
940 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
943 int last_error
= WSAGetLastError();
944 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
945 // Map some codes that are special to bind() separately.
946 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
947 // returned instead of WSAEADDRINUSE, depending on whether the socket
948 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
949 // conflicting socket is owned by a different user account. See the MSDN
950 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
951 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
952 return ERR_ADDRESS_IN_USE
;
953 return MapSystemError(last_error
);
956 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
957 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
959 for (int i
= 0; i
< kBindRetries
; ++i
) {
960 int rv
= DoBind(IPEndPoint(
961 address
, static_cast<uint16
>(rand_int_cb_
.Run(kPortStart
, kPortEnd
))));
962 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
965 return DoBind(IPEndPoint(address
, 0));
968 int UDPSocketWin::JoinGroup(
969 const IPAddressNumber
& group_address
) const {
970 DCHECK(CalledOnValidThread());
972 return ERR_SOCKET_NOT_CONNECTED
;
974 switch (group_address
.size()) {
975 case kIPv4AddressSize
: {
976 if (addr_family_
!= AF_INET
)
977 return ERR_ADDRESS_INVALID
;
979 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
980 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
981 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
982 reinterpret_cast<const char*>(&mreq
),
985 return MapSystemError(WSAGetLastError());
988 case kIPv6AddressSize
: {
989 if (addr_family_
!= AF_INET6
)
990 return ERR_ADDRESS_INVALID
;
992 mreq
.ipv6mr_interface
= multicast_interface_
;
993 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
994 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
995 reinterpret_cast<const char*>(&mreq
),
998 return MapSystemError(WSAGetLastError());
1002 NOTREACHED() << "Invalid address family";
1003 return ERR_ADDRESS_INVALID
;
1007 int UDPSocketWin::LeaveGroup(
1008 const IPAddressNumber
& group_address
) const {
1009 DCHECK(CalledOnValidThread());
1010 if (!is_connected())
1011 return ERR_SOCKET_NOT_CONNECTED
;
1013 switch (group_address
.size()) {
1014 case kIPv4AddressSize
: {
1015 if (addr_family_
!= AF_INET
)
1016 return ERR_ADDRESS_INVALID
;
1018 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
1019 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
1020 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
1021 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
1023 return MapSystemError(WSAGetLastError());
1026 case kIPv6AddressSize
: {
1027 if (addr_family_
!= AF_INET6
)
1028 return ERR_ADDRESS_INVALID
;
1030 mreq
.ipv6mr_interface
= multicast_interface_
;
1031 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
1032 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
1033 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
1035 return MapSystemError(WSAGetLastError());
1039 NOTREACHED() << "Invalid address family";
1040 return ERR_ADDRESS_INVALID
;
1044 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
1045 DCHECK(CalledOnValidThread());
1047 return ERR_SOCKET_IS_CONNECTED
;
1048 multicast_interface_
= interface_index
;
1052 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
1053 DCHECK(CalledOnValidThread());
1055 return ERR_SOCKET_IS_CONNECTED
;
1057 if (time_to_live
< 0 || time_to_live
> 255)
1058 return ERR_INVALID_ARGUMENT
;
1059 multicast_time_to_live_
= time_to_live
;
1063 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
1064 DCHECK(CalledOnValidThread());
1066 return ERR_SOCKET_IS_CONNECTED
;
1069 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
1071 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
1075 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
1076 if (dscp
== DSCP_NO_CHANGE
) {
1080 if (!is_connected())
1081 return ERR_SOCKET_NOT_CONNECTED
;
1083 QwaveAPI
& qos(QwaveAPI::Get());
1085 if (!qos
.qwave_supported())
1086 return ERROR_NOT_SUPPORTED
;
1088 if (qos_handle_
== NULL
) {
1089 QOS_VERSION version
;
1090 version
.MajorVersion
= 1;
1091 version
.MinorVersion
= 0;
1092 qos
.CreateHandle(&version
, &qos_handle_
);
1093 if (qos_handle_
== NULL
)
1094 return ERROR_NOT_SUPPORTED
;
1097 QOS_TRAFFIC_TYPE traffic_type
= QOSTrafficTypeBestEffort
;
1100 traffic_type
= QOSTrafficTypeBestEffort
;
1103 traffic_type
= QOSTrafficTypeBackground
;
1117 traffic_type
= QOSTrafficTypeExcellentEffort
;
1123 traffic_type
= QOSTrafficTypeAudioVideo
;
1127 traffic_type
= QOSTrafficTypeVoice
;
1130 traffic_type
= QOSTrafficTypeControl
;
1132 case DSCP_NO_CHANGE
:
1136 if (qos_flow_id_
!= 0) {
1137 qos
.RemoveSocketFromFlow(qos_handle_
, NULL
, qos_flow_id_
, 0);
1140 if (!qos
.AddSocketToFlow(qos_handle_
,
1144 QOS_NON_ADAPTIVE_FLOW
,
1146 DWORD err
= GetLastError();
1147 if (err
== ERROR_DEVICE_REINITIALIZATION_NEEDED
) {
1148 qos
.CloseHandle(qos_handle_
);
1152 return MapSystemError(err
);
1154 // This requires admin rights, and may fail, if so we ignore it
1155 // as AddSocketToFlow should still do *approximately* the right thing.
1157 qos
.SetFlow(qos_handle_
,
1159 QOSSetOutgoingDSCPValue
,
1168 void UDPSocketWin::DetachFromThread() {
1169 base::NonThreadSafe::DetachFromThread();
1172 void UDPSocketWin::UseNonBlockingIO() {
1174 use_non_blocking_io_
= true;