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 bool UDPSocketWin::SetReceiveBufferSize(int32 size
) {
392 DCHECK(CalledOnValidThread());
393 setsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
394 reinterpret_cast<const char*>(&size
), sizeof(size
));
395 // If the setsockopt fails, but the buffer is big enough, we will return
396 // success. It is not worth testing the return value as we still need to check
397 // via getsockopt anyway according to Windows documentation.
398 int32 actual_size
= 0;
399 int option_size
= sizeof(actual_size
);
400 int rv
= getsockopt(socket_
, SOL_SOCKET
, SO_RCVBUF
,
401 reinterpret_cast<char*>(&actual_size
), &option_size
);
404 if (actual_size
< size
) {
405 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketReceiveBufferUnchangeable",
406 actual_size
, 1000, 1000000, 50);
408 return actual_size
>= size
;
411 bool UDPSocketWin::SetSendBufferSize(int32 size
) {
412 DCHECK(CalledOnValidThread());
413 setsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
414 reinterpret_cast<const char*>(&size
), sizeof(size
));
415 // If the setsockopt fails, but the buffer is big enough, we will return
416 // success. It is not worth testing the return value as we still need to check
417 // via getsockopt anyway according to Windows documentation.
418 int32 actual_size
= 0;
419 int option_size
= sizeof(actual_size
);
420 int rv
= getsockopt(socket_
, SOL_SOCKET
, SO_SNDBUF
,
421 reinterpret_cast<char*>(&actual_size
), &option_size
);
424 if (actual_size
< size
) {
425 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
426 actual_size
, 1000, 1000000, 50);
428 return actual_size
>= size
;
431 void UDPSocketWin::AllowAddressReuse() {
432 DCHECK(CalledOnValidThread());
433 DCHECK(!is_connected());
435 socket_options_
|= SOCKET_OPTION_REUSE_ADDRESS
;
438 void UDPSocketWin::AllowBroadcast() {
439 DCHECK(CalledOnValidThread());
440 DCHECK(!is_connected());
442 socket_options_
|= SOCKET_OPTION_BROADCAST
;
445 void UDPSocketWin::DoReadCallback(int rv
) {
446 DCHECK_NE(rv
, ERR_IO_PENDING
);
447 DCHECK(!read_callback_
.is_null());
449 // since Run may result in Read being called, clear read_callback_ up front.
450 CompletionCallback c
= read_callback_
;
451 read_callback_
.Reset();
455 void UDPSocketWin::DoWriteCallback(int rv
) {
456 DCHECK_NE(rv
, ERR_IO_PENDING
);
457 DCHECK(!write_callback_
.is_null());
459 // since Run may result in Write being called, clear write_callback_ up front.
460 CompletionCallback c
= write_callback_
;
461 write_callback_
.Reset();
465 void UDPSocketWin::DidCompleteRead() {
466 DWORD num_bytes
, flags
;
467 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->read_overlapped_
,
468 &num_bytes
, FALSE
, &flags
);
469 WSAResetEvent(core_
->read_overlapped_
.hEvent
);
470 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
472 if (recv_from_address_
&& result
>= 0) {
473 if (!ReceiveAddressToIPEndpoint(recv_from_address_
))
474 result
= ERR_ADDRESS_INVALID
;
476 LogRead(result
, core_
->read_iobuffer_
->data());
477 core_
->read_iobuffer_
= NULL
;
478 recv_from_address_
= NULL
;
479 DoReadCallback(result
);
482 void UDPSocketWin::LogRead(int result
, const char* bytes
) const {
484 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR
, result
);
488 if (net_log_
.IsLogging()) {
489 // Get address for logging, if |address| is NULL.
491 bool is_address_valid
= ReceiveAddressToIPEndpoint(&address
);
493 NetLog::TYPE_UDP_BYTES_RECEIVED
,
494 CreateNetLogUDPDataTranferCallback(
496 is_address_valid
? &address
: NULL
));
499 base::StatsCounter
read_bytes("udp.read_bytes");
500 read_bytes
.Add(result
);
503 void UDPSocketWin::DidCompleteWrite() {
504 DWORD num_bytes
, flags
;
505 BOOL ok
= WSAGetOverlappedResult(socket_
, &core_
->write_overlapped_
,
506 &num_bytes
, FALSE
, &flags
);
507 WSAResetEvent(core_
->write_overlapped_
.hEvent
);
508 int result
= ok
? num_bytes
: MapSystemError(WSAGetLastError());
509 LogWrite(result
, core_
->write_iobuffer_
->data(), send_to_address_
.get());
511 send_to_address_
.reset();
512 core_
->write_iobuffer_
= NULL
;
513 DoWriteCallback(result
);
516 void UDPSocketWin::LogWrite(int result
,
518 const IPEndPoint
* address
) const {
520 net_log_
.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR
, result
);
524 if (net_log_
.IsLogging()) {
526 NetLog::TYPE_UDP_BYTES_SENT
,
527 CreateNetLogUDPDataTranferCallback(result
, bytes
, address
));
530 base::StatsCounter
write_bytes("udp.write_bytes");
531 write_bytes
.Add(result
);
534 int UDPSocketWin::InternalRecvFrom(IOBuffer
* buf
, int buf_len
,
535 IPEndPoint
* address
) {
536 DCHECK(!core_
->read_iobuffer_
);
537 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
538 storage
.addr_len
= sizeof(storage
.addr_storage
);
541 read_buffer
.buf
= buf
->data();
542 read_buffer
.len
= buf_len
;
546 CHECK_NE(INVALID_SOCKET
, socket_
);
547 AssertEventNotSignaled(core_
->read_overlapped_
.hEvent
);
548 int rv
= WSARecvFrom(socket_
, &read_buffer
, 1, &num
, &flags
, storage
.addr
,
549 &storage
.addr_len
, &core_
->read_overlapped_
, NULL
);
551 if (ResetEventIfSignaled(core_
->read_overlapped_
.hEvent
)) {
554 if (address
&& result
>= 0) {
555 if (!ReceiveAddressToIPEndpoint(address
))
556 result
= ERR_ADDRESS_INVALID
;
558 LogRead(result
, buf
->data());
562 int os_error
= WSAGetLastError();
563 if (os_error
!= WSA_IO_PENDING
) {
564 int result
= MapSystemError(os_error
);
565 LogRead(result
, NULL
);
569 core_
->WatchForRead();
570 core_
->read_iobuffer_
= buf
;
571 return ERR_IO_PENDING
;
574 int UDPSocketWin::InternalSendTo(IOBuffer
* buf
, int buf_len
,
575 const IPEndPoint
* address
) {
576 DCHECK(!core_
->write_iobuffer_
);
577 SockaddrStorage storage
;
578 struct sockaddr
* addr
= storage
.addr
;
582 storage
.addr_len
= 0;
584 if (!address
->ToSockAddr(addr
, &storage
.addr_len
)) {
585 int result
= ERR_ADDRESS_INVALID
;
586 LogWrite(result
, NULL
, NULL
);
592 write_buffer
.buf
= buf
->data();
593 write_buffer
.len
= buf_len
;
597 AssertEventNotSignaled(core_
->write_overlapped_
.hEvent
);
598 int rv
= WSASendTo(socket_
, &write_buffer
, 1, &num
, flags
,
599 addr
, storage
.addr_len
, &core_
->write_overlapped_
, NULL
);
601 if (ResetEventIfSignaled(core_
->write_overlapped_
.hEvent
)) {
603 LogWrite(result
, buf
->data(), address
);
607 int os_error
= WSAGetLastError();
608 if (os_error
!= WSA_IO_PENDING
) {
609 int result
= MapSystemError(os_error
);
610 LogWrite(result
, NULL
, NULL
);
615 core_
->WatchForWrite();
616 core_
->write_iobuffer_
= buf
;
617 return ERR_IO_PENDING
;
620 int UDPSocketWin::SetSocketOptions() {
622 if (socket_options_
& SOCKET_OPTION_REUSE_ADDRESS
) {
623 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_REUSEADDR
,
624 reinterpret_cast<const char*>(&true_value
),
627 return MapSystemError(WSAGetLastError());
629 if (socket_options_
& SOCKET_OPTION_BROADCAST
) {
630 int rv
= setsockopt(socket_
, SOL_SOCKET
, SO_BROADCAST
,
631 reinterpret_cast<const char*>(&true_value
),
634 return MapSystemError(WSAGetLastError());
636 if (!(socket_options_
& SOCKET_OPTION_MULTICAST_LOOP
)) {
639 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
641 addr_family_
== AF_INET
? IP_MULTICAST_LOOP
: IPV6_MULTICAST_LOOP
;
642 int rv
= setsockopt(socket_
, protocol_level
, option
,
643 reinterpret_cast<const char*>(&loop
), sizeof(loop
));
645 return MapSystemError(WSAGetLastError());
647 if (multicast_time_to_live_
!= 1) {
648 DWORD hops
= multicast_time_to_live_
;
650 addr_family_
== AF_INET
? IPPROTO_IP
: IPPROTO_IPV6
;
652 addr_family_
== AF_INET
? IP_MULTICAST_TTL
: IPV6_MULTICAST_HOPS
;
653 int rv
= setsockopt(socket_
, protocol_level
, option
,
654 reinterpret_cast<const char*>(&hops
), sizeof(hops
));
656 return MapSystemError(WSAGetLastError());
658 if (multicast_interface_
!= 0) {
659 switch (addr_family_
) {
662 address
.s_addr
= htonl(multicast_interface_
);
663 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_MULTICAST_IF
,
664 reinterpret_cast<const char*>(&address
),
667 return MapSystemError(WSAGetLastError());
671 uint32 interface_index
= multicast_interface_
;
672 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_MULTICAST_IF
,
673 reinterpret_cast<const char*>(&interface_index
),
674 sizeof(interface_index
));
676 return MapSystemError(WSAGetLastError());
680 NOTREACHED() << "Invalid address family";
681 return ERR_ADDRESS_INVALID
;
687 int UDPSocketWin::DoBind(const IPEndPoint
& address
) {
688 SockaddrStorage storage
;
689 if (!address
.ToSockAddr(storage
.addr
, &storage
.addr_len
))
690 return ERR_ADDRESS_INVALID
;
691 int rv
= bind(socket_
, storage
.addr
, storage
.addr_len
);
694 int last_error
= WSAGetLastError();
695 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error
);
696 // Map some codes that are special to bind() separately.
697 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
698 // returned instead of WSAEADDRINUSE, depending on whether the socket
699 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
700 // conflicting socket is owned by a different user account. See the MSDN
701 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
702 if (last_error
== WSAEACCES
|| last_error
== WSAEADDRNOTAVAIL
)
703 return ERR_ADDRESS_IN_USE
;
704 return MapSystemError(last_error
);
707 int UDPSocketWin::RandomBind(const IPAddressNumber
& address
) {
708 DCHECK(bind_type_
== DatagramSocket::RANDOM_BIND
&& !rand_int_cb_
.is_null());
710 for (int i
= 0; i
< kBindRetries
; ++i
) {
711 int rv
= DoBind(IPEndPoint(address
,
712 rand_int_cb_
.Run(kPortStart
, kPortEnd
)));
713 if (rv
== OK
|| rv
!= ERR_ADDRESS_IN_USE
)
716 return DoBind(IPEndPoint(address
, 0));
719 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint
* address
) const {
720 SockaddrStorage
& storage
= core_
->recv_addr_storage_
;
721 return address
->FromSockAddr(storage
.addr
, storage
.addr_len
);
724 int UDPSocketWin::JoinGroup(
725 const IPAddressNumber
& group_address
) const {
726 DCHECK(CalledOnValidThread());
728 return ERR_SOCKET_NOT_CONNECTED
;
730 switch (group_address
.size()) {
731 case kIPv4AddressSize
: {
732 if (addr_family_
!= AF_INET
)
733 return ERR_ADDRESS_INVALID
;
735 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
736 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
737 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
,
738 reinterpret_cast<const char*>(&mreq
),
741 return MapSystemError(WSAGetLastError());
744 case kIPv6AddressSize
: {
745 if (addr_family_
!= AF_INET6
)
746 return ERR_ADDRESS_INVALID
;
748 mreq
.ipv6mr_interface
= multicast_interface_
;
749 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
750 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IPV6_ADD_MEMBERSHIP
,
751 reinterpret_cast<const char*>(&mreq
),
754 return MapSystemError(WSAGetLastError());
758 NOTREACHED() << "Invalid address family";
759 return ERR_ADDRESS_INVALID
;
763 int UDPSocketWin::LeaveGroup(
764 const IPAddressNumber
& group_address
) const {
765 DCHECK(CalledOnValidThread());
767 return ERR_SOCKET_NOT_CONNECTED
;
769 switch (group_address
.size()) {
770 case kIPv4AddressSize
: {
771 if (addr_family_
!= AF_INET
)
772 return ERR_ADDRESS_INVALID
;
774 mreq
.imr_interface
.s_addr
= htonl(multicast_interface_
);
775 memcpy(&mreq
.imr_multiaddr
, &group_address
[0], kIPv4AddressSize
);
776 int rv
= setsockopt(socket_
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
,
777 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
779 return MapSystemError(WSAGetLastError());
782 case kIPv6AddressSize
: {
783 if (addr_family_
!= AF_INET6
)
784 return ERR_ADDRESS_INVALID
;
786 mreq
.ipv6mr_interface
= multicast_interface_
;
787 memcpy(&mreq
.ipv6mr_multiaddr
, &group_address
[0], kIPv6AddressSize
);
788 int rv
= setsockopt(socket_
, IPPROTO_IPV6
, IP_DROP_MEMBERSHIP
,
789 reinterpret_cast<const char*>(&mreq
), sizeof(mreq
));
791 return MapSystemError(WSAGetLastError());
795 NOTREACHED() << "Invalid address family";
796 return ERR_ADDRESS_INVALID
;
800 int UDPSocketWin::SetMulticastInterface(uint32 interface_index
) {
801 DCHECK(CalledOnValidThread());
803 return ERR_SOCKET_IS_CONNECTED
;
804 multicast_interface_
= interface_index
;
808 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live
) {
809 DCHECK(CalledOnValidThread());
811 return ERR_SOCKET_IS_CONNECTED
;
813 if (time_to_live
< 0 || time_to_live
> 255)
814 return ERR_INVALID_ARGUMENT
;
815 multicast_time_to_live_
= time_to_live
;
819 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback
) {
820 DCHECK(CalledOnValidThread());
822 return ERR_SOCKET_IS_CONNECTED
;
825 socket_options_
|= SOCKET_OPTION_MULTICAST_LOOP
;
827 socket_options_
&= ~SOCKET_OPTION_MULTICAST_LOOP
;
831 // TODO(hubbe): Implement differentiated services for windows.
832 // Note: setsockopt(IP_TOS) does not work on windows XP and later.
833 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp
) {
834 return ERR_NOT_IMPLEMENTED
;
837 void UDPSocketWin::DetachFromThread() {
838 base::NonThreadSafe::DetachFromThread();