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/stats_counters.h" 14#include "base/posix/eintr_wrapper.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/udp/udp_net_log_parameters.h" 24 25namespace { 26 27const int kBindRetries = 10; 28const int kPortStart = 1024; 29const int kPortEnd = 65535; 30 31} // namespace 32 33namespace net { 34 35// This class encapsulates all the state that has to be preserved as long as 36// there is a network IO operation in progress. If the owner UDPSocketWin 37// is destroyed while an operation is in progress, the Core is detached and it 38// lives until the operation completes and the OS doesn't reference any resource 39// declared on this class anymore. 40class UDPSocketWin::Core : public base::RefCounted<Core> { 41 public: 42 explicit Core(UDPSocketWin* socket); 43 44 // Start watching for the end of a read or write operation. 45 void WatchForRead(); 46 void WatchForWrite(); 47 48 // The UDPSocketWin is going away. 49 void Detach() { socket_ = NULL; } 50 51 // The separate OVERLAPPED variables for asynchronous operation. 52 OVERLAPPED read_overlapped_; 53 OVERLAPPED write_overlapped_; 54 55 // The buffers used in Read() and Write(). 56 scoped_refptr<IOBuffer> read_iobuffer_; 57 scoped_refptr<IOBuffer> write_iobuffer_; 58 59 // The address storage passed to WSARecvFrom(). 60 SockaddrStorage recv_addr_storage_; 61 62 private: 63 friend class base::RefCounted<Core>; 64 65 class ReadDelegate : public base::win::ObjectWatcher::Delegate { 66 public: 67 explicit ReadDelegate(Core* core) : core_(core) {} 68 virtual ~ReadDelegate() {} 69 70 // base::ObjectWatcher::Delegate methods: 71 virtual void OnObjectSignaled(HANDLE object); 72 73 private: 74 Core* const core_; 75 }; 76 77 class WriteDelegate : public base::win::ObjectWatcher::Delegate { 78 public: 79 explicit WriteDelegate(Core* core) : core_(core) {} 80 virtual ~WriteDelegate() {} 81 82 // base::ObjectWatcher::Delegate methods: 83 virtual void OnObjectSignaled(HANDLE object); 84 85 private: 86 Core* const core_; 87 }; 88 89 ~Core(); 90 91 // The socket that created this object. 92 UDPSocketWin* socket_; 93 94 // |reader_| handles the signals from |read_watcher_|. 95 ReadDelegate reader_; 96 // |writer_| handles the signals from |write_watcher_|. 97 WriteDelegate writer_; 98 99 // |read_watcher_| watches for events from Read(). 100 base::win::ObjectWatcher read_watcher_; 101 // |write_watcher_| watches for events from Write(); 102 base::win::ObjectWatcher write_watcher_; 103 104 DISALLOW_COPY_AND_ASSIGN(Core); 105}; 106 107UDPSocketWin::Core::Core(UDPSocketWin* socket) 108 : socket_(socket), 109 reader_(this), 110 writer_(this) { 111 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); 112 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); 113 114 read_overlapped_.hEvent = WSACreateEvent(); 115 write_overlapped_.hEvent = WSACreateEvent(); 116} 117 118UDPSocketWin::Core::~Core() { 119 // Make sure the message loop is not watching this object anymore. 120 read_watcher_.StopWatching(); 121 write_watcher_.StopWatching(); 122 123 WSACloseEvent(read_overlapped_.hEvent); 124 memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_)); 125 WSACloseEvent(write_overlapped_.hEvent); 126 memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_)); 127} 128 129void UDPSocketWin::Core::WatchForRead() { 130 // We grab an extra reference because there is an IO operation in progress. 131 // Balanced in ReadDelegate::OnObjectSignaled(). 132 AddRef(); 133 read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_); 134} 135 136void UDPSocketWin::Core::WatchForWrite() { 137 // We grab an extra reference because there is an IO operation in progress. 138 // Balanced in WriteDelegate::OnObjectSignaled(). 139 AddRef(); 140 write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_); 141} 142 143void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) { 144 DCHECK_EQ(object, core_->read_overlapped_.hEvent); 145 if (core_->socket_) 146 core_->socket_->DidCompleteRead(); 147 148 core_->Release(); 149} 150 151void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) { 152 DCHECK_EQ(object, core_->write_overlapped_.hEvent); 153 if (core_->socket_) 154 core_->socket_->DidCompleteWrite(); 155 156 core_->Release(); 157} 158 159//----------------------------------------------------------------------------- 160 161UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, 162 const RandIntCallback& rand_int_cb, 163 net::NetLog* net_log, 164 const net::NetLog::Source& source) 165 : socket_(INVALID_SOCKET), 166 addr_family_(0), 167 socket_options_(SOCKET_OPTION_MULTICAST_LOOP), 168 multicast_time_to_live_(1), 169 bind_type_(bind_type), 170 rand_int_cb_(rand_int_cb), 171 recv_from_address_(NULL), 172 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { 173 EnsureWinsockInit(); 174 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, 175 source.ToEventParametersCallback()); 176 if (bind_type == DatagramSocket::RANDOM_BIND) 177 DCHECK(!rand_int_cb.is_null()); 178} 179 180UDPSocketWin::~UDPSocketWin() { 181 Close(); 182 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); 183} 184 185void UDPSocketWin::Close() { 186 DCHECK(CalledOnValidThread()); 187 188 if (!is_connected()) 189 return; 190 191 // Zero out any pending read/write callback state. 192 read_callback_.Reset(); 193 recv_from_address_ = NULL; 194 write_callback_.Reset(); 195 196 base::TimeTicks start_time = base::TimeTicks::Now(); 197 closesocket(socket_); 198 UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose", 199 base::TimeTicks::Now() - start_time); 200 socket_ = INVALID_SOCKET; 201 addr_family_ = 0; 202 203 core_->Detach(); 204 core_ = NULL; 205} 206 207int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { 208 DCHECK(CalledOnValidThread()); 209 DCHECK(address); 210 if (!is_connected()) 211 return ERR_SOCKET_NOT_CONNECTED; 212 213 // TODO(szym): Simplify. http://crbug.com/126152 214 if (!remote_address_.get()) { 215 SockaddrStorage storage; 216 if (getpeername(socket_, storage.addr, &storage.addr_len)) 217 return MapSystemError(WSAGetLastError()); 218 scoped_ptr<IPEndPoint> address(new IPEndPoint()); 219 if (!address->FromSockAddr(storage.addr, storage.addr_len)) 220 return ERR_ADDRESS_INVALID; 221 remote_address_.reset(address.release()); 222 } 223 224 *address = *remote_address_; 225 return OK; 226} 227 228int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const { 229 DCHECK(CalledOnValidThread()); 230 DCHECK(address); 231 if (!is_connected()) 232 return ERR_SOCKET_NOT_CONNECTED; 233 234 // TODO(szym): Simplify. http://crbug.com/126152 235 if (!local_address_.get()) { 236 SockaddrStorage storage; 237 if (getsockname(socket_, storage.addr, &storage.addr_len)) 238 return MapSystemError(WSAGetLastError()); 239 scoped_ptr<IPEndPoint> address(new IPEndPoint()); 240 if (!address->FromSockAddr(storage.addr, storage.addr_len)) 241 return ERR_ADDRESS_INVALID; 242 local_address_.reset(address.release()); 243 net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS, 244 CreateNetLogUDPConnectCallback(local_address_.get())); 245 } 246 247 *address = *local_address_; 248 return OK; 249} 250 251int UDPSocketWin::Read(IOBuffer* buf, 252 int buf_len, 253 const CompletionCallback& callback) { 254 return RecvFrom(buf, buf_len, NULL, callback); 255} 256 257int UDPSocketWin::RecvFrom(IOBuffer* buf, 258 int buf_len, 259 IPEndPoint* address, 260 const CompletionCallback& callback) { 261 DCHECK(CalledOnValidThread()); 262 DCHECK_NE(INVALID_SOCKET, socket_); 263 DCHECK(read_callback_.is_null()); 264 DCHECK(!recv_from_address_); 265 DCHECK(!callback.is_null()); // Synchronous operation not supported. 266 DCHECK_GT(buf_len, 0); 267 268 int nread = InternalRecvFrom(buf, buf_len, address); 269 if (nread != ERR_IO_PENDING) 270 return nread; 271 272 read_callback_ = callback; 273 recv_from_address_ = address; 274 return ERR_IO_PENDING; 275} 276 277int UDPSocketWin::Write(IOBuffer* buf, 278 int buf_len, 279 const CompletionCallback& callback) { 280 return SendToOrWrite(buf, buf_len, NULL, callback); 281} 282 283int UDPSocketWin::SendTo(IOBuffer* buf, 284 int buf_len, 285 const IPEndPoint& address, 286 const CompletionCallback& callback) { 287 return SendToOrWrite(buf, buf_len, &address, callback); 288} 289 290int UDPSocketWin::SendToOrWrite(IOBuffer* buf, 291 int buf_len, 292 const IPEndPoint* address, 293 const CompletionCallback& callback) { 294 DCHECK(CalledOnValidThread()); 295 DCHECK_NE(INVALID_SOCKET, socket_); 296 DCHECK(write_callback_.is_null()); 297 DCHECK(!callback.is_null()); // Synchronous operation not supported. 298 DCHECK_GT(buf_len, 0); 299 DCHECK(!send_to_address_.get()); 300 301 int nwrite = InternalSendTo(buf, buf_len, address); 302 if (nwrite != ERR_IO_PENDING) 303 return nwrite; 304 305 if (address) 306 send_to_address_.reset(new IPEndPoint(*address)); 307 write_callback_ = callback; 308 return ERR_IO_PENDING; 309} 310 311int UDPSocketWin::Connect(const IPEndPoint& address) { 312 net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT, 313 CreateNetLogUDPConnectCallback(&address)); 314 int rv = InternalConnect(address); 315 if (rv != OK) 316 Close(); 317 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); 318 return rv; 319} 320 321int UDPSocketWin::InternalConnect(const IPEndPoint& address) { 322 DCHECK(!is_connected()); 323 DCHECK(!remote_address_.get()); 324 int rv = CreateSocket(address); 325 if (rv < 0) 326 return rv; 327 328 if (bind_type_ == DatagramSocket::RANDOM_BIND) 329 rv = RandomBind(address); 330 // else connect() does the DatagramSocket::DEFAULT_BIND 331 332 if (rv < 0) { 333 Close(); 334 return rv; 335 } 336 337 SockaddrStorage storage; 338 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 339 return ERR_ADDRESS_INVALID; 340 341 rv = connect(socket_, storage.addr, storage.addr_len); 342 if (rv < 0) { 343 // Close() may change the last error. Map it beforehand. 344 int result = MapSystemError(WSAGetLastError()); 345 Close(); 346 return result; 347 } 348 349 remote_address_.reset(new IPEndPoint(address)); 350 return rv; 351} 352 353int UDPSocketWin::Bind(const IPEndPoint& address) { 354 DCHECK(!is_connected()); 355 int rv = CreateSocket(address); 356 if (rv < 0) 357 return rv; 358 rv = SetSocketOptions(); 359 if (rv < 0) { 360 Close(); 361 return rv; 362 } 363 rv = DoBind(address); 364 if (rv < 0) { 365 Close(); 366 return rv; 367 } 368 local_address_.reset(); 369 return rv; 370} 371 372int UDPSocketWin::CreateSocket(const IPEndPoint& address) { 373 addr_family_ = address.GetSockAddrFamily(); 374 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP); 375 if (socket_ == INVALID_SOCKET) 376 return MapSystemError(WSAGetLastError()); 377 core_ = new Core(this); 378 return OK; 379} 380 381bool UDPSocketWin::SetReceiveBufferSize(int32 size) { 382 DCHECK(CalledOnValidThread()); 383 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 384 reinterpret_cast<const char*>(&size), sizeof(size)); 385 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 386 return rv == 0; 387} 388 389bool UDPSocketWin::SetSendBufferSize(int32 size) { 390 DCHECK(CalledOnValidThread()); 391 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 392 reinterpret_cast<const char*>(&size), sizeof(size)); 393 DCHECK(!rv) << "Could not set socket send buffer size: " << errno; 394 return rv == 0; 395} 396 397void UDPSocketWin::AllowAddressReuse() { 398 DCHECK(CalledOnValidThread()); 399 DCHECK(!is_connected()); 400 401 socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS; 402} 403 404void UDPSocketWin::AllowBroadcast() { 405 DCHECK(CalledOnValidThread()); 406 DCHECK(!is_connected()); 407 408 socket_options_ |= SOCKET_OPTION_BROADCAST; 409} 410 411void UDPSocketWin::DoReadCallback(int rv) { 412 DCHECK_NE(rv, ERR_IO_PENDING); 413 DCHECK(!read_callback_.is_null()); 414 415 // since Run may result in Read being called, clear read_callback_ up front. 416 CompletionCallback c = read_callback_; 417 read_callback_.Reset(); 418 c.Run(rv); 419} 420 421void UDPSocketWin::DoWriteCallback(int rv) { 422 DCHECK_NE(rv, ERR_IO_PENDING); 423 DCHECK(!write_callback_.is_null()); 424 425 // since Run may result in Write being called, clear write_callback_ up front. 426 CompletionCallback c = write_callback_; 427 write_callback_.Reset(); 428 c.Run(rv); 429} 430 431void UDPSocketWin::DidCompleteRead() { 432 DWORD num_bytes, flags; 433 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, 434 &num_bytes, FALSE, &flags); 435 WSAResetEvent(core_->read_overlapped_.hEvent); 436 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); 437 // Convert address. 438 if (recv_from_address_ && result >= 0) { 439 if (!ReceiveAddressToIPEndpoint(recv_from_address_)) 440 result = ERR_ADDRESS_INVALID; 441 } 442 LogRead(result, core_->read_iobuffer_->data()); 443 core_->read_iobuffer_ = NULL; 444 recv_from_address_ = NULL; 445 DoReadCallback(result); 446} 447 448void UDPSocketWin::LogRead(int result, const char* bytes) const { 449 if (result < 0) { 450 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); 451 return; 452 } 453 454 if (net_log_.IsLoggingAllEvents()) { 455 // Get address for logging, if |address| is NULL. 456 IPEndPoint address; 457 bool is_address_valid = ReceiveAddressToIPEndpoint(&address); 458 net_log_.AddEvent( 459 NetLog::TYPE_UDP_BYTES_RECEIVED, 460 CreateNetLogUDPDataTranferCallback( 461 result, bytes, 462 is_address_valid ? &address : NULL)); 463 } 464 465 base::StatsCounter read_bytes("udp.read_bytes"); 466 read_bytes.Add(result); 467} 468 469void UDPSocketWin::DidCompleteWrite() { 470 DWORD num_bytes, flags; 471 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, 472 &num_bytes, FALSE, &flags); 473 WSAResetEvent(core_->write_overlapped_.hEvent); 474 int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); 475 LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get()); 476 477 send_to_address_.reset(); 478 core_->write_iobuffer_ = NULL; 479 DoWriteCallback(result); 480} 481 482void UDPSocketWin::LogWrite(int result, 483 const char* bytes, 484 const IPEndPoint* address) const { 485 if (result < 0) { 486 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); 487 return; 488 } 489 490 if (net_log_.IsLoggingAllEvents()) { 491 net_log_.AddEvent( 492 NetLog::TYPE_UDP_BYTES_SENT, 493 CreateNetLogUDPDataTranferCallback(result, bytes, address)); 494 } 495 496 base::StatsCounter write_bytes("udp.write_bytes"); 497 write_bytes.Add(result); 498} 499 500int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, 501 IPEndPoint* address) { 502 DCHECK(!core_->read_iobuffer_); 503 SockaddrStorage& storage = core_->recv_addr_storage_; 504 storage.addr_len = sizeof(storage.addr_storage); 505 506 WSABUF read_buffer; 507 read_buffer.buf = buf->data(); 508 read_buffer.len = buf_len; 509 510 DWORD flags = 0; 511 DWORD num; 512 CHECK_NE(INVALID_SOCKET, socket_); 513 AssertEventNotSignaled(core_->read_overlapped_.hEvent); 514 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr, 515 &storage.addr_len, &core_->read_overlapped_, NULL); 516 if (rv == 0) { 517 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 518 int result = num; 519 // Convert address. 520 if (address && result >= 0) { 521 if (!ReceiveAddressToIPEndpoint(address)) 522 result = ERR_FAILED; 523 } 524 LogRead(result, buf->data()); 525 return result; 526 } 527 } else { 528 int os_error = WSAGetLastError(); 529 if (os_error != WSA_IO_PENDING) { 530 int result = MapSystemError(os_error); 531 LogRead(result, NULL); 532 return result; 533 } 534 } 535 core_->WatchForRead(); 536 core_->read_iobuffer_ = buf; 537 return ERR_IO_PENDING; 538} 539 540int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, 541 const IPEndPoint* address) { 542 DCHECK(!core_->write_iobuffer_); 543 SockaddrStorage storage; 544 struct sockaddr* addr = storage.addr; 545 // Convert address. 546 if (!address) { 547 addr = NULL; 548 storage.addr_len = 0; 549 } else { 550 if (!address->ToSockAddr(addr, &storage.addr_len)) { 551 int result = ERR_FAILED; 552 LogWrite(result, NULL, NULL); 553 return result; 554 } 555 } 556 557 WSABUF write_buffer; 558 write_buffer.buf = buf->data(); 559 write_buffer.len = buf_len; 560 561 DWORD flags = 0; 562 DWORD num; 563 AssertEventNotSignaled(core_->write_overlapped_.hEvent); 564 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, 565 addr, storage.addr_len, &core_->write_overlapped_, NULL); 566 if (rv == 0) { 567 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 568 int result = num; 569 LogWrite(result, buf->data(), address); 570 return result; 571 } 572 } else { 573 int os_error = WSAGetLastError(); 574 if (os_error != WSA_IO_PENDING) { 575 int result = MapSystemError(os_error); 576 LogWrite(result, NULL, NULL); 577 return result; 578 } 579 } 580 581 core_->WatchForWrite(); 582 core_->write_iobuffer_ = buf; 583 return ERR_IO_PENDING; 584} 585 586int UDPSocketWin::SetSocketOptions() { 587 BOOL true_value = 1; 588 if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) { 589 int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 590 reinterpret_cast<const char*>(&true_value), 591 sizeof(true_value)); 592 if (rv < 0) 593 return MapSystemError(WSAGetLastError()); 594 } 595 if (socket_options_ & SOCKET_OPTION_BROADCAST) { 596 int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, 597 reinterpret_cast<const char*>(&true_value), 598 sizeof(true_value)); 599 if (rv < 0) 600 return MapSystemError(WSAGetLastError()); 601 } 602 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) { 603 DWORD loop = 0; 604 int protocol_level = 605 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 606 int option = 607 addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP; 608 int rv = setsockopt(socket_, protocol_level, option, 609 reinterpret_cast<const char*>(&loop), sizeof(loop)); 610 if (rv < 0) 611 return MapSystemError(WSAGetLastError()); 612 } 613 if (multicast_time_to_live_ != 1) { 614 DWORD hops = multicast_time_to_live_; 615 int protocol_level = 616 addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 617 int option = 618 addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS; 619 int rv = setsockopt(socket_, protocol_level, option, 620 reinterpret_cast<const char*>(&hops), sizeof(hops)); 621 if (rv < 0) 622 return MapSystemError(WSAGetLastError()); 623 } 624 return OK; 625} 626 627int UDPSocketWin::DoBind(const IPEndPoint& address) { 628 SockaddrStorage storage; 629 if (!address.ToSockAddr(storage.addr, &storage.addr_len)) 630 return ERR_ADDRESS_INVALID; 631 int rv = bind(socket_, storage.addr, storage.addr_len); 632 return rv < 0 ? MapSystemError(WSAGetLastError()) : rv; 633} 634 635int UDPSocketWin::RandomBind(const IPEndPoint& address) { 636 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 637 638 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 639 IPAddressNumber ip(address.address().size()); 640 641 for (int i = 0; i < kBindRetries; ++i) { 642 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 643 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 644 return rv; 645 } 646 return DoBind(IPEndPoint(ip, 0)); 647} 648 649bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { 650 SockaddrStorage& storage = core_->recv_addr_storage_; 651 return address->FromSockAddr(storage.addr, storage.addr_len); 652} 653 654int UDPSocketWin::JoinGroup( 655 const IPAddressNumber& group_address) const { 656 DCHECK(CalledOnValidThread()); 657 if (!is_connected()) 658 return ERR_SOCKET_NOT_CONNECTED; 659 660 switch (group_address.size()) { 661 case kIPv4AddressSize: { 662 if (addr_family_ != AF_INET) 663 return ERR_ADDRESS_INVALID; 664 ip_mreq mreq; 665 mreq.imr_interface.s_addr = INADDR_ANY; 666 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); 667 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, 668 reinterpret_cast<const char*>(&mreq), 669 sizeof(mreq)); 670 if (rv) 671 return MapSystemError(WSAGetLastError()); 672 return OK; 673 } 674 case kIPv6AddressSize: { 675 if (addr_family_ != AF_INET6) 676 return ERR_ADDRESS_INVALID; 677 ipv6_mreq mreq; 678 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. 679 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); 680 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, 681 reinterpret_cast<const char*>(&mreq), 682 sizeof(mreq)); 683 if (rv) 684 return MapSystemError(WSAGetLastError()); 685 return OK; 686 } 687 default: 688 NOTREACHED() << "Invalid address family"; 689 return ERR_ADDRESS_INVALID; 690 } 691} 692 693int UDPSocketWin::LeaveGroup( 694 const IPAddressNumber& group_address) const { 695 DCHECK(CalledOnValidThread()); 696 if (!is_connected()) 697 return ERR_SOCKET_NOT_CONNECTED; 698 699 switch (group_address.size()) { 700 case kIPv4AddressSize: { 701 if (addr_family_ != AF_INET) 702 return ERR_ADDRESS_INVALID; 703 ip_mreq mreq; 704 mreq.imr_interface.s_addr = INADDR_ANY; 705 memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize); 706 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP, 707 reinterpret_cast<const char*>(&mreq), 708 sizeof(mreq)); 709 if (rv) 710 return MapSystemError(WSAGetLastError()); 711 return OK; 712 } 713 case kIPv6AddressSize: { 714 if (addr_family_ != AF_INET6) 715 return ERR_ADDRESS_INVALID; 716 ipv6_mreq mreq; 717 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface. 718 memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize); 719 int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP, 720 reinterpret_cast<const char*>(&mreq), 721 sizeof(mreq)); 722 if (rv) 723 return MapSystemError(WSAGetLastError()); 724 return OK; 725 } 726 default: 727 NOTREACHED() << "Invalid address family"; 728 return ERR_ADDRESS_INVALID; 729 } 730} 731 732int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) { 733 DCHECK(CalledOnValidThread()); 734 if (is_connected()) 735 return ERR_SOCKET_IS_CONNECTED; 736 737 if (time_to_live < 0 || time_to_live > 255) 738 return ERR_INVALID_ARGUMENT; 739 multicast_time_to_live_ = time_to_live; 740 return OK; 741} 742 743int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) { 744 DCHECK(CalledOnValidThread()); 745 if (is_connected()) 746 return ERR_SOCKET_IS_CONNECTED; 747 748 if (loopback) 749 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP; 750 else 751 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP; 752 return OK; 753} 754 755} // namespace net 756