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/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/metrics/histogram.h"
13 #include "base/metrics/sparse_histogram.h"
14 #include "base/metrics/stats_counters.h"
15 #include "base/rand_util.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/ip_endpoint.h"
18 #include "net/base/net_errors.h"
19 #include "net/base/net_log.h"
20 #include "net/base/net_util.h"
21 #include "net/base/winsock_init.h"
22 #include "net/base/winsock_util.h"
23 #include "net/socket/socket_descriptor.h"
24 #include "net/udp/udp_net_log_parameters.h"
28 const int kBindRetries
= 10;
29 const int kPortStart
= 1024;
30 const int kPortEnd
= 65535;
36 // This class encapsulates all the state that has to be preserved as long as
37 // there is a network IO operation in progress. If the owner UDPSocketWin
38 // is destroyed while an operation is in progress, the Core is detached and it
39 // lives until the operation completes and the OS doesn't reference any resource
40 // declared on this class anymore.
41 class UDPSocketWin::Core
: public base::RefCounted
<Core
> {
43 explicit Core(UDPSocketWin
* socket
);
45 // Start watching for the end of a read or write operation.
49 // The UDPSocketWin is going away.
50 void Detach() { socket_
= NULL
; }
52 // The separate OVERLAPPED variables for asynchronous operation.
53 OVERLAPPED read_overlapped_
;
54 OVERLAPPED write_overlapped_
;
56 // The buffers used in Read() and Write().
57 scoped_refptr
<IOBuffer
> read_iobuffer_
;
58 scoped_refptr
<IOBuffer
> write_iobuffer_
;
60 // The address storage passed to WSARecvFrom().
61 SockaddrStorage recv_addr_storage_
;
64 friend class base::RefCounted
<Core
>;
66 class ReadDelegate
: public base::win::ObjectWatcher::Delegate
{
68 explicit ReadDelegate(Core
* core
) : core_(core
) {}
69 virtual ~ReadDelegate() {}
71 // base::ObjectWatcher::Delegate methods:
72 virtual void OnObjectSignaled(HANDLE object
);
78 class WriteDelegate
: public base::win::ObjectWatcher::Delegate
{
80 explicit WriteDelegate(Core
* core
) : core_(core
) {}
81 virtual ~WriteDelegate() {}
83 // base::ObjectWatcher::Delegate methods:
84 virtual void OnObjectSignaled(HANDLE object
);
92 // The socket that created this object.
93 UDPSocketWin
* socket_
;
95 // |reader_| handles the signals from |read_watcher_|.
97 // |writer_| handles the signals from |write_watcher_|.
98 WriteDelegate writer_
;
100 // |read_watcher_| watches for events from Read().
101 base::win::ObjectWatcher read_watcher_
;
102 // |write_watcher_| watches for events from Write();
103 base::win::ObjectWatcher write_watcher_
;
105 DISALLOW_COPY_AND_ASSIGN(Core
);
108 UDPSocketWin::Core::Core(UDPSocketWin
* socket
)
112 memset(&read_overlapped_
, 0, sizeof(read_overlapped_
));
113 memset(&write_overlapped_
, 0, sizeof(write_overlapped_
));
115 read_overlapped_
.hEvent
= WSACreateEvent();
116 write_overlapped_
.hEvent
= WSACreateEvent();
119 UDPSocketWin::Core::~Core() {
120 // Make sure the message loop is not watching this object anymore.
121 read_watcher_
.StopWatching();
122 write_watcher_
.StopWatching();
124 WSACloseEvent(read_overlapped_
.hEvent
);
125 memset(&read_overlapped_
, 0xaf, sizeof(read_overlapped_
));
126 WSACloseEvent(write_overlapped_
.hEvent
);
127 memset(&write_overlapped_
, 0xaf, sizeof(write_overlapped_
));
130 void UDPSocketWin::Core::WatchForRead() {
131 // We grab an extra reference because there is an IO operation in progress.
132 // Balanced in ReadDelegate::OnObjectSignaled().
134 read_watcher_
.StartWatching(read_overlapped_
.hEvent
, &reader_
);
137 void UDPSocketWin::Core::WatchForWrite() {
138 // We grab an extra reference because there is an IO operation in progress.
139 // Balanced in WriteDelegate::OnObjectSignaled().
141 write_watcher_
.StartWatching(write_overlapped_
.hEvent
, &writer_
);
144 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object
) {
145 DCHECK_EQ(object
, core_
->read_overlapped_
.hEvent
);
147 core_
->socket_
->DidCompleteRead();
152 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object
) {
153 DCHECK_EQ(object
, core_
->write_overlapped_
.hEvent
);
155 core_
->socket_
->DidCompleteWrite();
160 //-----------------------------------------------------------------------------
162 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type
,
163 const RandIntCallback
& rand_int_cb
,
164 net::NetLog
* net_log
,
165 const net::NetLog::Source
& source
)
166 : socket_(INVALID_SOCKET
),
168 socket_options_(SOCKET_OPTION_MULTICAST_LOOP
),
169 multicast_interface_(0),
170 multicast_time_to_live_(1),
171 bind_type_(bind_type
),
172 rand_int_cb_(rand_int_cb
),
173 recv_from_address_(NULL
),
174 net_log_(BoundNetLog::Make(net_log
, NetLog::SOURCE_UDP_SOCKET
)) {
176 net_log_
.BeginEvent(NetLog::TYPE_SOCKET_ALIVE
,
177 source
.ToEventParametersCallback());
178 if (bind_type
== DatagramSocket::RANDOM_BIND
)
179 DCHECK(!rand_int_cb
.is_null());
182 UDPSocketWin::~UDPSocketWin() {
184 net_log_
.EndEvent(NetLog::TYPE_SOCKET_ALIVE
);
187 void UDPSocketWin::Close() {
188 DCHECK(CalledOnValidThread());
193 // Zero out any pending read/write callback state.
194 read_callback_
.Reset();
195 recv_from_address_
= NULL
;
196 write_callback_
.Reset();
198 base::TimeTicks start_time
= base::TimeTicks::Now();
199 closesocket(socket_
);
200 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
201 base::TimeTicks::Now() - start_time
);
202 socket_
= INVALID_SOCKET
;
209 int UDPSocketWin::GetPeerAddress(IPEndPoint
* address
) const {
210 DCHECK(CalledOnValidThread());
213 return ERR_SOCKET_NOT_CONNECTED
;
215 // TODO(szym): Simplify. http://crbug.com/126152
216 if (!remote_address_
.get()) {
217 SockaddrStorage storage
;
218 if (getpeername(socket_
, storage
.addr
, &storage
.addr_len
))
219 return MapSystemError(WSAGetLastError());
220 scoped_ptr
<IPEndPoint
> address(new IPEndPoint());
221 if (!address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
222 return ERR_ADDRESS_INVALID
;
223 remote_address_
.reset(address
.release());
226 *address
= *remote_address_
;
230 int UDPSocketWin::GetLocalAddress(IPEndPoint
* address
) const {
231 DCHECK(CalledOnValidThread());
234 return ERR_SOCKET_NOT_CONNECTED
;
236 // TODO(szym): Simplify. http://crbug.com/126152
237 if (!local_address_
.get()) {
238 SockaddrStorage storage
;
239 if (getsockname(socket_
, storage
.addr
, &storage
.addr_len
))
240 return MapSystemError(WSAGetLastError());
241 scoped_ptr
<IPEndPoint
> address(new IPEndPoint());
242 if (!address
->FromSockAddr(storage
.addr
, storage
.addr_len
))
243 return ERR_ADDRESS_INVALID
;
244 local_address_
.reset(address
.release());
245 net_log_
.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS
,
246 CreateNetLogUDPConnectCallback(local_address_
.get()));
249 *address
= *local_address_
;
253 int UDPSocketWin::Read(IOBuffer
* buf
,
255 const CompletionCallback
& callback
) {
256 return RecvFrom(buf
, buf_len
, NULL
, callback
);
259 int UDPSocketWin::RecvFrom(IOBuffer
* buf
,
262 const CompletionCallback
& callback
) {
263 DCHECK(CalledOnValidThread());
264 DCHECK_NE(INVALID_SOCKET
, socket_
);
265 DCHECK(read_callback_
.is_null());
266 DCHECK(!recv_from_address_
);
267 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
268 DCHECK_GT(buf_len
, 0);
270 int nread
= InternalRecvFrom(buf
, buf_len
, address
);
271 if (nread
!= ERR_IO_PENDING
)
274 read_callback_
= callback
;
275 recv_from_address_
= address
;
276 return ERR_IO_PENDING
;
279 int UDPSocketWin::Write(IOBuffer
* buf
,
281 const CompletionCallback
& callback
) {
282 return SendToOrWrite(buf
, buf_len
, NULL
, callback
);
285 int UDPSocketWin::SendTo(IOBuffer
* buf
,
287 const IPEndPoint
& address
,
288 const CompletionCallback
& callback
) {
289 return SendToOrWrite(buf
, buf_len
, &address
, callback
);
292 int UDPSocketWin::SendToOrWrite(IOBuffer
* buf
,
294 const IPEndPoint
* address
,
295 const CompletionCallback
& callback
) {
296 DCHECK(CalledOnValidThread());
297 DCHECK_NE(INVALID_SOCKET
, socket_
);
298 DCHECK(write_callback_
.is_null());
299 DCHECK(!callback
.is_null()); // Synchronous operation not supported.
300 DCHECK_GT(buf_len
, 0);
301 DCHECK(!send_to_address_
.get());
303 int nwrite
= InternalSendTo(buf
, buf_len
, address
);
304 if (nwrite
!= ERR_IO_PENDING
)
308 send_to_address_
.reset(new IPEndPoint(*address
));
309 write_callback_
= callback
;
310 return ERR_IO_PENDING
;
313 int UDPSocketWin::Connect(const IPEndPoint
& address
) {
314 net_log_
.BeginEvent(NetLog::TYPE_UDP_CONNECT
,
315 CreateNetLogUDPConnectCallback(&address
));
316 int rv
= InternalConnect(address
);
319 net_log_
.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT
, rv
);
323 int UDPSocketWin::InternalConnect(const IPEndPoint
& address
) {
324 DCHECK(!is_connected());
325 DCHECK(!remote_address_
.get());
326 int addr_family
= address
.GetSockAddrFamily();
327 int rv
= CreateSocket(addr_family
);
331 if (bind_type_
== DatagramSocket::RANDOM_BIND
) {
332 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
333 // representing INADDR_ANY or in6addr_any.
335 addr_family
== AF_INET
? kIPv4AddressSize
: kIPv6AddressSize
;
336 IPAddressNumber
addr_any(addr_size
);
337 rv
= RandomBind(addr_any
);
339 // else connect() does the DatagramSocket::DEFAULT_BIND
342 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv
);
347 SockaddrStorage storage
;
348 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
349 return ERR_ADDRESS_INVALID
;
351 rv
= connect(socket_
, storage
.addr
, storage
.addr_len
);
353 // Close() may change the last error. Map it beforehand.
354 int result
= MapSystemError(WSAGetLastError());
359 remote_address_
.reset(new IPEndPoint(address
));
363 int UDPSocketWin::Bind(const IPEndPoint
& address
) {
364 DCHECK(!is_connected());
365 int rv
= CreateSocket(address
.GetSockAddrFamily());
368 rv
= SetSocketOptions();
373 rv
= DoBind(address
);
378 local_address_
.reset();
382 int UDPSocketWin::CreateSocket(int addr_family
) {
383 addr_family_
= addr_family
;
384 socket_
= CreatePlatformSocket(addr_family_
, SOCK_DGRAM
, IPPROTO_UDP
);
385 if (socket_
== INVALID_SOCKET
)
386 return MapSystemError(WSAGetLastError());
387 core_
= new Core(this);
391 int UDPSocketWin::SetReceiveBufferSize(int32 size
) {
392 DCHECK(CalledOnValidThread());
393 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
394 reinterpret_cast<const char*>(&size
), sizeof(size
));
396 return MapSystemError(WSAGetLastError());
398 // According to documentation, setsockopt may succeed, but we need to check
399 // the results via getsockopt to be sure it works on Windows.
400 int32 actual_size
= 0;
401 int option_size
= sizeof(actual_size
);
402 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
403 reinterpret_cast<char*>(&actual_size
), &option_size
);
405 return MapSystemError(WSAGetLastError());
406 if (actual_size
>= size
)
408 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
409 actual_size
, 1000, 1000000, 50);
410 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE
;
413 int UDPSocketWin::SetSendBufferSize(int32 size
) {
414 DCHECK(CalledOnValidThread());
415 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
416 reinterpret_cast<const char*>(&size
), sizeof(size
));
418 return MapSystemError(WSAGetLastError());
419 // According to documentation, setsockopt may succeed, but we need to check
420 // the results via getsockopt to be sure it works on Windows.
421 int32 actual_size
= 0;
422 int option_size
= sizeof(actual_size
);
423 rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
424 reinterpret_cast<char*>(&actual_size
), &option_size
);
426 return MapSystemError(WSAGetLastError());
427 if (actual_size
>= size
)
429 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
430 actual_size
, 1000, 1000000, 50);
431 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE
;
434 void UDPSocketWin::AllowAddressReuse() {
435 DCHECK(CalledOnValidThread());
436 DCHECK(!is_connected());
438 socket_options_
|= SOCKET_OPTION_REUSE_ADDRESS
;
441 void UDPSocketWin::AllowBroadcast() {
442 DCHECK(CalledOnValidThread());
443 DCHECK(!is_connected());
445 socket_options_
|= SOCKET_OPTION_BROADCAST
;
448 void UDPSocketWin::DoReadCallback(int rv
) {
449 DCHECK_NE(rv
, ERR_IO_PENDING
);
450 DCHECK(!read_callback_
.is_null());
452 // since Run may result in Read being called, clear read_callback_ up front.
453 CompletionCallback c
= read_callback_
;
454 read_callback_
.Reset();
458 void UDPSocketWin::DoWriteCallback(int rv
) {
459 DCHECK_NE(rv
, ERR_IO_PENDING
);
460 DCHECK(!write_callback_
.is_null());
462 // since Run may result in Write being called, clear write_callback_ up front.
463 CompletionCallback c
= write_callback_
;
464 write_callback_
.Reset();
468 void UDPSocketWin::DidCompleteRead() {
469 DWORD num_bytes
, flags
;
470 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
471 &num_bytes
, FALSE
, &flags
);
472 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
473 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
475 if (recv_from_address_
&& result
>= 0) {
476 if (!ReceiveAddressToIPEndpoint(recv_from_address_
))
477 result
= ERR_ADDRESS_INVALID
;
479 LogRead(result
, core_
->read_iobuffer_
->data());
480 core_
->read_iobuffer_
= NULL
;
481 recv_from_address_
= NULL
;
482 DoReadCallback(result
);
485 void UDPSocketWin::LogRead(int result
, const char* bytes
) const {
487 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
491 if (net_log_
.IsLogging()) {
492 // Get address for logging, if |address| is NULL.
494 bool is_address_valid
= ReceiveAddressToIPEndpoint(&address
);
496 NetLog::TYPE_UDP_BYTES_RECEIVED
,
497 CreateNetLogUDPDataTranferCallback(
499 is_address_valid
? &address
: NULL
));
502 base::StatsCounter
read_bytes("udp.read_bytes");
503 read_bytes
.Add(result
);
506 void UDPSocketWin::DidCompleteWrite() {
507 DWORD num_bytes
, flags
;
508 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
509 &num_bytes
, FALSE
, &flags
);
510 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
511 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
512 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
514 send_to_address_
.reset();
515 core_
->write_iobuffer_
= NULL
;
516 DoWriteCallback(result
);
519 void UDPSocketWin::LogWrite(int result
,
521 const IPEndPoint
* address
) const {
523 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
527 if (net_log_
.IsLogging()) {
529 NetLog::TYPE_UDP_BYTES_SENT
,
530 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
533 base::StatsCounter
write_bytes("udp.write_bytes");
534 write_bytes
.Add(result
);
537 int UDPSocketWin::InternalRecvFrom(IOBuffer
* buf
, int buf_len
,
538 IPEndPoint
* address
) {
539 DCHECK(!core_
->read_iobuffer_
);
540 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
541 storage
.addr_len
= sizeof(storage
.addr_storage
);
544 read_buffer
.buf
= buf
->data();
545 read_buffer
.len
= buf_len
;
549 CHECK_NE(INVALID_SOCKET
, socket_
);
550 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
551 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
552 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
554 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
557 if (address
&& result
>= 0) {
558 if (!ReceiveAddressToIPEndpoint(address
))
559 result
= ERR_ADDRESS_INVALID
;
561 LogRead(result
, buf
->data());
565 int os_error
= WSAGetLastError();
566 if (os_error
!= WSA_IO_PENDING
) {
567 int result
= MapSystemError(os_error
);
568 LogRead(result
, NULL
);
572 core_
->WatchForRead();
573 core_
->read_iobuffer_
= buf
;
574 return ERR_IO_PENDING
;
577 int UDPSocketWin::InternalSendTo(IOBuffer
* buf
, int buf_len
,
578 const IPEndPoint
* address
) {
579 DCHECK(!core_
->write_iobuffer_
);
580 SockaddrStorage storage
;
581 struct sockaddr
* addr
= storage
.addr
;
585 storage
.addr_len
= 0;
587 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
588 int result
= ERR_ADDRESS_INVALID
;
589 LogWrite(result
, NULL
, NULL
);
595 write_buffer
.buf
= buf
->data();
596 write_buffer
.len
= buf_len
;
600 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
601 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
602 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
604 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
606 LogWrite(result
, buf
->data(), address
);
610 int os_error
= WSAGetLastError();
611 if (os_error
!= WSA_IO_PENDING
) {
612 int result
= MapSystemError(os_error
);
613 LogWrite(result
, NULL
, NULL
);
618 core_
->WatchForWrite();
619 core_
->write_iobuffer_
= buf
;
620 return ERR_IO_PENDING
;
623 int UDPSocketWin::SetSocketOptions() {
625 if (socket_options_
& SOCKET_OPTION_REUSE_ADDRESS
) {
626 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
627 reinterpret_cast<const char*>(&true_value
),
630 return MapSystemError(WSAGetLastError());
632 if (socket_options_
& SOCKET_OPTION_BROADCAST
) {
633 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
634 reinterpret_cast<const char*>(&true_value
),
637 return MapSystemError(WSAGetLastError());
639 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
642 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
644 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
645 int rv
= setsockopt(socket_
, protocol_level
, option
,
646 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
648 return MapSystemError(WSAGetLastError());
650 if (multicast_time_to_live_
!= 1) {
651 DWORD hops
= multicast_time_to_live_
;
653 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
655 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
656 int rv
= setsockopt(socket_
, protocol_level
, option
,
657 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
659 return MapSystemError(WSAGetLastError());
661 if (multicast_interface_
!= 0) {
662 switch (addr_family_
) {
665 address
.s_addr
= htonl(multicast_interface_
);
666 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
667 reinterpret_cast<const char*>(&address
),
670 return MapSystemError(WSAGetLastError());
674 uint32 interface_index
= multicast_interface_
;
675 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
676 reinterpret_cast<const char*>(&interface_index
),
677 sizeof(interface_index
));
679 return MapSystemError(WSAGetLastError());
683 NOTREACHED() << "Invalid address family";
684 return ERR_ADDRESS_INVALID
;
690 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
691 SockaddrStorage storage
;
692 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
693 return ERR_ADDRESS_INVALID
;
694 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
697 int last_error
= WSAGetLastError();
698 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
699 // Map some codes that are special to bind() separately.
700 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
701 // returned instead of WSAEADDRINUSE, depending on whether the socket
702 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
703 // conflicting socket is owned by a different user account. See the MSDN
704 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
705 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
706 return ERR_ADDRESS_IN_USE
;
707 return MapSystemError(last_error
);
710 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
711 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
713 for (int i
= 0; i
< kBindRetries
; ++i
) {
714 int rv
= DoBind(IPEndPoint(address
,
715 rand_int_cb_
.Run(kPortStart
, kPortEnd
)));
716 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
719 return DoBind(IPEndPoint(address
, 0));
722 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint
* address
) const {
723 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
724 return address
->FromSockAddr(storage
.addr
, storage
.addr_len
);
727 int UDPSocketWin::JoinGroup(
728 const IPAddressNumber
& group_address
) const {
729 DCHECK(CalledOnValidThread());
731 return ERR_SOCKET_NOT_CONNECTED
;
733 switch (group_address
.size()) {
734 case kIPv4AddressSize
: {
735 if (addr_family_
!= AF_INET
)
736 return ERR_ADDRESS_INVALID
;
738 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
739 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
740 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
741 reinterpret_cast<const char*>(&mreq
),
744 return MapSystemError(WSAGetLastError());
747 case kIPv6AddressSize
: {
748 if (addr_family_
!= AF_INET6
)
749 return ERR_ADDRESS_INVALID
;
751 mreq
.ipv6mr_interface
= multicast_interface_
;
752 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
753 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
754 reinterpret_cast<const char*>(&mreq
),
757 return MapSystemError(WSAGetLastError());
761 NOTREACHED() << "Invalid address family";
762 return ERR_ADDRESS_INVALID
;
766 int UDPSocketWin::LeaveGroup(
767 const IPAddressNumber
& group_address
) const {
768 DCHECK(CalledOnValidThread());
770 return ERR_SOCKET_NOT_CONNECTED
;
772 switch (group_address
.size()) {
773 case kIPv4AddressSize
: {
774 if (addr_family_
!= AF_INET
)
775 return ERR_ADDRESS_INVALID
;
777 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
778 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
779 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
780 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
782 return MapSystemError(WSAGetLastError());
785 case kIPv6AddressSize
: {
786 if (addr_family_
!= AF_INET6
)
787 return ERR_ADDRESS_INVALID
;
789 mreq
.ipv6mr_interface
= multicast_interface_
;
790 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
791 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
792 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
794 return MapSystemError(WSAGetLastError());
798 NOTREACHED() << "Invalid address family";
799 return ERR_ADDRESS_INVALID
;
803 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
804 DCHECK(CalledOnValidThread());
806 return ERR_SOCKET_IS_CONNECTED
;
807 multicast_interface_
= interface_index
;
811 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
812 DCHECK(CalledOnValidThread());
814 return ERR_SOCKET_IS_CONNECTED
;
816 if (time_to_live
< 0 || time_to_live
> 255)
817 return ERR_INVALID_ARGUMENT
;
818 multicast_time_to_live_
= time_to_live
;
822 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
823 DCHECK(CalledOnValidThread());
825 return ERR_SOCKET_IS_CONNECTED
;
828 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
830 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
834 // TODO(hubbe): Implement differentiated services for windows.
835 // Note: setsockopt(IP_TOS) does not work on windows XP and later.
836 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
837 return ERR_NOT_IMPLEMENTED
;
840 void UDPSocketWin::DetachFromThread() {
841 base::NonThreadSafe::DetachFromThread();