// 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 "quic/platform/api/quic_ip_address.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>

#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_logging.h"

namespace quic {

static int ToPlatformAddressFamily(IpAddressFamily family) {
  switch (family) {
    case IpAddressFamily::IP_V4:
      return AF_INET;
    case IpAddressFamily::IP_V6:
      return AF_INET6;
    case IpAddressFamily::IP_UNSPEC:
      return AF_UNSPEC;
  }
  QUIC_BUG(quic_bug_10126_1)
      << "Invalid IpAddressFamily " << static_cast<int32_t>(family);
  return AF_UNSPEC;
}

QuicIpAddress QuicIpAddress::Loopback4() {
  QuicIpAddress result;
  result.family_ = IpAddressFamily::IP_V4;
  result.address_.bytes[0] = 127;
  result.address_.bytes[1] = 0;
  result.address_.bytes[2] = 0;
  result.address_.bytes[3] = 1;
  return result;
}

QuicIpAddress QuicIpAddress::Loopback6() {
  QuicIpAddress result;
  result.family_ = IpAddressFamily::IP_V6;
  uint8_t* bytes = result.address_.bytes;
  memset(bytes, 0, 15);
  bytes[15] = 1;
  return result;
}

QuicIpAddress QuicIpAddress::Any4() {
  in_addr address;
  memset(&address, 0, sizeof(address));
  return QuicIpAddress(address);
}

QuicIpAddress QuicIpAddress::Any6() {
  in6_addr address;
  memset(&address, 0, sizeof(address));
  return QuicIpAddress(address);
}

QuicIpAddress::QuicIpAddress() : family_(IpAddressFamily::IP_UNSPEC) {}

QuicIpAddress::QuicIpAddress(const in_addr& ipv4_address)
    : family_(IpAddressFamily::IP_V4) {
  address_.v4 = ipv4_address;
}
QuicIpAddress::QuicIpAddress(const in6_addr& ipv6_address)
    : family_(IpAddressFamily::IP_V6) {
  address_.v6 = ipv6_address;
}

bool operator==(QuicIpAddress lhs, QuicIpAddress rhs) {
  if (lhs.family_ != rhs.family_) {
    return false;
  }
  switch (lhs.family_) {
    case IpAddressFamily::IP_V4:
      return std::equal(lhs.address_.bytes,
                        lhs.address_.bytes + QuicIpAddress::kIPv4AddressSize,
                        rhs.address_.bytes);
    case IpAddressFamily::IP_V6:
      return std::equal(lhs.address_.bytes,
                        lhs.address_.bytes + QuicIpAddress::kIPv6AddressSize,
                        rhs.address_.bytes);
    case IpAddressFamily::IP_UNSPEC:
      return true;
  }
  QUIC_BUG(quic_bug_10126_2)
      << "Invalid IpAddressFamily " << static_cast<int32_t>(lhs.family_);
  return false;
}

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

bool QuicIpAddress::IsInitialized() const {
  return family_ != IpAddressFamily::IP_UNSPEC;
}

IpAddressFamily QuicIpAddress::address_family() const {
  return family_;
}

int QuicIpAddress::AddressFamilyToInt() const {
  return ToPlatformAddressFamily(family_);
}

std::string QuicIpAddress::ToPackedString() const {
  switch (family_) {
    case IpAddressFamily::IP_V4:
      return std::string(address_.chars, sizeof(address_.v4));
    case IpAddressFamily::IP_V6:
      return std::string(address_.chars, sizeof(address_.v6));
    case IpAddressFamily::IP_UNSPEC:
      return "";
  }
  QUIC_BUG(quic_bug_10126_3)
      << "Invalid IpAddressFamily " << static_cast<int32_t>(family_);
  return "";
}

std::string QuicIpAddress::ToString() const {
  if (!IsInitialized()) {
    return "";
  }

  char buffer[INET6_ADDRSTRLEN] = {0};
  const char* result =
      inet_ntop(AddressFamilyToInt(), address_.bytes, buffer, sizeof(buffer));
  QUIC_BUG_IF(quic_bug_10126_4, result == nullptr)
      << "Failed to convert an IP address to string";
  return buffer;
}

static const uint8_t kMappedAddressPrefix[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
};

QuicIpAddress QuicIpAddress::Normalized() const {
  if (!IsIPv6()) {
    return *this;
  }
  if (!std::equal(std::begin(kMappedAddressPrefix),
                  std::end(kMappedAddressPrefix), address_.bytes)) {
    return *this;
  }

  in_addr result;
  memcpy(&result, &address_.bytes[12], sizeof(result));
  return QuicIpAddress(result);
}

QuicIpAddress QuicIpAddress::DualStacked() const {
  if (!IsIPv4()) {
    return *this;
  }

  QuicIpAddress result;
  result.family_ = IpAddressFamily::IP_V6;
  memcpy(result.address_.bytes, kMappedAddressPrefix,
         sizeof(kMappedAddressPrefix));
  memcpy(result.address_.bytes + 12, address_.bytes, kIPv4AddressSize);
  return result;
}

bool QuicIpAddress::FromPackedString(const char* data, size_t length) {
  switch (length) {
    case kIPv4AddressSize:
      family_ = IpAddressFamily::IP_V4;
      break;
    case kIPv6AddressSize:
      family_ = IpAddressFamily::IP_V6;
      break;
    default:
      return false;
  }
  memcpy(address_.chars, data, length);
  return true;
}

bool QuicIpAddress::FromString(std::string str) {
  for (IpAddressFamily family :
       {IpAddressFamily::IP_V6, IpAddressFamily::IP_V4}) {
    int result =
        inet_pton(ToPlatformAddressFamily(family), str.c_str(), address_.bytes);
    if (result > 0) {
      family_ = family;
      return true;
    }
  }
  return false;
}

bool QuicIpAddress::IsIPv4() const {
  return family_ == IpAddressFamily::IP_V4;
}

bool QuicIpAddress::IsIPv6() const {
  return family_ == IpAddressFamily::IP_V6;
}

bool QuicIpAddress::InSameSubnet(const QuicIpAddress& other,
                                 int subnet_length) {
  if (!IsInitialized()) {
    QUIC_BUG(quic_bug_10126_5)
        << "Attempting to do subnet matching on undefined address";
    return false;
  }
  if ((IsIPv4() && subnet_length > 32) || (IsIPv6() && subnet_length > 128)) {
    QUIC_BUG(quic_bug_10126_6) << "Subnet mask is out of bounds";
    return false;
  }

  int bytes_to_check = subnet_length / 8;
  int bits_to_check = subnet_length % 8;
  const uint8_t* const lhs = address_.bytes;
  const uint8_t* const rhs = other.address_.bytes;
  if (!std::equal(lhs, lhs + bytes_to_check, rhs)) {
    return false;
  }
  if (bits_to_check == 0) {
    return true;
  }
  QUICHE_DCHECK_LT(static_cast<size_t>(bytes_to_check), sizeof(address_.bytes));
  int mask = (~0u) << (8u - bits_to_check);
  return (lhs[bytes_to_check] & mask) == (rhs[bytes_to_check] & mask);
}

in_addr QuicIpAddress::GetIPv4() const {
  QUICHE_DCHECK(IsIPv4());
  return address_.v4;
}

in6_addr QuicIpAddress::GetIPv6() const {
  QUICHE_DCHECK(IsIPv6());
  return address_.v6;
}

}  // namespace quic
