// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/dns/dns_socket_pool.h"

#include "base/logging.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "net/base/address_list.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/rand_callback.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/stream_socket.h"
#include "net/udp/datagram_client_socket.h"

namespace net {

namespace {

// When we initialize the SocketPool, we allocate kInitialPoolSize sockets.
// When we allocate a socket, we ensure we have at least kAllocateMinSize
// sockets to choose from.  Freed sockets are not retained.

// On Windows, we can't request specific (random) ports, since that will
// trigger firewall prompts, so request default ones, but keep a pile of
// them.  Everywhere else, request fresh, random ports each time.
#if defined(OS_WIN)
const DatagramSocket::BindType kBindType = DatagramSocket::DEFAULT_BIND;
const unsigned kInitialPoolSize = 256;
const unsigned kAllocateMinSize = 256;
#else
const DatagramSocket::BindType kBindType = DatagramSocket::RANDOM_BIND;
const unsigned kInitialPoolSize = 0;
const unsigned kAllocateMinSize = 1;
#endif

} // namespace

DnsSocketPool::DnsSocketPool(ClientSocketFactory* socket_factory)
    : socket_factory_(socket_factory),
      net_log_(NULL),
      nameservers_(NULL),
      initialized_(false) {
}

void DnsSocketPool::InitializeInternal(
    const std::vector<IPEndPoint>* nameservers,
    NetLog* net_log) {
  DCHECK(nameservers);
  DCHECK(!initialized_);

  net_log_ = net_log;
  nameservers_ = nameservers;
  initialized_ = true;
}

scoped_ptr<StreamSocket> DnsSocketPool::CreateTCPSocket(
    unsigned server_index,
    const NetLog::Source& source) {
  DCHECK_LT(server_index, nameservers_->size());

  return scoped_ptr<StreamSocket>(
      socket_factory_->CreateTransportClientSocket(
          AddressList((*nameservers_)[server_index]), net_log_, source));
}

scoped_ptr<DatagramClientSocket> DnsSocketPool::CreateConnectedSocket(
    unsigned server_index) {
  DCHECK_LT(server_index, nameservers_->size());

  scoped_ptr<DatagramClientSocket> socket;

  NetLog::Source no_source;
  socket = socket_factory_->CreateDatagramClientSocket(
      kBindType, base::Bind(&base::RandInt), net_log_, no_source);

  if (socket.get()) {
    int rv = socket->Connect((*nameservers_)[server_index]);
    if (rv != OK) {
      VLOG(1) << "Failed to connect socket: " << rv;
      socket.reset();
    }
  } else {
    LOG(WARNING) << "Failed to create socket.";
  }

  return socket.Pass();
}

class NullDnsSocketPool : public DnsSocketPool {
 public:
  NullDnsSocketPool(ClientSocketFactory* factory)
     : DnsSocketPool(factory) {
  }

  virtual void Initialize(
      const std::vector<IPEndPoint>* nameservers,
      NetLog* net_log) OVERRIDE {
    InitializeInternal(nameservers, net_log);
  }

  virtual scoped_ptr<DatagramClientSocket> AllocateSocket(
      unsigned server_index) OVERRIDE {
    return CreateConnectedSocket(server_index);
  }

  virtual void FreeSocket(
      unsigned server_index,
      scoped_ptr<DatagramClientSocket> socket) OVERRIDE {
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(NullDnsSocketPool);
};

// static
scoped_ptr<DnsSocketPool> DnsSocketPool::CreateNull(
    ClientSocketFactory* factory) {
  return scoped_ptr<DnsSocketPool>(new NullDnsSocketPool(factory));
}

class DefaultDnsSocketPool : public DnsSocketPool {
 public:
  DefaultDnsSocketPool(ClientSocketFactory* factory)
     : DnsSocketPool(factory) {
  };

  virtual ~DefaultDnsSocketPool();

  virtual void Initialize(
      const std::vector<IPEndPoint>* nameservers,
      NetLog* net_log) OVERRIDE;

  virtual scoped_ptr<DatagramClientSocket> AllocateSocket(
      unsigned server_index) OVERRIDE;

  virtual void FreeSocket(
      unsigned server_index,
      scoped_ptr<DatagramClientSocket> socket) OVERRIDE;

 private:
  void FillPool(unsigned server_index, unsigned size);

  typedef std::vector<DatagramClientSocket*> SocketVector;

  std::vector<SocketVector> pools_;

  DISALLOW_COPY_AND_ASSIGN(DefaultDnsSocketPool);
};

// static
scoped_ptr<DnsSocketPool> DnsSocketPool::CreateDefault(
    ClientSocketFactory* factory) {
  return scoped_ptr<DnsSocketPool>(new DefaultDnsSocketPool(factory));
}

void DefaultDnsSocketPool::Initialize(
    const std::vector<IPEndPoint>* nameservers,
    NetLog* net_log) {
  InitializeInternal(nameservers, net_log);

  DCHECK(pools_.empty());
  const unsigned num_servers = nameservers->size();
  pools_.resize(num_servers);
  for (unsigned server_index = 0; server_index < num_servers; ++server_index)
    FillPool(server_index, kInitialPoolSize);
}

DefaultDnsSocketPool::~DefaultDnsSocketPool() {
  unsigned num_servers = pools_.size();
  for (unsigned server_index = 0; server_index < num_servers; ++server_index) {
    SocketVector& pool = pools_[server_index];
    STLDeleteElements(&pool);
  }
}

scoped_ptr<DatagramClientSocket> DefaultDnsSocketPool::AllocateSocket(
    unsigned server_index) {
  DCHECK_LT(server_index, pools_.size());
  SocketVector& pool = pools_[server_index];

  FillPool(server_index, kAllocateMinSize);
  if (pool.size() == 0) {
    LOG(WARNING) << "No DNS sockets available in pool " << server_index << "!";
    return scoped_ptr<DatagramClientSocket>();
  }

  if (pool.size() < kAllocateMinSize) {
    LOG(WARNING) << "Low DNS port entropy: wanted " << kAllocateMinSize
                 << " sockets to choose from, but only have " << pool.size()
                 << " in pool " << server_index << ".";
  }

  unsigned socket_index = base::RandInt(0, pool.size() - 1);
  DatagramClientSocket* socket = pool[socket_index];
  pool[socket_index] = pool.back();
  pool.pop_back();

  return scoped_ptr<DatagramClientSocket>(socket);
}

void DefaultDnsSocketPool::FreeSocket(
    unsigned server_index,
    scoped_ptr<DatagramClientSocket> socket) {
  DCHECK_LT(server_index, pools_.size());
}

void DefaultDnsSocketPool::FillPool(unsigned server_index, unsigned size) {
  SocketVector& pool = pools_[server_index];

  for (unsigned pool_index = pool.size(); pool_index < size; ++pool_index) {
    DatagramClientSocket* socket =
        CreateConnectedSocket(server_index).release();
    if (!socket)
      break;
    pool.push_back(socket);
  }
}

} // namespace net
