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

#ifndef SRC_LIB_INET_IP_ADDRESS_H_
#define SRC_LIB_INET_IP_ADDRESS_H_

#include <arpa/inet.h>
#include <fuchsia/net/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>

namespace inet {

// Represents a V4 or V6 IP address.
class IpAddress {
 public:
  static const IpAddress kInvalid;
  static const IpAddress kV4Loopback;
  static const IpAddress kV6Loopback;

  // Creates an IpAddress from a string containing a numeric IP address. Returns
  // |kInvalid| if |address_string| cannot be converted into a valid IP address.
  static IpAddress FromString(const std::string address_string, sa_family_t family = AF_UNSPEC);

  // Creates an invalid IP address.
  IpAddress();

  // Creates an IPV4 address from four address bytes.
  IpAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3);

  // Creates an IPV4 address from an in_addr_t.
  explicit IpAddress(in_addr_t addr);

  // Creates an IPV4 address from an in_addr struct.
  explicit IpAddress(const in_addr& addr);

  // Creates an IPV6 address from eight address words.
  IpAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4, uint16_t w5,
            uint16_t w6, uint16_t w7);

  // Creates an IPV6 address from two address words (first and last).
  IpAddress(uint16_t w0, uint16_t w7);

  // Creates an IPV6 address from an in6_addr struct.
  explicit IpAddress(const in6_addr& addr);

  // Creates an address from a sockaddr struct.
  explicit IpAddress(const sockaddr* addr);

  // Creates an address from a sockaddr_storage struct.
  explicit IpAddress(const sockaddr_storage& addr);

  // Creates an address from a fuchsia.net Ipv4Address struct.
  explicit IpAddress(const fuchsia::net::Ipv4Address* addr);

  // Creates an address from a fuchsia.net Ipv6Address struct.
  explicit IpAddress(const fuchsia::net::Ipv6Address* addr);

  // Creates an address from a fuchsia.net IpAddress struct.
  explicit IpAddress(const fuchsia::net::IpAddress* addr);

  // Indicates whether this address is valid.
  bool is_valid() const { return family_ != AF_UNSPEC; }

  // Returns the family of this address: |AF_INET| for V4, |AF_INET6| for V6 and
  // |AF_UNSPEC| for an invalid address.
  sa_family_t family() const { return family_; }

  // Indicates whether this address is a V4 address.
  bool is_v4() const { return family() == AF_INET; }

  // Indicates whether this address is a V6 address.
  bool is_v6() const { return family() == AF_INET6; }

  // Indicates whether this address is a V6 address that is mapped from a V4 address.
  bool is_mapped_from_v4() const;

  // Returns the V4 address from a V6 address that is mapped from a V4 address. Calling this method
  // is only permitted if this address returns true from |is_mapped_from_v4|.
  IpAddress mapped_v4_address() const;

  // Returns the V6 address that is the mapping of this address, which must be a V4 address.
  IpAddress mapped_as_v6() const;

  // Indicates whether this address is a loopback address.
  bool is_loopback() const;

  // Returns this address as an |in_addr|. Only defined for V4 addresses.
  const in_addr& as_in_addr() const {
    FX_DCHECK(is_v4());
    return v4_;
  }

  // Returns this address as an |in_addr_t|. Only defined for V4 addresses.
  in_addr_t as_in_addr_t() const {
    FX_DCHECK(is_v4());
    return v4_.s_addr;
  }

  // Returns this address as an |in6_addr|. Only defined for V6 addresses.
  const in6_addr& as_in6_addr() const {
    FX_DCHECK(is_v6());
    return v6_;
  }

  // Returns a pointer to the bytes that make up this address. |byte_count|
  // indicates the byte count. Not defined for invalid addresses.
  const uint8_t* as_bytes() const {
    FX_DCHECK(is_valid());
    return v6_.s6_addr;
  }

  // Returns a pointer to the network-order words (big-endian) that make up the
  // address. |word_count| indicates the byte count. Not defined for invalid
  // addresses.
  const uint16_t* as_words() const {
    FX_DCHECK(is_valid());
    return v6_.s6_addr16;
  }

  // Returns the number of bytes that make up this address. A V4 address is
  // 4 bytes, and a V6 address is 16 bytes. Not defined for invalid addresses.
  size_t byte_count() const {
    FX_DCHECK(is_valid());
    return is_v4() ? sizeof(in_addr) : sizeof(in6_addr);
  }

  // Returns the number of words that make up this address. A V4 address is
  // 2 words, and a V6 address is 8 words. Not defined for invalid addresses.
  size_t word_count() const {
    FX_DCHECK(is_valid());
    return byte_count() / sizeof(uint16_t);
  }

  // Returns a string representation of this address. V6 addresses are
  // represented as specified in RFC 5952. For invalid addresses, this method
  // returns "<invalid>".
  std::string ToString() const;

  explicit operator bool() const { return is_valid(); }

  bool operator==(const IpAddress& other) const {
    return family() == other.family() &&
           (!is_valid() || (std::memcmp(as_bytes(), other.as_bytes(), byte_count()) == 0));
  }

  bool operator!=(const IpAddress& other) const { return !(*this == other); }

 private:
  sa_family_t family_;
  union {
    in_addr v4_;
    in6_addr v6_;
  };
};

// Inserts a string representation of |value|. V6 addresses are represented as
// specified in RFC 5952. For invalid addresses, this method inserts
// "<invalid>".
std::ostream& operator<<(std::ostream& os, const IpAddress& value);

}  // namespace inet

template <>
struct std::hash<inet::IpAddress> {
  std::size_t operator()(const inet::IpAddress& address) const noexcept {
    size_t hash = 0;

    if (address.is_valid()) {
      auto word_ptr = address.as_words();
      for (size_t i = 0; i < address.word_count(); ++i) {
        hash = (hash << 1) ^ *word_ptr;
        ++word_ptr;
      }
    }

    return hash;
  }
};

#endif  // SRC_LIB_INET_IP_ADDRESS_H_
