// 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/address_sorter.h"

#include <winsock2.h>

#include <algorithm>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/threading/worker_pool.h"
#include "base/win/windows_version.h"
#include "net/base/address_list.h"
#include "net/base/ip_endpoint.h"
#include "net/base/winsock_init.h"

namespace net {

namespace {

class AddressSorterWin : public AddressSorter {
 public:
  AddressSorterWin() {
    EnsureWinsockInit();
  }

  virtual ~AddressSorterWin() {}

  // AddressSorter:
  virtual void Sort(const AddressList& list,
                    const CallbackType& callback) const OVERRIDE {
    DCHECK(!list.empty());
    scoped_refptr<Job> job = new Job(list, callback);
  }

 private:
  // Executes the SIO_ADDRESS_LIST_SORT ioctl on the WorkerPool, and
  // performs the necessary conversions to/from AddressList.
  class Job : public base::RefCountedThreadSafe<Job> {
   public:
    Job(const AddressList& list, const CallbackType& callback)
        : callback_(callback),
          buffer_size_(sizeof(SOCKET_ADDRESS_LIST) +
                       list.size() * (sizeof(SOCKET_ADDRESS) +
                                      sizeof(SOCKADDR_STORAGE))),
          input_buffer_(reinterpret_cast<SOCKET_ADDRESS_LIST*>(
              malloc(buffer_size_))),
          output_buffer_(reinterpret_cast<SOCKET_ADDRESS_LIST*>(
              malloc(buffer_size_))),
          success_(false) {
      input_buffer_->iAddressCount = list.size();
      SOCKADDR_STORAGE* storage = reinterpret_cast<SOCKADDR_STORAGE*>(
          input_buffer_->Address + input_buffer_->iAddressCount);

      for (size_t i = 0; i < list.size(); ++i) {
        IPEndPoint ipe = list[i];
        // Addresses must be sockaddr_in6.
        if (ipe.GetFamily() == ADDRESS_FAMILY_IPV4) {
          ipe = IPEndPoint(ConvertIPv4NumberToIPv6Number(ipe.address()),
                           ipe.port());
        }

        struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(storage + i);
        socklen_t addr_len = sizeof(SOCKADDR_STORAGE);
        bool result = ipe.ToSockAddr(addr, &addr_len);
        DCHECK(result);
        input_buffer_->Address[i].lpSockaddr = addr;
        input_buffer_->Address[i].iSockaddrLength = addr_len;
      }

      if (!base::WorkerPool::PostTaskAndReply(
          FROM_HERE,
          base::Bind(&Job::Run, this),
          base::Bind(&Job::OnComplete, this),
          false /* task is slow */)) {
        LOG(ERROR) << "WorkerPool::PostTaskAndReply failed";
        OnComplete();
      }
    }

   private:
    friend class base::RefCountedThreadSafe<Job>;
    ~Job() {}

    // Executed on the WorkerPool.
    void Run() {
      SOCKET sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
      if (sock == INVALID_SOCKET)
        return;
      DWORD result_size = 0;
      int result = WSAIoctl(sock, SIO_ADDRESS_LIST_SORT, input_buffer_.get(),
                            buffer_size_, output_buffer_.get(), buffer_size_,
                            &result_size, NULL, NULL);
      if (result == SOCKET_ERROR) {
        LOG(ERROR) << "SIO_ADDRESS_LIST_SORT failed " << WSAGetLastError();
      } else {
        success_ = true;
      }
      closesocket(sock);
    }

    // Executed on the calling thread.
    void OnComplete() {
      AddressList list;
      if (success_) {
        list.reserve(output_buffer_->iAddressCount);
        for (int i = 0; i < output_buffer_->iAddressCount; ++i) {
          IPEndPoint ipe;
          ipe.FromSockAddr(output_buffer_->Address[i].lpSockaddr,
                           output_buffer_->Address[i].iSockaddrLength);
          // Unmap V4MAPPED IPv6 addresses so that Happy Eyeballs works.
          if (IsIPv4Mapped(ipe.address())) {
            ipe = IPEndPoint(ConvertIPv4MappedToIPv4(ipe.address()),
                                                     ipe.port());
          }
          list.push_back(ipe);
        }
      }
      callback_.Run(success_, list);
    }

    const CallbackType callback_;
    const size_t buffer_size_;
    scoped_ptr<SOCKET_ADDRESS_LIST, base::FreeDeleter> input_buffer_;
    scoped_ptr<SOCKET_ADDRESS_LIST, base::FreeDeleter> output_buffer_;
    bool success_;

    DISALLOW_COPY_AND_ASSIGN(Job);
  };

  DISALLOW_COPY_AND_ASSIGN(AddressSorterWin);
};

// Merges |list_ipv4| and |list_ipv6| before passing it to |callback|, but
// only if |success| is true.
void MergeResults(const AddressSorter::CallbackType& callback,
                  const AddressList& list_ipv4,
                  bool success,
                  const AddressList& list_ipv6) {
  if (!success) {
    callback.Run(false, AddressList());
    return;
  }
  AddressList list;
  list.insert(list.end(), list_ipv6.begin(), list_ipv6.end());
  list.insert(list.end(), list_ipv4.begin(), list_ipv4.end());
  callback.Run(true, list);
}

// Wrapper for AddressSorterWin which does not sort IPv4 or IPv4-mapped
// addresses but always puts them at the end of the list. Needed because the
// SIO_ADDRESS_LIST_SORT does not support IPv4 addresses on Windows XP.
class AddressSorterWinXP : public AddressSorter {
 public:
  AddressSorterWinXP() {}
  virtual ~AddressSorterWinXP() {}

  // AddressSorter:
  virtual void Sort(const AddressList& list,
                    const CallbackType& callback) const OVERRIDE {
    AddressList list_ipv4;
    AddressList list_ipv6;
    for (size_t i = 0; i < list.size(); ++i) {
      const IPEndPoint& ipe = list[i];
      if (ipe.GetFamily() == ADDRESS_FAMILY_IPV4) {
        list_ipv4.push_back(ipe);
      } else {
        list_ipv6.push_back(ipe);
      }
    }
    if (!list_ipv6.empty()) {
      sorter_.Sort(list_ipv6, base::Bind(&MergeResults, callback, list_ipv4));
    } else {
      NOTREACHED() << "Should not be called with IPv4-only addresses.";
      callback.Run(true, list);
    }
  }

 private:
  AddressSorterWin sorter_;

  DISALLOW_COPY_AND_ASSIGN(AddressSorterWinXP);
};

}  // namespace

// static
scoped_ptr<AddressSorter> AddressSorter::CreateAddressSorter() {
  if (base::win::GetVersion() < base::win::VERSION_VISTA)
    return scoped_ptr<AddressSorter>(new AddressSorterWinXP());
  return scoped_ptr<AddressSorter>(new AddressSorterWin());
}

}  // namespace net

