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. 4 5#include "net/udp/udp_socket_win.h" 6 7#include <mstcpip.h> 8 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" 25 26namespace { 27 28const int kBindRetries = 10; 29const int kPortStart = 1024; 30const int kPortEnd = 65535; 31 32} // namespace 33 34namespace net { 35 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. 41class UDPSocketWin::Core : public base::RefCounted<Core> { 42 public: 43 explicit Core(UDPSocketWin* socket); 44 45 // Start watching for the end of a read or write operation. 46 void WatchForRead(); 47 void WatchForWrite(); 48 49 // The UDPSocketWin is going away. 50 void Detach() { socket_ = NULL; } 51 52 // The separate OVERLAPPED variables for asynchronous operation. 53 OVERLAPPED read_overlapped_; 54 OVERLAPPED write_overlapped_; 55 56 // The buffers used in Read() and Write(). 57 scoped_refptr<IOBuffer> read_iobuffer_; 58 scoped_refptr<IOBuffer> write_iobuffer_; 59 60 // The address storage passed to WSARecvFrom(). 61 SockaddrStorage recv_addr_storage_; 62 63 private: 64 friend class base::RefCounted<Core>; 65 66 class ReadDelegate : public base::win::ObjectWatcher::Delegate { 67 public: 68 explicit ReadDelegate(Core* core) : core_(core) {} 69 virtual ~ReadDelegate() {} 70 71 // base::ObjectWatcher::Delegate methods: 72 virtual void OnObjectSignaled(HANDLE object); 73 74 private: 75 Core* const core_; 76 }; 77 78 class WriteDelegate : public base::win::ObjectWatcher::Delegate { 79 public: 80 explicit WriteDelegate(Core* core) : core_(core) {} 81 virtual ~WriteDelegate() {} 82 83 // base::ObjectWatcher::Delegate methods: 84 virtual void OnObjectSignaled(HANDLE object); 85 86 private: 87 Core* const core_; 88 }; 89 90 ~Core(); 91 92 // The socket that created this object. 93 UDPSocketWin* socket_; 94 95 // |reader_| handles the signals from |read_watcher_|. 96 ReadDelegate reader_; 97 // |writer_| handles the signals from |write_watcher_|. 98 WriteDelegate writer_; 99 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_; 104 105 DISALLOW_COPY_AND_ASSIGN(Core); 106}; 107 108UDPSocketWin::Core::Core(UDPSocketWin* socket) 109 : socket_(socket), 110 reader_(this), 111 writer_(this) { 112 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); 113 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); 114 115 read_overlapped_.hEvent = WSACreateEvent(); 116 write_overlapped_.hEvent = WSACreateEvent(); 117} 118 119UDPSocketWin::Core::~Core() { 120 // Make sure the message loop is not watching this object anymore. 121 read_watcher_.StopWatching(); 122 write_watcher_.StopWatching(); 123 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_)); 128} 129 130void UDPSocketWin::Core::WatchForRead() { 131 // We grab an extra reference because there is an IO operation in progress. 132 // Balanced in ReadDelegate::OnObjectSignaled(). 133 AddRef(); 134 read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); 135} 136 137void UDPSocketWin::Core::WatchForWrite() { 138 // We grab an extra reference because there is an IO operation in progress. 139 // Balanced in WriteDelegate::OnObjectSignaled(). 140 AddRef(); 141 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); 142} 143 144void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) { 145 DCHECK_EQ(object, core_->read_overlapped_.hEvent); 146 if (core_->socket_) 147 core_->socket_->DidCompleteRead(); 148 149 core_->Release(); 150} 151 152void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) { 153 DCHECK_EQ(object, core_->write_overlapped_.hEvent); 154 if (core_->socket_) 155 core_->socket_->DidCompleteWrite(); 156 157 core_->Release(); 158} 159 160//----------------------------------------------------------------------------- 161 162UDPSocketWin::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), 167 addr_family_(0), 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)) { 175 EnsureWinsockInit(); 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()); 180} 181 182UDPSocketWin::~UDPSocketWin() { 183 Close(); 184 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 185} 186 187void UDPSocketWin::Close() { 188 DCHECK(CalledOnValidThread()); 189 190 if (!is_connected()) 191 return; 192 193 // Zero out any pending read/write callback state. 194 read_callback_.Reset(); 195 recv_from_address_ = NULL; 196 write_callback_.Reset(); 197 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; 203 addr_family_ = 0; 204 205 core_->Detach(); 206 core_ = NULL; 207} 208 209int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { 210 DCHECK(CalledOnValidThread()); 211 DCHECK(address); 212 if (!is_connected()) 213 return ERR_SOCKET_NOT_CONNECTED; 214 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()); 224 } 225 226 *address = *remote_address_; 227 return OK; 228} 229 230int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const { 231 DCHECK(CalledOnValidThread()); 232 DCHECK(address); 233 if (!is_connected()) 234 return ERR_SOCKET_NOT_CONNECTED; 235 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())); 247 } 248 249 *address = *local_address_; 250 return OK; 251} 252 253int UDPSocketWin::Read(IOBuffer* buf, 254 int buf_len, 255 const CompletionCallback& callback) { 256 return RecvFrom(buf, buf_len, NULL, callback); 257} 258 259int UDPSocketWin::RecvFrom(IOBuffer* buf, 260 int buf_len, 261 IPEndPoint* address, 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); 269 270 int nread = InternalRecvFrom(buf, buf_len, address); 271 if (nread != ERR_IO_PENDING) 272 return nread; 273 274 read_callback_ = callback; 275 recv_from_address_ = address; 276 return ERR_IO_PENDING; 277} 278 279int UDPSocketWin::Write(IOBuffer* buf, 280 int buf_len, 281 const CompletionCallback& callback) { 282 return SendToOrWrite(buf, buf_len, NULL, callback); 283} 284 285int UDPSocketWin::SendTo(IOBuffer* buf, 286 int buf_len, 287 const IPEndPoint& address, 288 const CompletionCallback& callback) { 289 return SendToOrWrite(buf, buf_len, &address, callback); 290} 291 292int UDPSocketWin::SendToOrWrite(IOBuffer* buf, 293 int buf_len, 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()); 302 303 int nwrite = InternalSendTo(buf, buf_len, address); 304 if (nwrite != ERR_IO_PENDING) 305 return nwrite; 306 307 if (address) 308 send_to_address_.reset(new IPEndPoint(*address)); 309 write_callback_ = callback; 310 return ERR_IO_PENDING; 311} 312 313int UDPSocketWin::Connect(const IPEndPoint& address) { 314 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, 315 CreateNetLogUDPConnectCallback(&address)); 316 int rv = InternalConnect(address); 317 if (rv != OK) 318 Close(); 319 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); 320 return rv; 321} 322 323int 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); 328 if (rv < 0) 329 return rv; 330 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. 334 size_t addr_size = 335 addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize; 336 IPAddressNumber addr_any(addr_size); 337 rv = RandomBind(addr_any); 338 } 339 // else connect() does the DatagramSocket::DEFAULT_BIND 340 341 if (rv < 0) { 342 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv); 343 Close(); 344 return rv; 345 } 346 347 SockaddrStorage storage; 348 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 349 return ERR_ADDRESS_INVALID; 350 351 rv = connect(socket_, storage.addr, storage.addr_len); 352 if (rv < 0) { 353 // Close() may change the last error. Map it beforehand. 354 int result = MapSystemError(WSAGetLastError()); 355 Close(); 356 return result; 357 } 358 359 remote_address_.reset(new IPEndPoint(address)); 360 return rv; 361} 362 363int UDPSocketWin::Bind(const IPEndPoint& address) { 364 DCHECK(!is_connected()); 365 int rv = CreateSocket(address.GetSockAddrFamily()); 366 if (rv < 0) 367 return rv; 368 rv = SetSocketOptions(); 369 if (rv < 0) { 370 Close(); 371 return rv; 372 } 373 rv = DoBind(address); 374 if (rv < 0) { 375 Close(); 376 return rv; 377 } 378 local_address_.reset(); 379 return rv; 380} 381 382int 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); 388 return OK; 389} 390 391int UDPSocketWin::SetReceiveBufferSize(int32 size) { 392 DCHECK(CalledOnValidThread()); 393 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 394 reinterpret_cast<const char*>(&size), sizeof(size)); 395 if (rv != 0) 396 return MapSystemError(WSAGetLastError()); 397 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); 404 if (rv != 0) 405 return MapSystemError(WSAGetLastError()); 406 if (actual_size >= size) 407 return OK; 408 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableReceiveBuffer", 409 actual_size, 1000, 1000000, 50); 410 return ERR_SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE; 411} 412 413int UDPSocketWin::SetSendBufferSize(int32 size) { 414 DCHECK(CalledOnValidThread()); 415 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 416 reinterpret_cast<const char*>(&size), sizeof(size)); 417 if (rv != 0) 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); 425 if (rv != 0) 426 return MapSystemError(WSAGetLastError()); 427 if (actual_size >= size) 428 return OK; 429 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer", 430 actual_size, 1000, 1000000, 50); 431 return ERR_SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE; 432} 433 434void UDPSocketWin::AllowAddressReuse() { 435 DCHECK(CalledOnValidThread()); 436 DCHECK(!is_connected()); 437 438 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; 439} 440 441void UDPSocketWin::AllowBroadcast() { 442 DCHECK(CalledOnValidThread()); 443 DCHECK(!is_connected()); 444 445 socket_options_ |= SOCKET_OPTION_BROADCAST; 446} 447 448void UDPSocketWin::DoReadCallback(int rv) { 449 DCHECK_NE(rv, ERR_IO_PENDING); 450 DCHECK(!read_callback_.is_null()); 451 452 // since Run may result in Read being called, clear read_callback_ up front. 453 CompletionCallback c = read_callback_; 454 read_callback_.Reset(); 455 c.Run(rv); 456} 457 458void UDPSocketWin::DoWriteCallback(int rv) { 459 DCHECK_NE(rv, ERR_IO_PENDING); 460 DCHECK(!write_callback_.is_null()); 461 462 // since Run may result in Write being called, clear write_callback_ up front. 463 CompletionCallback c = write_callback_; 464 write_callback_.Reset(); 465 c.Run(rv); 466} 467 468void 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()); 474 // Convert address. 475 if (recv_from_address_ && result >= 0) { 476 if (!ReceiveAddressToIPEndpoint(recv_from_address_)) 477 result = ERR_ADDRESS_INVALID; 478 } 479 LogRead(result, core_->read_iobuffer_->data()); 480 core_->read_iobuffer_ = NULL; 481 recv_from_address_ = NULL; 482 DoReadCallback(result); 483} 484 485void UDPSocketWin::LogRead(int result, const char* bytes) const { 486 if (result < 0) { 487 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); 488 return; 489 } 490 491 if (net_log_.IsLogging()) { 492 // Get address for logging, if |address| is NULL. 493 IPEndPoint address; 494 bool is_address_valid = ReceiveAddressToIPEndpoint(&address); 495 net_log_.AddEvent( 496 NetLog::TYPE_UDP_BYTES_RECEIVED, 497 CreateNetLogUDPDataTranferCallback( 498 result, bytes, 499 is_address_valid ? &address : NULL)); 500 } 501 502 base::StatsCounter read_bytes("udp.read_bytes"); 503 read_bytes.Add(result); 504} 505 506void 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()); 513 514 send_to_address_.reset(); 515 core_->write_iobuffer_ = NULL; 516 DoWriteCallback(result); 517} 518 519void UDPSocketWin::LogWrite(int result, 520 const char* bytes, 521 const IPEndPoint* address) const { 522 if (result < 0) { 523 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); 524 return; 525 } 526 527 if (net_log_.IsLogging()) { 528 net_log_.AddEvent( 529 NetLog::TYPE_UDP_BYTES_SENT, 530 CreateNetLogUDPDataTranferCallback(result, bytes, address)); 531 } 532 533 base::StatsCounter write_bytes("udp.write_bytes"); 534 write_bytes.Add(result); 535} 536 537int 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); 542 543 WSABUF read_buffer; 544 read_buffer.buf = buf->data(); 545 read_buffer.len = buf_len; 546 547 DWORD flags = 0; 548 DWORD num; 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); 553 if (rv == 0) { 554 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 555 int result = num; 556 // Convert address. 557 if (address && result >= 0) { 558 if (!ReceiveAddressToIPEndpoint(address)) 559 result = ERR_ADDRESS_INVALID; 560 } 561 LogRead(result, buf->data()); 562 return result; 563 } 564 } else { 565 int os_error = WSAGetLastError(); 566 if (os_error != WSA_IO_PENDING) { 567 int result = MapSystemError(os_error); 568 LogRead(result, NULL); 569 return result; 570 } 571 } 572 core_->WatchForRead(); 573 core_->read_iobuffer_ = buf; 574 return ERR_IO_PENDING; 575} 576 577int 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; 582 // Convert address. 583 if (!address) { 584 addr = NULL; 585 storage.addr_len = 0; 586 } else { 587 if (!address->ToSockAddr(addr, &storage.addr_len)) { 588 int result = ERR_ADDRESS_INVALID; 589 LogWrite(result, NULL, NULL); 590 return result; 591 } 592 } 593 594 WSABUF write_buffer; 595 write_buffer.buf = buf->data(); 596 write_buffer.len = buf_len; 597 598 DWORD flags = 0; 599 DWORD num; 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); 603 if (rv == 0) { 604 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 605 int result = num; 606 LogWrite(result, buf->data(), address); 607 return result; 608 } 609 } else { 610 int os_error = WSAGetLastError(); 611 if (os_error != WSA_IO_PENDING) { 612 int result = MapSystemError(os_error); 613 LogWrite(result, NULL, NULL); 614 return result; 615 } 616 } 617 618 core_->WatchForWrite(); 619 core_->write_iobuffer_ = buf; 620 return ERR_IO_PENDING; 621} 622 623int UDPSocketWin::SetSocketOptions() { 624 BOOL true_value = 1; 625 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { 626 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 627 reinterpret_cast<const char*>(&true_value), 628 sizeof(true_value)); 629 if (rv < 0) 630 return MapSystemError(WSAGetLastError()); 631 } 632 if (socket_options_ & SOCKET_OPTION_BROADCAST) { 633 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, 634 reinterpret_cast<const char*>(&true_value), 635 sizeof(true_value)); 636 if (rv < 0) 637 return MapSystemError(WSAGetLastError()); 638 } 639 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { 640 DWORD loop = 0; 641 int protocol_level = 642 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 643 int option = 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)); 647 if (rv < 0) 648 return MapSystemError(WSAGetLastError()); 649 } 650 if (multicast_time_to_live_ != 1) { 651 DWORD hops = multicast_time_to_live_; 652 int protocol_level = 653 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 654 int option = 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)); 658 if (rv < 0) 659 return MapSystemError(WSAGetLastError()); 660 } 661 if (multicast_interface_ != 0) { 662 switch (addr_family_) { 663 case AF_INET: { 664 in_addr address; 665 address.s_addr = htonl(multicast_interface_); 666 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, 667 reinterpret_cast<const char*>(&address), 668 sizeof(address)); 669 if (rv) 670 return MapSystemError(WSAGetLastError()); 671 break; 672 } 673 case AF_INET6: { 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)); 678 if (rv) 679 return MapSystemError(WSAGetLastError()); 680 break; 681 } 682 default: 683 NOTREACHED() << "Invalid address family"; 684 return ERR_ADDRESS_INVALID; 685 } 686 } 687 return OK; 688} 689 690int 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); 695 if (rv == 0) 696 return OK; 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); 708} 709 710int UDPSocketWin::RandomBind(const IPAddressNumber& address) { 711 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 712 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) 717 return rv; 718 } 719 return DoBind(IPEndPoint(address, 0)); 720} 721 722bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { 723 SockaddrStorage& storage = core_->recv_addr_storage_; 724 return address->FromSockAddr(storage.addr, storage.addr_len); 725} 726 727int UDPSocketWin::JoinGroup( 728 const IPAddressNumber& group_address) const { 729 DCHECK(CalledOnValidThread()); 730 if (!is_connected()) 731 return ERR_SOCKET_NOT_CONNECTED; 732 733 switch (group_address.size()) { 734 case kIPv4AddressSize: { 735 if (addr_family_ != AF_INET) 736 return ERR_ADDRESS_INVALID; 737 ip_mreq mreq; 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), 742 sizeof(mreq)); 743 if (rv) 744 return MapSystemError(WSAGetLastError()); 745 return OK; 746 } 747 case kIPv6AddressSize: { 748 if (addr_family_ != AF_INET6) 749 return ERR_ADDRESS_INVALID; 750 ipv6_mreq mreq; 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), 755 sizeof(mreq)); 756 if (rv) 757 return MapSystemError(WSAGetLastError()); 758 return OK; 759 } 760 default: 761 NOTREACHED() << "Invalid address family"; 762 return ERR_ADDRESS_INVALID; 763 } 764} 765 766int UDPSocketWin::LeaveGroup( 767 const IPAddressNumber& group_address) const { 768 DCHECK(CalledOnValidThread()); 769 if (!is_connected()) 770 return ERR_SOCKET_NOT_CONNECTED; 771 772 switch (group_address.size()) { 773 case kIPv4AddressSize: { 774 if (addr_family_ != AF_INET) 775 return ERR_ADDRESS_INVALID; 776 ip_mreq mreq; 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)); 781 if (rv) 782 return MapSystemError(WSAGetLastError()); 783 return OK; 784 } 785 case kIPv6AddressSize: { 786 if (addr_family_ != AF_INET6) 787 return ERR_ADDRESS_INVALID; 788 ipv6_mreq mreq; 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)); 793 if (rv) 794 return MapSystemError(WSAGetLastError()); 795 return OK; 796 } 797 default: 798 NOTREACHED() << "Invalid address family"; 799 return ERR_ADDRESS_INVALID; 800 } 801} 802 803int UDPSocketWin::SetMulticastInterface(uint32 interface_index) { 804 DCHECK(CalledOnValidThread()); 805 if (is_connected()) 806 return ERR_SOCKET_IS_CONNECTED; 807 multicast_interface_ = interface_index; 808 return OK; 809} 810 811int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) { 812 DCHECK(CalledOnValidThread()); 813 if (is_connected()) 814 return ERR_SOCKET_IS_CONNECTED; 815 816 if (time_to_live < 0 || time_to_live > 255) 817 return ERR_INVALID_ARGUMENT; 818 multicast_time_to_live_ = time_to_live; 819 return OK; 820} 821 822int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) { 823 DCHECK(CalledOnValidThread()); 824 if (is_connected()) 825 return ERR_SOCKET_IS_CONNECTED; 826 827 if (loopback) 828 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP; 829 else 830 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP; 831 return OK; 832} 833 834// TODO(hubbe): Implement differentiated services for windows. 835// Note: setsockopt(IP_TOS) does not work on windows XP and later. 836int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { 837 return ERR_NOT_IMPLEMENTED; 838} 839 840void UDPSocketWin::DetachFromThread() { 841 base::NonThreadSafe::DetachFromThread(); 842} 843 844} // namespace net 845