// Copyright 2019 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.

#include "src/connectivity/overnet/lib/vocabulary/ip_addr.h"
#include <arpa/inet.h>
#include <string.h>
#include <ostream>

namespace overnet {

IpAddr IpAddr::AnyIpv4() {
  IpAddr out;
  memset(&out, 0, sizeof(out));
  out.ipv4.sin_family = AF_INET;
  return out;
}

IpAddr IpAddr::AnyIpv6() {
  IpAddr out;
  memset(&out, 0, sizeof(out));
  out.ipv6.sin6_family = AF_INET6;
  return out;
}

Optional<IpAddr> IpAddr::WithPort(uint16_t port) const {
  IpAddr out = *this;
  switch (out.addr.sa_family) {
    case AF_INET:
      out.ipv4.sin_port = htons(port);
      return out;
    case AF_INET6:
      out.ipv6.sin6_port = htons(port);
      return out;
    default:
      return Nothing;
  }
}

Optional<IpAddr> IpAddr::AsIpv6() const {
  switch (addr.sa_family) {
    case AF_INET6:
      return *this;
    default:
      return Nothing;
    case AF_INET: {
      auto out = AnyIpv6();
      out.ipv6.sin6_port = ipv4.sin_port;
      out.ipv6.sin6_addr.s6_addr[10] = 0xff;
      out.ipv6.sin6_addr.s6_addr[11] = 0xff;
      memcpy(out.ipv6.sin6_addr.s6_addr + 12, &ipv4.sin_addr,
             sizeof(ipv4.sin_addr));
      return out;
    }
  }
}

std::ostream& operator<<(std::ostream& out, IpAddr addr) {
  char dst[512];
  switch (addr.addr.sa_family) {
    case AF_INET:
      inet_ntop(AF_INET, &addr.ipv4.sin_addr, dst, sizeof(dst));
      return out << dst << ":" << ntohs(addr.ipv4.sin_port);
    case AF_INET6:
      inet_ntop(AF_INET6, &addr.ipv6.sin6_addr, dst, sizeof(dst));
      return out << dst << "." << ntohs(addr.ipv6.sin6_port);
    default:
      return out << "<<unknown address family " << addr.addr.sa_family << ">>";
  }
}

size_t HashIpAddr::operator()(const IpAddr& addr) const {
  size_t out = 0;
  auto add_value = [&out](auto x) {
    const char* p = reinterpret_cast<const char*>(&x);
    const char* end = reinterpret_cast<const char*>(1 + &x);
    while (p != end) {
      out = 257 * out + *p++;
    }
  };
  switch (addr.addr.sa_family) {
    case AF_INET:
      add_value(addr.ipv4.sin_addr);
      add_value(addr.ipv4.sin_port);
      break;
    case AF_INET6:
      add_value(addr.ipv6.sin6_addr);
      add_value(addr.ipv6.sin6_port);
      break;
  }
  return out;
}

bool EqIpAddr::operator()(const IpAddr& a, const IpAddr& b) const {
  if (a.addr.sa_family == b.addr.sa_family) {
    switch (a.addr.sa_family) {
      case AF_INET:
        return a.ipv4.sin_port == b.ipv4.sin_port &&
               0 == memcmp(&a.ipv4.sin_addr, &b.ipv4.sin_addr,
                           sizeof(a.ipv4.sin_addr));
      case AF_INET6:
        return a.ipv6.sin6_port == b.ipv6.sin6_port &&
               0 == memcmp(&a.ipv6.sin6_addr, &b.ipv6.sin6_addr,
                           sizeof(a.ipv6.sin6_addr));
    }
  }
  if (auto a6 = a.AsIpv6(); a6.has_value()) {
    if (auto b6 = b.AsIpv6(); b6.has_value()) {
      return a6 == b6;
    }
  }
  return false;
}

}  // namespace overnet
