15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/udp_socket_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <mstcpip.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/udp/udp_net_log_parameters.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kBindRetries = 10;
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kPortStart = 1024;
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kPortEnd = 65535;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class encapsulates all the state that has to be preserved as long as
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// there is a network IO operation in progress. If the owner UDPSocketWin
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is destroyed while an operation is in progress, the Core is detached and it
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lives until the operation completes and the OS doesn't reference any resource
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// declared on this class anymore.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UDPSocketWin::Core : public base::RefCounted<Core> {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit Core(UDPSocketWin* socket);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start watching for the end of a read or write operation.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WatchForRead();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WatchForWrite();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The UDPSocketWin is going away.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Detach() { socket_ = NULL; }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The separate OVERLAPPED variables for asynchronous operation.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OVERLAPPED read_overlapped_;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OVERLAPPED write_overlapped_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The buffers used in Read() and Write().
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> read_iobuffer_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> write_iobuffer_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The address storage passed to WSARecvFrom().
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage recv_addr_storage_;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<Core>;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class ReadDelegate : public base::win::ObjectWatcher::Delegate {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit ReadDelegate(Core* core) : core_(core) {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~ReadDelegate() {}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // base::ObjectWatcher::Delegate methods:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnObjectSignaled(HANDLE object);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Core* const core_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class WriteDelegate : public base::win::ObjectWatcher::Delegate {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    explicit WriteDelegate(Core* core) : core_(core) {}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~WriteDelegate() {}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // base::ObjectWatcher::Delegate methods:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnObjectSignaled(HANDLE object);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Core* const core_;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Core();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The socket that created this object.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UDPSocketWin* socket_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |reader_| handles the signals from |read_watcher_|.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadDelegate reader_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |writer_| handles the signals from |write_watcher_|.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteDelegate writer_;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |read_watcher_| watches for events from Read().
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ObjectWatcher read_watcher_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |write_watcher_| watches for events from Write();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ObjectWatcher write_watcher_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Core);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::Core::Core(UDPSocketWin* socket)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : socket_(socket),
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      reader_(this),
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      writer_(this) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&read_overlapped_, 0, sizeof(read_overlapped_));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&write_overlapped_, 0, sizeof(write_overlapped_));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_overlapped_.hEvent = WSACreateEvent();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_overlapped_.hEvent = WSACreateEvent();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::Core::~Core() {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the message loop is not watching this object anymore.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_watcher_.StopWatching();
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_watcher_.StopWatching();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSACloseEvent(read_overlapped_.hEvent);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&read_overlapped_, 0xaf, sizeof(read_overlapped_));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSACloseEvent(write_overlapped_.hEvent);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&write_overlapped_, 0xaf, sizeof(write_overlapped_));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::WatchForRead() {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We grab an extra reference because there is an IO operation in progress.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balanced in ReadDelegate::OnObjectSignaled().
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_watcher_.StartWatching(read_overlapped_.hEvent, &reader_);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::WatchForWrite() {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We grab an extra reference because there is an IO operation in progress.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Balanced in WriteDelegate::OnObjectSignaled().
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddRef();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_watcher_.StartWatching(write_overlapped_.hEvent, &writer_);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::ReadDelegate::OnObjectSignaled(HANDLE object) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(object, core_->read_overlapped_.hEvent);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core_->socket_)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_->socket_->DidCompleteRead();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Release();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Core::WriteDelegate::OnObjectSignaled(HANDLE object) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(object, core_->write_overlapped_.hEvent);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (core_->socket_)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    core_->socket_->DidCompleteWrite();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Release();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const RandIntCallback& rand_int_cb,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           net::NetLog* net_log,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const net::NetLog::Source& source)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : socket_(INVALID_SOCKET),
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      addr_family_(0),
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      multicast_time_to_live_(1),
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bind_type_(bind_type),
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rand_int_cb_(rand_int_cb),
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recv_from_address_(NULL),
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureWinsockInit();
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      source.ToEventParametersCallback());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bind_type == DatagramSocket::RANDOM_BIND)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!rand_int_cb.is_null());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UDPSocketWin::~UDPSocketWin() {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Close();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::Close() {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_connected())
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Zero out any pending read/write callback state.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_callback_.Reset();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_from_address_ = NULL;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_callback_.Reset();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks start_time = base::TimeTicks::Now();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  closesocket(socket_);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UMA_HISTOGRAM_TIMES("Net.UDPSocketWinClose",
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::TimeTicks::Now() - start_time);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_ = INVALID_SOCKET;
2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  addr_family_ = 0;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->Detach();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_ = NULL;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(address);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_connected())
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(szym): Simplify. http://crbug.com/126152
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!remote_address_.get()) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SockaddrStorage storage;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (getpeername(socket_, storage.addr, &storage.addr_len))
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapSystemError(WSAGetLastError());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<IPEndPoint> address(new IPEndPoint());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!address->FromSockAddr(storage.addr, storage.addr_len))
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return ERR_ADDRESS_INVALID;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remote_address_.reset(address.release());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *address = *remote_address_;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(address);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_connected())
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(szym): Simplify. http://crbug.com/126152
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!local_address_.get()) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SockaddrStorage storage;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (getsockname(socket_, storage.addr, &storage.addr_len))
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapSystemError(WSAGetLastError());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<IPEndPoint> address(new IPEndPoint());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!address->FromSockAddr(storage.addr, storage.addr_len))
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return ERR_ADDRESS_INVALID;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    local_address_.reset(address.release());
243a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
244a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                      CreateNetLogUDPConnectCallback(local_address_.get()));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *address = *local_address_;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Read(IOBuffer* buf,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int buf_len,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const CompletionCallback& callback) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RecvFrom(buf, buf_len, NULL, callback);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::RecvFrom(IOBuffer* buf,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int buf_len,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           IPEndPoint* address,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const CompletionCallback& callback) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(INVALID_SOCKET, socket_);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(read_callback_.is_null());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!recv_from_address_);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());  // Synchronous operation not supported.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nread = InternalRecvFrom(buf, buf_len, address);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nread != ERR_IO_PENDING)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return nread;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_callback_ = callback;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_from_address_ = address;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Write(IOBuffer* buf,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int buf_len,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const CompletionCallback& callback) {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SendToOrWrite(buf, buf_len, NULL, callback);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::SendTo(IOBuffer* buf,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int buf_len,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const IPEndPoint& address,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const CompletionCallback& callback) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SendToOrWrite(buf, buf_len, &address, callback);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::SendToOrWrite(IOBuffer* buf,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int buf_len,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const IPEndPoint* address,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const CompletionCallback& callback) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(INVALID_SOCKET, socket_);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(write_callback_.is_null());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());  // Synchronous operation not supported.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(buf_len, 0);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!send_to_address_.get());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nwrite = InternalSendTo(buf, buf_len, address);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nwrite != ERR_IO_PENDING)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return nwrite;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    send_to_address_.reset(new IPEndPoint(*address));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_callback_ = callback;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Connect(const IPEndPoint& address) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_UDP_CONNECT,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CreateNetLogUDPConnectCallback(&address));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = InternalConnect(address);
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv != OK)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Close();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_connected());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!remote_address_.get());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = CreateSocket(address);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv < 0)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bind_type_ == DatagramSocket::RANDOM_BIND)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = RandomBind(address);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // else connect() does the DatagramSocket::DEFAULT_BIND
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (rv < 0) {
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Close();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage storage;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!address.ToSockAddr(storage.addr, &storage.addr_len))
3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return ERR_ADDRESS_INVALID;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = connect(socket_, storage.addr, storage.addr_len);
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (rv < 0) {
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Close() may change the last error. Map it beforehand.
3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int result = MapSystemError(WSAGetLastError());
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Close();
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return result;
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remote_address_.reset(new IPEndPoint(address));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::Bind(const IPEndPoint& address) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_connected());
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = CreateSocket(address);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv < 0)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SetSocketOptions();
3597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (rv < 0) {
3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Close();
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
3627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = DoBind(address);
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (rv < 0) {
3657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Close();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  local_address_.reset();
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::CreateSocket(const IPEndPoint& address) {
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  addr_family_ = address.GetSockAddrFamily();
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (socket_ == INVALID_SOCKET)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapSystemError(WSAGetLastError());
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_ = new Core(this);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UDPSocketWin::SetReceiveBufferSize(int32 size) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      reinterpret_cast<const char*>(&size), sizeof(size));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv == 0;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UDPSocketWin::SetSendBufferSize(int32 size) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      reinterpret_cast<const char*>(&size), sizeof(size));
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv == 0;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::AllowAddressReuse() {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_connected());
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_options_ |= SOCKET_OPTION_REUSE_ADDRESS;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::AllowBroadcast() {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_connected());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket_options_ |= SOCKET_OPTION_BROADCAST;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DoReadCallback(int rv) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!read_callback_.is_null());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since Run may result in Read being called, clear read_callback_ up front.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback c = read_callback_;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_callback_.Reset();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  c.Run(rv);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DoWriteCallback(int rv) {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!write_callback_.is_null());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since Run may result in Write being called, clear write_callback_ up front.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback c = write_callback_;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_callback_.Reset();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  c.Run(rv);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DidCompleteRead() {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD num_bytes, flags;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &num_bytes, FALSE, &flags);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSAResetEvent(core_->read_overlapped_.hEvent);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert address.
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (recv_from_address_ && result >= 0) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ReceiveAddressToIPEndpoint(recv_from_address_))
4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      result = ERR_ADDRESS_INVALID;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogRead(result, core_->read_iobuffer_->data());
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->read_iobuffer_ = NULL;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_from_address_ = NULL;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoReadCallback(result);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::LogRead(int result, const char* bytes) const {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents()) {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get address for logging, if |address| is NULL.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPEndPoint address;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_address_valid = ReceiveAddressToIPEndpoint(&address);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_UDP_BYTES_RECEIVED,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogUDPDataTranferCallback(
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result, bytes,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            is_address_valid ? &address : NULL));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StatsCounter read_bytes("udp.read_bytes");
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_bytes.Add(result);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::DidCompleteWrite() {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD num_bytes, flags;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &num_bytes, FALSE, &flags);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSAResetEvent(core_->write_overlapped_.hEvent);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = ok ? num_bytes : MapSystemError(WSAGetLastError());
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogWrite(result, core_->write_iobuffer_->data(), send_to_address_.get());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  send_to_address_.reset();
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->write_iobuffer_ = NULL;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoWriteCallback(result);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UDPSocketWin::LogWrite(int result,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const char* bytes,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const IPEndPoint* address) const {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_.IsLoggingAllEvents()) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_UDP_BYTES_SENT,
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateNetLogUDPDataTranferCallback(result, bytes, address));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StatsCounter write_bytes("udp.write_bytes");
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_bytes.Add(result);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   IPEndPoint* address) {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!core_->read_iobuffer_);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage& storage = core_->recv_addr_storage_;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  storage.addr_len = sizeof(storage.addr_storage);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSABUF read_buffer;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.buf = buf->data();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer.len = buf_len;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD flags = 0;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD num;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_NE(INVALID_SOCKET, socket_);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertEventNotSignaled(core_->read_overlapped_.hEvent);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, storage.addr,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &storage.addr_len, &core_->read_overlapped_, NULL);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == 0) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = num;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Convert address.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (address && result >= 0) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ReceiveAddressToIPEndpoint(address))
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result = ERR_FAILED;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogRead(result, buf->data());
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int os_error = WSAGetLastError();
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (os_error != WSA_IO_PENDING) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = MapSystemError(os_error);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogRead(result, NULL);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->WatchForRead();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->read_iobuffer_ = buf;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len,
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const IPEndPoint* address) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!core_->write_iobuffer_);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage storage;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sockaddr* addr = storage.addr;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert address.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!address) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    addr = NULL;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    storage.addr_len = 0;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!address->ToSockAddr(addr, &storage.addr_len)) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = ERR_FAILED;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogWrite(result, NULL, NULL);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSABUF write_buffer;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_buffer.buf = buf->data();
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  write_buffer.len = buf_len;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD flags = 0;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD num;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AssertEventNotSignaled(core_->write_overlapped_.hEvent);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     addr, storage.addr_len, &core_->write_overlapped_, NULL);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == 0) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = num;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogWrite(result, buf->data(), address);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int os_error = WSAGetLastError();
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (os_error != WSA_IO_PENDING) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result = MapSystemError(os_error);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogWrite(result, NULL, NULL);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->WatchForWrite();
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_->write_iobuffer_ = buf;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::SetSocketOptions() {
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL true_value = 1;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (socket_options_ & SOCKET_OPTION_REUSE_ADDRESS) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        reinterpret_cast<const char*>(&true_value),
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(true_value));
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv < 0)
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return MapSystemError(WSAGetLastError());
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (socket_options_ & SOCKET_OPTION_BROADCAST) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST,
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        reinterpret_cast<const char*>(&true_value),
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        sizeof(true_value));
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv < 0)
600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return MapSystemError(WSAGetLastError());
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DWORD loop = 0;
604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int protocol_level =
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int option =
607c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        addr_family_ == AF_INET ? IP_MULTICAST_LOOP: IPV6_MULTICAST_LOOP;
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int rv = setsockopt(socket_, protocol_level, option,
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        reinterpret_cast<const char*>(&loop), sizeof(loop));
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (rv < 0)
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return MapSystemError(WSAGetLastError());
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (multicast_time_to_live_ != 1) {
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DWORD hops = multicast_time_to_live_;
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int protocol_level =
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        addr_family_ == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int option =
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        addr_family_ == AF_INET ? IP_MULTICAST_TTL: IPV6_MULTICAST_HOPS;
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int rv = setsockopt(socket_, protocol_level, option,
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        reinterpret_cast<const char*>(&hops), sizeof(hops));
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (rv < 0)
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return MapSystemError(WSAGetLastError());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::DoBind(const IPEndPoint& address) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage storage;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!address.ToSockAddr(storage.addr, &storage.addr_len))
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_ADDRESS_INVALID;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = bind(socket_, storage.addr, storage.addr_len);
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv < 0 ? MapSystemError(WSAGetLastError()) : rv;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UDPSocketWin::RandomBind(const IPEndPoint& address) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ip(address.address().size());
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kBindRetries; ++i) {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == OK || rv != ERR_ADDRESS_IN_USE)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rv;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DoBind(IPEndPoint(ip, 0));
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SockaddrStorage& storage = core_->recv_addr_storage_;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return address->FromSockAddr(storage.addr, storage.addr_len);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::JoinGroup(
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPAddressNumber& group_address) const {
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!is_connected())
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (group_address.size()) {
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kIPv4AddressSize: {
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (addr_family_ != AF_INET)
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return ERR_ADDRESS_INVALID;
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ip_mreq mreq;
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mreq.imr_interface.s_addr = INADDR_ANY;
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          reinterpret_cast<const char*>(&mreq),
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          sizeof(mreq));
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (rv)
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return MapSystemError(WSAGetLastError());
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return OK;
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kIPv6AddressSize: {
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (addr_family_ != AF_INET6)
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return ERR_ADDRESS_INVALID;
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ipv6_mreq mreq;
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mreq.ipv6mr_interface = 0;  // 0 indicates default multicast interface.
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          reinterpret_cast<const char*>(&mreq),
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          sizeof(mreq));
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (rv)
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return MapSystemError(WSAGetLastError());
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return OK;
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED() << "Invalid address family";
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ERR_ADDRESS_INVALID;
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::LeaveGroup(
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const IPAddressNumber& group_address) const {
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!is_connected())
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (group_address.size()) {
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kIPv4AddressSize: {
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (addr_family_ != AF_INET)
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return ERR_ADDRESS_INVALID;
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ip_mreq mreq;
704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mreq.imr_interface.s_addr = INADDR_ANY;
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      reinterpret_cast<const char*>(&mreq),
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      sizeof(mreq));
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (rv)
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return MapSystemError(WSAGetLastError());
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return OK;
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kIPv6AddressSize: {
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (addr_family_ != AF_INET6)
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return ERR_ADDRESS_INVALID;
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ipv6_mreq mreq;
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      mreq.ipv6mr_interface = 0;  // 0 indicates default multicast interface.
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      reinterpret_cast<const char*>(&mreq),
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      sizeof(mreq));
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (rv)
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return MapSystemError(WSAGetLastError());
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return OK;
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    default:
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED() << "Invalid address family";
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return ERR_ADDRESS_INVALID;
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_connected())
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_SOCKET_IS_CONNECTED;
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (time_to_live < 0 || time_to_live > 255)
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_INVALID_ARGUMENT;
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  multicast_time_to_live_ = time_to_live;
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return OK;
741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(CalledOnValidThread());
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (is_connected())
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return ERR_SOCKET_IS_CONNECTED;
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (loopback)
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return OK;
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
756