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 26 namespace { 27 28 const int kBindRetries = 10; 29 const int kPortStart = 1024; 30 const int kPortEnd = 65535; 31 32 } // namespace 33 34 namespace 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. 41 class 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 108 UDPSocketWin::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 119 UDPSocketWin::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 130 void 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 137 void 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 144 void 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 152 void 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 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), 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 182 UDPSocketWin::~UDPSocketWin() { 183 Close(); 184 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 185 } 186 187 void 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 209 int 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 230 int 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 253 int UDPSocketWin::Read(IOBuffer* buf, 254 int buf_len, 255 const CompletionCallback& callback) { 256 return RecvFrom(buf, buf_len, NULL, callback); 257 } 258 259 int 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 279 int UDPSocketWin::Write(IOBuffer* buf, 280 int buf_len, 281 const CompletionCallback& callback) { 282 return SendToOrWrite(buf, buf_len, NULL, callback); 283 } 284 285 int 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 292 int 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 313 int 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 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); 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 363 int 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 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); 388 return OK; 389 } 390 391 bool 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 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 396 return rv == 0; 397 } 398 399 bool UDPSocketWin::SetSendBufferSize(int32 size) { 400 DCHECK(CalledOnValidThread()); 401 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 402 reinterpret_cast<const char*>(&size), sizeof(size)); 403 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 404 return rv == 0; 405 } 406 407 void UDPSocketWin::AllowAddressReuse() { 408 DCHECK(CalledOnValidThread()); 409 DCHECK(!is_connected()); 410 411 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; 412 } 413 414 void UDPSocketWin::AllowBroadcast() { 415 DCHECK(CalledOnValidThread()); 416 DCHECK(!is_connected()); 417 418 socket_options_ |= SOCKET_OPTION_BROADCAST; 419 } 420 421 void UDPSocketWin::DoReadCallback(int rv) { 422 DCHECK_NE(rv, ERR_IO_PENDING); 423 DCHECK(!read_callback_.is_null()); 424 425 // since Run may result in Read being called, clear read_callback_ up front. 426 CompletionCallback c = read_callback_; 427 read_callback_.Reset(); 428 c.Run(rv); 429 } 430 431 void UDPSocketWin::DoWriteCallback(int rv) { 432 DCHECK_NE(rv, ERR_IO_PENDING); 433 DCHECK(!write_callback_.is_null()); 434 435 // since Run may result in Write being called, clear write_callback_ up front. 436 CompletionCallback c = write_callback_; 437 write_callback_.Reset(); 438 c.Run(rv); 439 } 440 441 void UDPSocketWin::DidCompleteRead() { 442 DWORD num_bytes, flags; 443 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, 444 &num_bytes, FALSE, &flags); 445 WSAResetEvent(core_->read_overlapped_.hEvent); 446 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); 447 // Convert address. 448 if (recv_from_address_ && result >= 0) { 449 if (!ReceiveAddressToIPEndpoint(recv_from_address_)) 450 result = ERR_ADDRESS_INVALID; 451 } 452 LogRead(result, core_->read_iobuffer_->data()); 453 core_->read_iobuffer_ = NULL; 454 recv_from_address_ = NULL; 455 DoReadCallback(result); 456 } 457 458 void UDPSocketWin::LogRead(int result, const char* bytes) const { 459 if (result < 0) { 460 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); 461 return; 462 } 463 464 if (net_log_.IsLoggingAllEvents()) { 465 // Get address for logging, if |address| is NULL. 466 IPEndPoint address; 467 bool is_address_valid = ReceiveAddressToIPEndpoint(&address); 468 net_log_.AddEvent( 469 NetLog::TYPE_UDP_BYTES_RECEIVED, 470 CreateNetLogUDPDataTranferCallback( 471 result, bytes, 472 is_address_valid ? &address : NULL)); 473 } 474 475 base::StatsCounter read_bytes("udp.read_bytes"); 476 read_bytes.Add(result); 477 } 478 479 void UDPSocketWin::DidCompleteWrite() { 480 DWORD num_bytes, flags; 481 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, 482 &num_bytes, FALSE, &flags); 483 WSAResetEvent(core_->write_overlapped_.hEvent); 484 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); 485 LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get()); 486 487 send_to_address_.reset(); 488 core_->write_iobuffer_ = NULL; 489 DoWriteCallback(result); 490 } 491 492 void UDPSocketWin::LogWrite(int result, 493 const char* bytes, 494 const IPEndPoint* address) const { 495 if (result < 0) { 496 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); 497 return; 498 } 499 500 if (net_log_.IsLoggingAllEvents()) { 501 net_log_.AddEvent( 502 NetLog::TYPE_UDP_BYTES_SENT, 503 CreateNetLogUDPDataTranferCallback(result, bytes, address)); 504 } 505 506 base::StatsCounter write_bytes("udp.write_bytes"); 507 write_bytes.Add(result); 508 } 509 510 int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, 511 IPEndPoint* address) { 512 DCHECK(!core_->read_iobuffer_); 513 SockaddrStorage& storage = core_->recv_addr_storage_; 514 storage.addr_len = sizeof(storage.addr_storage); 515 516 WSABUF read_buffer; 517 read_buffer.buf = buf->data(); 518 read_buffer.len = buf_len; 519 520 DWORD flags = 0; 521 DWORD num; 522 CHECK_NE(INVALID_SOCKET, socket_); 523 AssertEventNotSignaled(core_->read_overlapped_.hEvent); 524 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr, 525 &storage.addr_len, &core_->read_overlapped_, NULL); 526 if (rv == 0) { 527 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 528 int result = num; 529 // Convert address. 530 if (address && result >= 0) { 531 if (!ReceiveAddressToIPEndpoint(address)) 532 result = ERR_FAILED; 533 } 534 LogRead(result, buf->data()); 535 return result; 536 } 537 } else { 538 int os_error = WSAGetLastError(); 539 if (os_error != WSA_IO_PENDING) { 540 int result = MapSystemError(os_error); 541 LogRead(result, NULL); 542 return result; 543 } 544 } 545 core_->WatchForRead(); 546 core_->read_iobuffer_ = buf; 547 return ERR_IO_PENDING; 548 } 549 550 int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, 551 const IPEndPoint* address) { 552 DCHECK(!core_->write_iobuffer_); 553 SockaddrStorage storage; 554 struct sockaddr* addr = storage.addr; 555 // Convert address. 556 if (!address) { 557 addr = NULL; 558 storage.addr_len = 0; 559 } else { 560 if (!address->ToSockAddr(addr, &storage.addr_len)) { 561 int result = ERR_FAILED; 562 LogWrite(result, NULL, NULL); 563 return result; 564 } 565 } 566 567 WSABUF write_buffer; 568 write_buffer.buf = buf->data(); 569 write_buffer.len = buf_len; 570 571 DWORD flags = 0; 572 DWORD num; 573 AssertEventNotSignaled(core_->write_overlapped_.hEvent); 574 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, 575 addr, storage.addr_len, &core_->write_overlapped_, NULL); 576 if (rv == 0) { 577 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 578 int result = num; 579 LogWrite(result, buf->data(), address); 580 return result; 581 } 582 } else { 583 int os_error = WSAGetLastError(); 584 if (os_error != WSA_IO_PENDING) { 585 int result = MapSystemError(os_error); 586 LogWrite(result, NULL, NULL); 587 return result; 588 } 589 } 590 591 core_->WatchForWrite(); 592 core_->write_iobuffer_ = buf; 593 return ERR_IO_PENDING; 594 } 595 596 int UDPSocketWin::SetSocketOptions() { 597 BOOL true_value = 1; 598 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { 599 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 600 reinterpret_cast<const char*>(&true_value), 601 sizeof(true_value)); 602 if (rv < 0) 603 return MapSystemError(WSAGetLastError()); 604 } 605 if (socket_options_ & SOCKET_OPTION_BROADCAST) { 606 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, 607 reinterpret_cast<const char*>(&true_value), 608 sizeof(true_value)); 609 if (rv < 0) 610 return MapSystemError(WSAGetLastError()); 611 } 612 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { 613 DWORD loop = 0; 614 int protocol_level = 615 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 616 int option = 617 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; 618 int rv = setsockopt(socket_, protocol_level, option, 619 reinterpret_cast<const char*>(&loop), sizeof(loop)); 620 if (rv < 0) 621 return MapSystemError(WSAGetLastError()); 622 } 623 if (multicast_time_to_live_ != 1) { 624 DWORD hops = multicast_time_to_live_; 625 int protocol_level = 626 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 627 int option = 628 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; 629 int rv = setsockopt(socket_, protocol_level, option, 630 reinterpret_cast<const char*>(&hops), sizeof(hops)); 631 if (rv < 0) 632 return MapSystemError(WSAGetLastError()); 633 } 634 if (multicast_interface_ != 0) { 635 switch (addr_family_) { 636 case AF_INET: { 637 in_addr address; 638 address.s_addr = htonl(multicast_interface_); 639 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, 640 reinterpret_cast<const char*>(&address), 641 sizeof(address)); 642 if (rv) 643 return MapSystemError(WSAGetLastError()); 644 break; 645 } 646 case AF_INET6: { 647 uint32 interface_index = multicast_interface_; 648 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF, 649 reinterpret_cast<const char*>(&interface_index), 650 sizeof(interface_index)); 651 if (rv) 652 return MapSystemError(WSAGetLastError()); 653 break; 654 } 655 default: 656 NOTREACHED() << "Invalid address family"; 657 return ERR_ADDRESS_INVALID; 658 } 659 } 660 return OK; 661 } 662 663 int UDPSocketWin::DoBind(const IPEndPoint& address) { 664 SockaddrStorage storage; 665 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 666 return ERR_ADDRESS_INVALID; 667 int rv = bind(socket_, storage.addr, storage.addr_len); 668 if (rv == 0) 669 return OK; 670 int last_error = WSAGetLastError(); 671 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error); 672 // Map some codes that are special to bind() separately. 673 if (last_error == WSAEACCES || last_error == WSAEINVAL) 674 return ERR_ADDRESS_IN_USE; 675 return MapSystemError(last_error); 676 } 677 678 int UDPSocketWin::RandomBind(const IPAddressNumber& address) { 679 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 680 681 for (int i = 0; i < kBindRetries; ++i) { 682 int rv = DoBind(IPEndPoint(address, 683 rand_int_cb_.Run(kPortStart, kPortEnd))); 684 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 685 return rv; 686 } 687 return DoBind(IPEndPoint(address, 0)); 688 } 689 690 bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { 691 SockaddrStorage& storage = core_->recv_addr_storage_; 692 return address->FromSockAddr(storage.addr, storage.addr_len); 693 } 694 695 int UDPSocketWin::JoinGroup( 696 const IPAddressNumber& group_address) const { 697 DCHECK(CalledOnValidThread()); 698 if (!is_connected()) 699 return ERR_SOCKET_NOT_CONNECTED; 700 701 switch (group_address.size()) { 702 case kIPv4AddressSize: { 703 if (addr_family_ != AF_INET) 704 return ERR_ADDRESS_INVALID; 705 ip_mreq mreq; 706 mreq.imr_interface.s_addr = htonl(multicast_interface_); 707 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); 708 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, 709 reinterpret_cast<const char*>(&mreq), 710 sizeof(mreq)); 711 if (rv) 712 return MapSystemError(WSAGetLastError()); 713 return OK; 714 } 715 case kIPv6AddressSize: { 716 if (addr_family_ != AF_INET6) 717 return ERR_ADDRESS_INVALID; 718 ipv6_mreq mreq; 719 mreq.ipv6mr_interface = multicast_interface_; 720 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); 721 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, 722 reinterpret_cast<const char*>(&mreq), 723 sizeof(mreq)); 724 if (rv) 725 return MapSystemError(WSAGetLastError()); 726 return OK; 727 } 728 default: 729 NOTREACHED() << "Invalid address family"; 730 return ERR_ADDRESS_INVALID; 731 } 732 } 733 734 int UDPSocketWin::LeaveGroup( 735 const IPAddressNumber& group_address) const { 736 DCHECK(CalledOnValidThread()); 737 if (!is_connected()) 738 return ERR_SOCKET_NOT_CONNECTED; 739 740 switch (group_address.size()) { 741 case kIPv4AddressSize: { 742 if (addr_family_ != AF_INET) 743 return ERR_ADDRESS_INVALID; 744 ip_mreq mreq; 745 mreq.imr_interface.s_addr = htonl(multicast_interface_); 746 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); 747 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, 748 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); 749 if (rv) 750 return MapSystemError(WSAGetLastError()); 751 return OK; 752 } 753 case kIPv6AddressSize: { 754 if (addr_family_ != AF_INET6) 755 return ERR_ADDRESS_INVALID; 756 ipv6_mreq mreq; 757 mreq.ipv6mr_interface = multicast_interface_; 758 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); 759 int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP, 760 reinterpret_cast<const char*>(&mreq), sizeof(mreq)); 761 if (rv) 762 return MapSystemError(WSAGetLastError()); 763 return OK; 764 } 765 default: 766 NOTREACHED() << "Invalid address family"; 767 return ERR_ADDRESS_INVALID; 768 } 769 } 770 771 int UDPSocketWin::SetMulticastInterface(uint32 interface_index) { 772 DCHECK(CalledOnValidThread()); 773 if (is_connected()) 774 return ERR_SOCKET_IS_CONNECTED; 775 multicast_interface_ = interface_index; 776 return OK; 777 } 778 779 int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) { 780 DCHECK(CalledOnValidThread()); 781 if (is_connected()) 782 return ERR_SOCKET_IS_CONNECTED; 783 784 if (time_to_live < 0 || time_to_live > 255) 785 return ERR_INVALID_ARGUMENT; 786 multicast_time_to_live_ = time_to_live; 787 return OK; 788 } 789 790 int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) { 791 DCHECK(CalledOnValidThread()); 792 if (is_connected()) 793 return ERR_SOCKET_IS_CONNECTED; 794 795 if (loopback) 796 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP; 797 else 798 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP; 799 return OK; 800 } 801 802 // TODO(hubbe): Implement differentiated services for windows. 803 // Note: setsockopt(IP_TOS) does not work on windows XP and later. 804 int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { 805 return ERR_NOT_IMPLEMENTED; 806 } 807 808 } // namespace net 809