Chromecast Android buildfix: rework CommandLine initialization logic.
[chromium-blink-merge.git] / net / udp / udp_socket_win.cc
blobbb48c7dd7ed9c1c8d92a7eb3b885a20c8d4041a5
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"
7 #include <mstcpip.h>
9 #include "base/callback.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/metrics/histogram.h"
14 #include "base/metrics/sparse_histogram.h"
15 #include "base/metrics/stats_counters.h"
16 #include "base/profiler/scoped_profile.h"
17 #include "base/rand_util.h"
18 #include "net/base/io_buffer.h"
19 #include "net/base/ip_endpoint.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_log.h"
22 #include "net/base/net_util.h"
23 #include "net/base/winsock_init.h"
24 #include "net/base/winsock_util.h"
25 #include "net/socket/socket_descriptor.h"
26 #include "net/udp/udp_net_log_parameters.h"
28 namespace {
30 const int kBindRetries = 10;
31 const int kPortStart = 1024;
32 const int kPortEnd = 65535;
34 } // namespace
36 namespace net {
38 // This class encapsulates all the state that has to be preserved as long as
39 // there is a network IO operation in progress. If the owner UDPSocketWin
40 // is destroyed while an operation is in progress, the Core is detached and it
41 // lives until the operation completes and the OS doesn't reference any resource
42 // declared on this class anymore.
43 class UDPSocketWin::Core : public base::RefCounted<Core> {
44 public:
45 explicit Core(UDPSocketWin* socket);
47 // Start watching for the end of a read or write operation.
48 void WatchForRead();
49 void WatchForWrite();
51 // The UDPSocketWin is going away.
52 void Detach() { socket_ = NULL; }
54 // The separate OVERLAPPED variables for asynchronous operation.
55 OVERLAPPED read_overlapped_;
56 OVERLAPPED write_overlapped_;
58 // The buffers used in Read() and Write().
59 scoped_refptr<IOBuffer> read_iobuffer_;
60 scoped_refptr<IOBuffer> write_iobuffer_;
62 // The address storage passed to WSARecvFrom().
63 SockaddrStorage recv_addr_storage_;
65 private:
66 friend class base::RefCounted<Core>;
68 class ReadDelegate : public base::win::ObjectWatcher::Delegate {
69 public:
70 explicit ReadDelegate(Core* core) : core_(core) {}
71 virtual ~ReadDelegate() {}
73 // base::ObjectWatcher::Delegate methods:
74 virtual void OnObjectSignaled(HANDLE object);
76 private:
77 Core* const core_;
80 class WriteDelegate : public base::win::ObjectWatcher::Delegate {
81 public:
82 explicit WriteDelegate(Core* core) : core_(core) {}
83 virtual ~WriteDelegate() {}
85 // base::ObjectWatcher::Delegate methods:
86 virtual void OnObjectSignaled(HANDLE object);
88 private:
89 Core* const core_;
92 ~Core();
94 // The socket that created this object.
95 UDPSocketWin* socket_;
97 // |reader_| handles the signals from |read_watcher_|.
98 ReadDelegate reader_;
99 // |writer_| handles the signals from |write_watcher_|.
100 WriteDelegate writer_;
102 // |read_watcher_| watches for events from Read().
103 base::win::ObjectWatcher read_watcher_;
104 // |write_watcher_| watches for events from Write();
105 base::win::ObjectWatcher write_watcher_;
107 DISALLOW_COPY_AND_ASSIGN(Core);
110 UDPSocketWin::Core::Core(UDPSocketWin* socket)
111 : socket_(socket),
112 reader_(this),
113 writer_(this) {
114 memset(&read_overlapped_, 0, sizeof(read_overlapped_));
115 memset(&write_overlapped_, 0, sizeof(write_overlapped_));
117 read_overlapped_.hEvent = WSACreateEvent();
118 write_overlapped_.hEvent = WSACreateEvent();
121 UDPSocketWin::Core::~Core() {
122 // Make sure the message loop is not watching this object anymore.
123 read_watcher_.StopWatching();
124 write_watcher_.StopWatching();
126 WSACloseEvent(read_overlapped_.hEvent);
127 memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
128 WSACloseEvent(write_overlapped_.hEvent);
129 memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
132 void UDPSocketWin::Core::WatchForRead() {
133 // We grab an extra reference because there is an IO operation in progress.
134 // Balanced in ReadDelegate::OnObjectSignaled().
135 AddRef();
136 read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
139 void UDPSocketWin::Core::WatchForWrite() {
140 // We grab an extra reference because there is an IO operation in progress.
141 // Balanced in WriteDelegate::OnObjectSignaled().
142 AddRef();
143 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
146 void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
147 // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed.
148 tracked_objects::ScopedProfile tracking_profile(
149 FROM_HERE_WITH_EXPLICIT_FUNCTION(
150 "UDPSocketWin_Core_ReadDelegate_OnObjectSignaled"));
152 DCHECK_EQ(object, core_->read_overlapped_.hEvent);
153 if (core_->socket_)
154 core_->socket_->DidCompleteRead();
156 core_->Release();
159 void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) {
160 // TODO(vadimt): Remove ScopedProfile below once crbug.com/418183 is fixed.
161 tracked_objects::ScopedProfile tracking_profile(
162 FROM_HERE_WITH_EXPLICIT_FUNCTION(
163 "UDPSocketWin_Core_WriteDelegate_OnObjectSignaled"));
165 DCHECK_EQ(object, core_->write_overlapped_.hEvent);
166 if (core_->socket_)
167 core_->socket_->DidCompleteWrite();
169 core_->Release();
171 //-----------------------------------------------------------------------------
173 QwaveAPI::QwaveAPI() : qwave_supported_(false) {
174 HMODULE qwave = LoadLibrary(L"qwave.dll");
175 if (!qwave)
176 return;
177 create_handle_func_ =
178 (CreateHandleFn)GetProcAddress(qwave, "QOSCreateHandle");
179 close_handle_func_ =
180 (CloseHandleFn)GetProcAddress(qwave, "QOSCloseHandle");
181 add_socket_to_flow_func_ =
182 (AddSocketToFlowFn)GetProcAddress(qwave, "QOSAddSocketToFlow");
183 remove_socket_from_flow_func_ =
184 (RemoveSocketFromFlowFn)GetProcAddress(qwave, "QOSRemoveSocketFromFlow");
185 set_flow_func_ = (SetFlowFn)GetProcAddress(qwave, "QOSSetFlow");
187 if (create_handle_func_ && close_handle_func_ &&
188 add_socket_to_flow_func_ && remove_socket_from_flow_func_ &&
189 set_flow_func_) {
190 qwave_supported_ = true;
194 QwaveAPI& QwaveAPI::Get() {
195 static base::LazyInstance<QwaveAPI>::Leaky lazy_qwave =
196 LAZY_INSTANCE_INITIALIZER;
197 return lazy_qwave.Get();
200 bool QwaveAPI::qwave_supported() const {
201 return qwave_supported_;
203 BOOL QwaveAPI::CreateHandle(PQOS_VERSION version, PHANDLE handle) {
204 return create_handle_func_(version, handle);
206 BOOL QwaveAPI::CloseHandle(HANDLE handle) {
207 return close_handle_func_(handle);
210 BOOL QwaveAPI::AddSocketToFlow(HANDLE handle,
211 SOCKET socket,
212 PSOCKADDR addr,
213 QOS_TRAFFIC_TYPE traffic_type,
214 DWORD flags,
215 PQOS_FLOWID flow_id) {
216 return add_socket_to_flow_func_(handle,
217 socket,
218 addr,
219 traffic_type,
220 flags,
221 flow_id);
224 BOOL QwaveAPI::RemoveSocketFromFlow(HANDLE handle,
225 SOCKET socket,
226 QOS_FLOWID flow_id,
227 DWORD reserved) {
228 return remove_socket_from_flow_func_(handle, socket, flow_id, reserved);
231 BOOL QwaveAPI::SetFlow(HANDLE handle,
232 QOS_FLOWID flow_id,
233 QOS_SET_FLOW op,
234 ULONG size,
235 PVOID data,
236 DWORD reserved,
237 LPOVERLAPPED overlapped) {
238 return set_flow_func_(handle,
239 flow_id,
241 size,
242 data,
243 reserved,
244 overlapped);
248 //-----------------------------------------------------------------------------
250 UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
251 const RandIntCallback& rand_int_cb,
252 net::NetLog* net_log,
253 const net::NetLog::Source& source)
254 : socket_(INVALID_SOCKET),
255 addr_family_(0),
256 socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
257 multicast_interface_(0),
258 multicast_time_to_live_(1),
259 bind_type_(bind_type),
260 rand_int_cb_(rand_int_cb),
261 recv_from_address_(NULL),
262 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)),
263 qos_handle_(NULL),
264 qos_flow_id_(0) {
265 EnsureWinsockInit();
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() {
273 Close();
274 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
277 void UDPSocketWin::Close() {
278 DCHECK(CalledOnValidThread());
280 if (!is_connected())
281 return;
283 if (qos_handle_) {
284 QwaveAPI::Get().CloseHandle(qos_handle_);
287 // Zero out any pending read/write callback state.
288 read_callback_.Reset();
289 recv_from_address_ = NULL;
290 write_callback_.Reset();
292 base::TimeTicks start_time = base::TimeTicks::Now();
293 closesocket(socket_);
294 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
295 base::TimeTicks::Now() - start_time);
296 socket_ = INVALID_SOCKET;
297 addr_family_ = 0;
299 core_->Detach();
300 core_ = NULL;
303 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
304 DCHECK(CalledOnValidThread());
305 DCHECK(address);
306 if (!is_connected())
307 return ERR_SOCKET_NOT_CONNECTED;
309 // TODO(szym): Simplify. http://crbug.com/126152
310 if (!remote_address_.get()) {
311 SockaddrStorage storage;
312 if (getpeername(socket_, storage.addr, &storage.addr_len))
313 return MapSystemError(WSAGetLastError());
314 scoped_ptr<IPEndPoint> address(new IPEndPoint());
315 if (!address->FromSockAddr(storage.addr, storage.addr_len))
316 return ERR_ADDRESS_INVALID;
317 remote_address_.reset(address.release());
320 *address = *remote_address_;
321 return OK;
324 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
325 DCHECK(CalledOnValidThread());
326 DCHECK(address);
327 if (!is_connected())
328 return ERR_SOCKET_NOT_CONNECTED;
330 // TODO(szym): Simplify. http://crbug.com/126152
331 if (!local_address_.get()) {
332 SockaddrStorage storage;
333 if (getsockname(socket_, storage.addr, &storage.addr_len))
334 return MapSystemError(WSAGetLastError());
335 scoped_ptr<IPEndPoint> address(new IPEndPoint());
336 if (!address->FromSockAddr(storage.addr, storage.addr_len))
337 return ERR_ADDRESS_INVALID;
338 local_address_.reset(address.release());
339 net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
340 CreateNetLogUDPConnectCallback(local_address_.get()));
343 *address = *local_address_;
344 return OK;
347 int UDPSocketWin::Read(IOBuffer* buf,
348 int buf_len,
349 const CompletionCallback& callback) {
350 return RecvFrom(buf, buf_len, NULL, callback);
353 int UDPSocketWin::RecvFrom(IOBuffer* buf,
354 int buf_len,
355 IPEndPoint* address,
356 const CompletionCallback& callback) {
357 DCHECK(CalledOnValidThread());
358 DCHECK_NE(INVALID_SOCKET, socket_);
359 CHECK(read_callback_.is_null());
360 DCHECK(!recv_from_address_);
361 DCHECK(!callback.is_null()); // Synchronous operation not supported.
362 DCHECK_GT(buf_len, 0);
364 int nread = InternalRecvFrom(buf, buf_len, address);
365 if (nread != ERR_IO_PENDING)
366 return nread;
368 read_callback_ = callback;
369 recv_from_address_ = address;
370 return ERR_IO_PENDING;
373 int UDPSocketWin::Write(IOBuffer* buf,
374 int buf_len,
375 const CompletionCallback& callback) {
376 return SendToOrWrite(buf, buf_len, NULL, callback);
379 int UDPSocketWin::SendTo(IOBuffer* buf,
380 int buf_len,
381 const IPEndPoint& address,
382 const CompletionCallback& callback) {
383 return SendToOrWrite(buf, buf_len, &address, callback);
386 int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
387 int buf_len,
388 const IPEndPoint* address,
389 const CompletionCallback& callback) {
390 DCHECK(CalledOnValidThread());
391 DCHECK_NE(INVALID_SOCKET, socket_);
392 CHECK(write_callback_.is_null());
393 DCHECK(!callback.is_null()); // Synchronous operation not supported.
394 DCHECK_GT(buf_len, 0);
395 DCHECK(!send_to_address_.get());
397 int nwrite = InternalSendTo(buf, buf_len, address);
398 if (nwrite != ERR_IO_PENDING)
399 return nwrite;
401 if (address)
402 send_to_address_.reset(new IPEndPoint(*address));
403 write_callback_ = callback;
404 return ERR_IO_PENDING;
407 int UDPSocketWin::Connect(const IPEndPoint& address) {
408 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
409 CreateNetLogUDPConnectCallback(&address));
410 int rv = InternalConnect(address);
411 if (rv != OK)
412 Close();
413 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
414 return rv;
417 int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
418 DCHECK(!is_connected());
419 DCHECK(!remote_address_.get());
420 int addr_family = address.GetSockAddrFamily();
421 int rv = CreateSocket(addr_family);
422 if (rv < 0)
423 return rv;
425 if (bind_type_ == DatagramSocket::RANDOM_BIND) {
426 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
427 // representing INADDR_ANY or in6addr_any.
428 size_t addr_size =
429 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize;
430 IPAddressNumber addr_any(addr_size);
431 rv = RandomBind(addr_any);
433 // else connect() does the DatagramSocket::DEFAULT_BIND
435 if (rv < 0) {
436 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv);
437 Close();
438 return rv;
441 SockaddrStorage storage;
442 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
443 return ERR_ADDRESS_INVALID;
445 rv = connect(socket_, storage.addr, storage.addr_len);
446 if (rv < 0) {
447 // Close() may change the last error. Map it beforehand.
448 int result = MapSystemError(WSAGetLastError());
449 Close();
450 return result;
453 remote_address_.reset(new IPEndPoint(address));
454 return rv;
457 int UDPSocketWin::Bind(const IPEndPoint& address) {
458 DCHECK(!is_connected());
459 int rv = CreateSocket(address.GetSockAddrFamily());
460 if (rv < 0)
461 return rv;
462 rv = SetSocketOptions();
463 if (rv < 0) {
464 Close();
465 return rv;
467 rv = DoBind(address);
468 if (rv < 0) {
469 Close();
470 return rv;
472 local_address_.reset();
473 return rv;
476 int UDPSocketWin::CreateSocket(int addr_family) {
477 addr_family_ = addr_family;
478 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
479 if (socket_ == INVALID_SOCKET)
480 return MapSystemError(WSAGetLastError());
481 core_ = new Core(this);
482 return OK;
485 int UDPSocketWin::SetReceiveBufferSize(int32 size) {
486 DCHECK(CalledOnValidThread());
487 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
488 reinterpret_cast<const char*>(&size), sizeof(size));
489 if (rv != 0)
490 return MapSystemError(WSAGetLastError());
492 // According to documentation, setsockopt may succeed, but we need to check
493 // the results via getsockopt to be sure it works on Windows.
494 int32 actual_size = 0;
495 int option_size = sizeof(actual_size);
496 rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
497 reinterpret_cast<char*>(&actual_size), &option_size);
498 if (rv != 0)
499 return MapSystemError(WSAGetLastError());
500 if (actual_size >= size)
501 return OK;
502 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer",
503 actual_size, 1000, 1000000, 50);
504 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE;
507 int UDPSocketWin::SetSendBufferSize(int32 size) {
508 DCHECK(CalledOnValidThread());
509 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
510 reinterpret_cast<const char*>(&size), sizeof(size));
511 if (rv != 0)
512 return MapSystemError(WSAGetLastError());
513 // According to documentation, setsockopt may succeed, but we need to check
514 // the results via getsockopt to be sure it works on Windows.
515 int32 actual_size = 0;
516 int option_size = sizeof(actual_size);
517 rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
518 reinterpret_cast<char*>(&actual_size), &option_size);
519 if (rv != 0)
520 return MapSystemError(WSAGetLastError());
521 if (actual_size >= size)
522 return OK;
523 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
524 actual_size, 1000, 1000000, 50);
525 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE;
528 void UDPSocketWin::AllowAddressReuse() {
529 DCHECK(CalledOnValidThread());
530 DCHECK(!is_connected());
532 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
535 void UDPSocketWin::AllowBroadcast() {
536 DCHECK(CalledOnValidThread());
537 DCHECK(!is_connected());
539 socket_options_ |= SOCKET_OPTION_BROADCAST;
542 void UDPSocketWin::DoReadCallback(int rv) {
543 DCHECK_NE(rv, ERR_IO_PENDING);
544 DCHECK(!read_callback_.is_null());
546 // since Run may result in Read being called, clear read_callback_ up front.
547 CompletionCallback c = read_callback_;
548 read_callback_.Reset();
549 c.Run(rv);
552 void UDPSocketWin::DoWriteCallback(int rv) {
553 DCHECK_NE(rv, ERR_IO_PENDING);
554 DCHECK(!write_callback_.is_null());
556 // since Run may result in Write being called, clear write_callback_ up front.
557 CompletionCallback c = write_callback_;
558 write_callback_.Reset();
559 c.Run(rv);
562 void UDPSocketWin::DidCompleteRead() {
563 DWORD num_bytes, flags;
564 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
565 &num_bytes, FALSE, &flags);
566 WSAResetEvent(core_->read_overlapped_.hEvent);
567 int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
568 // Convert address.
569 if (recv_from_address_ && result >= 0) {
570 if (!ReceiveAddressToIPEndpoint(recv_from_address_))
571 result = ERR_ADDRESS_INVALID;
573 LogRead(result, core_->read_iobuffer_->data());
574 core_->read_iobuffer_ = NULL;
575 recv_from_address_ = NULL;
576 DoReadCallback(result);
579 void UDPSocketWin::LogRead(int result, const char* bytes) const {
580 if (result < 0) {
581 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
582 return;
585 if (net_log_.IsLogging()) {
586 // Get address for logging, if |address| is NULL.
587 IPEndPoint address;
588 bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
589 net_log_.AddEvent(
590 NetLog::TYPE_UDP_BYTES_RECEIVED,
591 CreateNetLogUDPDataTranferCallback(
592 result, bytes,
593 is_address_valid ? &address : NULL));
596 base::StatsCounter read_bytes("udp.read_bytes");
597 read_bytes.Add(result);
600 void UDPSocketWin::DidCompleteWrite() {
601 DWORD num_bytes, flags;
602 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
603 &num_bytes, FALSE, &flags);
604 WSAResetEvent(core_->write_overlapped_.hEvent);
605 int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
606 LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
608 send_to_address_.reset();
609 core_->write_iobuffer_ = NULL;
610 DoWriteCallback(result);
613 void UDPSocketWin::LogWrite(int result,
614 const char* bytes,
615 const IPEndPoint* address) const {
616 if (result < 0) {
617 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
618 return;
621 if (net_log_.IsLogging()) {
622 net_log_.AddEvent(
623 NetLog::TYPE_UDP_BYTES_SENT,
624 CreateNetLogUDPDataTranferCallback(result, bytes, address));
627 base::StatsCounter write_bytes("udp.write_bytes");
628 write_bytes.Add(result);
631 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
632 IPEndPoint* address) {
633 DCHECK(!core_->read_iobuffer_);
634 SockaddrStorage& storage = core_->recv_addr_storage_;
635 storage.addr_len = sizeof(storage.addr_storage);
637 WSABUF read_buffer;
638 read_buffer.buf = buf->data();
639 read_buffer.len = buf_len;
641 DWORD flags = 0;
642 DWORD num;
643 CHECK_NE(INVALID_SOCKET, socket_);
644 AssertEventNotSignaled(core_->read_overlapped_.hEvent);
645 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
646 &storage.addr_len, &core_->read_overlapped_, NULL);
647 if (rv == 0) {
648 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
649 int result = num;
650 // Convert address.
651 if (address && result >= 0) {
652 if (!ReceiveAddressToIPEndpoint(address))
653 result = ERR_ADDRESS_INVALID;
655 LogRead(result, buf->data());
656 return result;
658 } else {
659 int os_error = WSAGetLastError();
660 if (os_error != WSA_IO_PENDING) {
661 int result = MapSystemError(os_error);
662 LogRead(result, NULL);
663 return result;
666 core_->WatchForRead();
667 core_->read_iobuffer_ = buf;
668 return ERR_IO_PENDING;
671 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
672 const IPEndPoint* address) {
673 DCHECK(!core_->write_iobuffer_);
674 SockaddrStorage storage;
675 struct sockaddr* addr = storage.addr;
676 // Convert address.
677 if (!address) {
678 addr = NULL;
679 storage.addr_len = 0;
680 } else {
681 if (!address->ToSockAddr(addr, &storage.addr_len)) {
682 int result = ERR_ADDRESS_INVALID;
683 LogWrite(result, NULL, NULL);
684 return result;
688 WSABUF write_buffer;
689 write_buffer.buf = buf->data();
690 write_buffer.len = buf_len;
692 DWORD flags = 0;
693 DWORD num;
694 AssertEventNotSignaled(core_->write_overlapped_.hEvent);
695 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
696 addr, storage.addr_len, &core_->write_overlapped_, NULL);
697 if (rv == 0) {
698 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
699 int result = num;
700 LogWrite(result, buf->data(), address);
701 return result;
703 } else {
704 int os_error = WSAGetLastError();
705 if (os_error != WSA_IO_PENDING) {
706 int result = MapSystemError(os_error);
707 LogWrite(result, NULL, NULL);
708 return result;
712 core_->WatchForWrite();
713 core_->write_iobuffer_ = buf;
714 return ERR_IO_PENDING;
717 int UDPSocketWin::SetSocketOptions() {
718 BOOL true_value = 1;
719 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
720 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
721 reinterpret_cast<const char*>(&true_value),
722 sizeof(true_value));
723 if (rv < 0)
724 return MapSystemError(WSAGetLastError());
726 if (socket_options_ & SOCKET_OPTION_BROADCAST) {
727 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
728 reinterpret_cast<const char*>(&true_value),
729 sizeof(true_value));
730 if (rv < 0)
731 return MapSystemError(WSAGetLastError());
733 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
734 DWORD loop = 0;
735 int protocol_level =
736 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
737 int option =
738 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
739 int rv = setsockopt(socket_, protocol_level, option,
740 reinterpret_cast<const char*>(&loop), sizeof(loop));
741 if (rv < 0)
742 return MapSystemError(WSAGetLastError());
744 if (multicast_time_to_live_ != 1) {
745 DWORD hops = multicast_time_to_live_;
746 int protocol_level =
747 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
748 int option =
749 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
750 int rv = setsockopt(socket_, protocol_level, option,
751 reinterpret_cast<const char*>(&hops), sizeof(hops));
752 if (rv < 0)
753 return MapSystemError(WSAGetLastError());
755 if (multicast_interface_ != 0) {
756 switch (addr_family_) {
757 case AF_INET: {
758 in_addr address;
759 address.s_addr = htonl(multicast_interface_);
760 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
761 reinterpret_cast<const char*>(&address),
762 sizeof(address));
763 if (rv)
764 return MapSystemError(WSAGetLastError());
765 break;
767 case AF_INET6: {
768 uint32 interface_index = multicast_interface_;
769 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
770 reinterpret_cast<const char*>(&interface_index),
771 sizeof(interface_index));
772 if (rv)
773 return MapSystemError(WSAGetLastError());
774 break;
776 default:
777 NOTREACHED() << "Invalid address family";
778 return ERR_ADDRESS_INVALID;
781 return OK;
784 int UDPSocketWin::DoBind(const IPEndPoint& address) {
785 SockaddrStorage storage;
786 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
787 return ERR_ADDRESS_INVALID;
788 int rv = bind(socket_, storage.addr, storage.addr_len);
789 if (rv == 0)
790 return OK;
791 int last_error = WSAGetLastError();
792 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
793 // Map some codes that are special to bind() separately.
794 // * WSAEACCES: If a port is already bound to a socket, WSAEACCES may be
795 // returned instead of WSAEADDRINUSE, depending on whether the socket
796 // option SO_REUSEADDR or SO_EXCLUSIVEADDRUSE is set and whether the
797 // conflicting socket is owned by a different user account. See the MSDN
798 // page "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" for the gory details.
799 if (last_error == WSAEACCES || last_error == WSAEADDRNOTAVAIL)
800 return ERR_ADDRESS_IN_USE;
801 return MapSystemError(last_error);
804 int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
805 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
807 for (int i = 0; i < kBindRetries; ++i) {
808 int rv = DoBind(IPEndPoint(address,
809 rand_int_cb_.Run(kPortStart, kPortEnd)));
810 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
811 return rv;
813 return DoBind(IPEndPoint(address, 0));
816 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
817 SockaddrStorage& storage = core_->recv_addr_storage_;
818 return address->FromSockAddr(storage.addr, storage.addr_len);
821 int UDPSocketWin::JoinGroup(
822 const IPAddressNumber& group_address) const {
823 DCHECK(CalledOnValidThread());
824 if (!is_connected())
825 return ERR_SOCKET_NOT_CONNECTED;
827 switch (group_address.size()) {
828 case kIPv4AddressSize: {
829 if (addr_family_ != AF_INET)
830 return ERR_ADDRESS_INVALID;
831 ip_mreq mreq;
832 mreq.imr_interface.s_addr = htonl(multicast_interface_);
833 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
834 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
835 reinterpret_cast<const char*>(&mreq),
836 sizeof(mreq));
837 if (rv)
838 return MapSystemError(WSAGetLastError());
839 return OK;
841 case kIPv6AddressSize: {
842 if (addr_family_ != AF_INET6)
843 return ERR_ADDRESS_INVALID;
844 ipv6_mreq mreq;
845 mreq.ipv6mr_interface = multicast_interface_;
846 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
847 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
848 reinterpret_cast<const char*>(&mreq),
849 sizeof(mreq));
850 if (rv)
851 return MapSystemError(WSAGetLastError());
852 return OK;
854 default:
855 NOTREACHED() << "Invalid address family";
856 return ERR_ADDRESS_INVALID;
860 int UDPSocketWin::LeaveGroup(
861 const IPAddressNumber& group_address) const {
862 DCHECK(CalledOnValidThread());
863 if (!is_connected())
864 return ERR_SOCKET_NOT_CONNECTED;
866 switch (group_address.size()) {
867 case kIPv4AddressSize: {
868 if (addr_family_ != AF_INET)
869 return ERR_ADDRESS_INVALID;
870 ip_mreq mreq;
871 mreq.imr_interface.s_addr = htonl(multicast_interface_);
872 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
873 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
874 reinterpret_cast<const char*>(&mreq), sizeof(mreq));
875 if (rv)
876 return MapSystemError(WSAGetLastError());
877 return OK;
879 case kIPv6AddressSize: {
880 if (addr_family_ != AF_INET6)
881 return ERR_ADDRESS_INVALID;
882 ipv6_mreq mreq;
883 mreq.ipv6mr_interface = multicast_interface_;
884 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
885 int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
886 reinterpret_cast<const char*>(&mreq), sizeof(mreq));
887 if (rv)
888 return MapSystemError(WSAGetLastError());
889 return OK;
891 default:
892 NOTREACHED() << "Invalid address family";
893 return ERR_ADDRESS_INVALID;
897 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
898 DCHECK(CalledOnValidThread());
899 if (is_connected())
900 return ERR_SOCKET_IS_CONNECTED;
901 multicast_interface_ = interface_index;
902 return OK;
905 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
906 DCHECK(CalledOnValidThread());
907 if (is_connected())
908 return ERR_SOCKET_IS_CONNECTED;
910 if (time_to_live < 0 || time_to_live > 255)
911 return ERR_INVALID_ARGUMENT;
912 multicast_time_to_live_ = time_to_live;
913 return OK;
916 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
917 DCHECK(CalledOnValidThread());
918 if (is_connected())
919 return ERR_SOCKET_IS_CONNECTED;
921 if (loopback)
922 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
923 else
924 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
925 return OK;
928 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
929 if (dscp == DSCP_NO_CHANGE) {
930 return OK;
933 if (!is_connected())
934 return ERR_SOCKET_NOT_CONNECTED;
936 QwaveAPI& qos(QwaveAPI::Get());
938 if (!qos.qwave_supported())
939 return ERROR_NOT_SUPPORTED;
941 if (qos_handle_ == NULL) {
942 QOS_VERSION version;
943 version.MajorVersion = 1;
944 version.MinorVersion = 0;
945 qos.CreateHandle(&version, &qos_handle_);
946 if (qos_handle_ == NULL)
947 return ERROR_NOT_SUPPORTED;
950 QOS_TRAFFIC_TYPE traffic_type = QOSTrafficTypeBestEffort;
951 switch (dscp) {
952 case DSCP_CS0:
953 traffic_type = QOSTrafficTypeBestEffort;
954 break;
955 case DSCP_CS1:
956 traffic_type = QOSTrafficTypeBackground;
957 break;
958 case DSCP_AF11:
959 case DSCP_AF12:
960 case DSCP_AF13:
961 case DSCP_CS2:
962 case DSCP_AF21:
963 case DSCP_AF22:
964 case DSCP_AF23:
965 case DSCP_CS3:
966 case DSCP_AF31:
967 case DSCP_AF32:
968 case DSCP_AF33:
969 case DSCP_CS4:
970 traffic_type = QOSTrafficTypeExcellentEffort;
971 break;
972 case DSCP_AF41:
973 case DSCP_AF42:
974 case DSCP_AF43:
975 case DSCP_CS5:
976 traffic_type = QOSTrafficTypeAudioVideo;
977 break;
978 case DSCP_EF:
979 case DSCP_CS6:
980 traffic_type = QOSTrafficTypeVoice;
981 break;
982 case DSCP_CS7:
983 traffic_type = QOSTrafficTypeControl;
984 break;
985 case DSCP_NO_CHANGE:
986 NOTREACHED();
987 break;
989 if (qos_flow_id_ != 0) {
990 qos.RemoveSocketFromFlow(qos_handle_, NULL, qos_flow_id_, 0);
991 qos_flow_id_ = 0;
993 if (!qos.AddSocketToFlow(qos_handle_,
994 socket_,
995 NULL,
996 traffic_type,
997 QOS_NON_ADAPTIVE_FLOW,
998 &qos_flow_id_)) {
999 DWORD err = GetLastError();
1000 if (err == ERROR_DEVICE_REINITIALIZATION_NEEDED) {
1001 qos.CloseHandle(qos_handle_);
1002 qos_flow_id_ = 0;
1003 qos_handle_ = 0;
1005 return MapSystemError(err);
1007 // This requires admin rights, and may fail, if so we ignore it
1008 // as AddSocketToFlow should still do *approximately* the right thing.
1009 DWORD buf = dscp;
1010 qos.SetFlow(qos_handle_,
1011 qos_flow_id_,
1012 QOSSetOutgoingDSCPValue,
1013 sizeof(buf),
1014 &buf,
1016 NULL);
1018 return OK;
1021 void UDPSocketWin::DetachFromThread() {
1022 base::NonThreadSafe::DetachFromThread();
1025 } // namespace net