// Copyright (c) 2016 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/third_party/quic/platform/impl/quic_ip_address_impl.h"

#include "build/build_config.h"
#include "net/base/address_family.h"
#include "net/third_party/quic/platform/api/quic_bug_tracker.h"

#if defined(OS_WIN)
#include <winsock2.h>
#include <ws2bth.h>
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <netinet/in.h>

#include "starboard/types.h"
#endif

using std::string;

namespace quic {

QuicIpAddressImpl QuicIpAddressImpl::Loopback4() {
  return QuicIpAddressImpl(net::IPAddress::IPv4Localhost());
}

QuicIpAddressImpl QuicIpAddressImpl::Loopback6() {
  return QuicIpAddressImpl(net::IPAddress::IPv6Localhost());
}

QuicIpAddressImpl QuicIpAddressImpl::Any4() {
  return QuicIpAddressImpl(net::IPAddress::IPv4AllZeros());
}

QuicIpAddressImpl QuicIpAddressImpl::Any6() {
  return QuicIpAddressImpl(net::IPAddress::IPv6AllZeros());
}

QuicIpAddressImpl::QuicIpAddressImpl(const net::IPAddress& addr)
    : ip_address_(addr) {}

bool operator==(QuicIpAddressImpl lhs, QuicIpAddressImpl rhs) {
  return lhs.ip_address_ == rhs.ip_address_;
}

bool operator!=(QuicIpAddressImpl lhs, QuicIpAddressImpl rhs) {
  return !(lhs == rhs);
}

bool QuicIpAddressImpl::IsInitialized() const {
  return net::GetAddressFamily(ip_address_) != net::ADDRESS_FAMILY_UNSPECIFIED;
}

IpAddressFamily QuicIpAddressImpl::address_family() const {
  switch (net::GetAddressFamily(ip_address_)) {
    case net::ADDRESS_FAMILY_IPV4:
      return IpAddressFamily::IP_V4;
    case net::ADDRESS_FAMILY_IPV6:
      return IpAddressFamily::IP_V6;
    case net::ADDRESS_FAMILY_UNSPECIFIED:
      break;
    default:
      QUIC_BUG << "Invalid address family "
               << net::GetAddressFamily(ip_address_);
  }
  return IpAddressFamily::IP_UNSPEC;
}

#if !defined(STARBOARD)
int QuicIpAddressImpl::AddressFamilyToInt() const {
  switch (ip_address_.size()) {
    case net::IPAddress::kIPv4AddressSize:
      return AF_INET;
    case net::IPAddress::kIPv6AddressSize:
      return AF_INET6;
    default:
      NOTREACHED() << "Bad IP address";
      return AF_UNSPEC;
  }
}
#endif

string QuicIpAddressImpl::ToPackedString() const {
  return net::IPAddressToPackedString(ip_address_);
}

string QuicIpAddressImpl::ToString() const {
  if (!IsInitialized()) {
    return "Uninitialized address";
  }
  return ip_address_.ToString();
}

QuicIpAddressImpl QuicIpAddressImpl::Normalized() const {
  if (ip_address_.IsIPv4MappedIPv6()) {
    return QuicIpAddressImpl(ConvertIPv4MappedIPv6ToIPv4(ip_address_));
  }
  return QuicIpAddressImpl(ip_address_);
}

QuicIpAddressImpl QuicIpAddressImpl::DualStacked() const {
  if (ip_address_.IsIPv4()) {
    return QuicIpAddressImpl(ConvertIPv4ToIPv4MappedIPv6(ip_address_));
  }
  return QuicIpAddressImpl(ip_address_);
}

bool QuicIpAddressImpl::FromPackedString(const char* data, size_t length) {
  if (length != net::IPAddress::kIPv4AddressSize &&
      length != net::IPAddress::kIPv6AddressSize) {
    QUIC_BUG << "Invalid packed IP address of length " << length;
    return false;
  }
  ip_address_ = net::IPAddress(reinterpret_cast<const uint8_t*>(data), length);
  return true;
}

bool QuicIpAddressImpl::FromString(string str) {
  return ip_address_.AssignFromIPLiteral(str);
}

bool QuicIpAddressImpl::IsIPv4() const {
  return ip_address_.IsIPv4();
}

bool QuicIpAddressImpl::IsIPv6() const {
  return ip_address_.IsIPv6();
}

bool QuicIpAddressImpl::InSameSubnet(const QuicIpAddressImpl& other,
                                     int subnet_length) {
  return net::IPAddressMatchesPrefix(ip_address_, other.ip_address(),
                                     subnet_length);
}

}  // namespace quic
