#include "node_sockaddr-inl.h"  // NOLINT(build/include)
#include "env-inl.h"
#include "base64-inl.h"
#include "base_object-inl.h"
#include "memory_tracker-inl.h"
#include "node_errors.h"
#include "uv.h"

#include <memory>
#include <string>
#include <vector>

namespace node {

using v8::Array;
using v8::Context;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Int32;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Object;
using v8::Uint32;
using v8::Value;

namespace {
template <typename T, typename F>
SocketAddress FromUVHandle(F fn, const T& handle) {
  SocketAddress addr;
  int len = sizeof(sockaddr_storage);
  if (fn(&handle, addr.storage(), &len) == 0)
    CHECK_EQ(static_cast<size_t>(len), addr.length());
  else
    addr.storage()->sa_family = 0;
  return addr;
}
}  // namespace

bool SocketAddress::ToSockAddr(
    int32_t family,
    const char* host,
    uint32_t port,
    sockaddr_storage* addr) {
  switch (family) {
    case AF_INET:
      return uv_ip4_addr(
          host,
          port,
          reinterpret_cast<sockaddr_in*>(addr)) == 0;
    case AF_INET6:
      return uv_ip6_addr(
          host,
          port,
          reinterpret_cast<sockaddr_in6*>(addr)) == 0;
    default:
      UNREACHABLE();
  }
}

bool SocketAddress::New(
    const char* host,
    uint32_t port,
    SocketAddress* addr) {
  return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr);
}

bool SocketAddress::New(
    int32_t family,
    const char* host,
    uint32_t port,
    SocketAddress* addr) {
  return ToSockAddr(family, host, port,
                    reinterpret_cast<sockaddr_storage*>(addr->storage()));
}

size_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
  size_t hash = 0;
  switch (addr.family()) {
    case AF_INET: {
      const sockaddr_in* ipv4 =
          reinterpret_cast<const sockaddr_in*>(addr.raw());
      hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
      break;
    }
    case AF_INET6: {
      const sockaddr_in6* ipv6 =
          reinterpret_cast<const sockaddr_in6*>(addr.raw());
      const uint64_t* a =
          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
      break;
    }
    default:
      UNREACHABLE();
  }
  return hash;
}

SocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) {
  return FromUVHandle(uv_tcp_getsockname, handle);
}

SocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) {
  return FromUVHandle(uv_udp_getsockname, handle);
}

SocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) {
  return FromUVHandle(uv_tcp_getpeername, handle);
}

SocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) {
  return FromUVHandle(uv_udp_getpeername, handle);
}

namespace {
constexpr uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };

bool is_match_ipv4(
    const SocketAddress& one,
    const SocketAddress& two) {
  const sockaddr_in* one_in =
      reinterpret_cast<const sockaddr_in*>(one.data());
  const sockaddr_in* two_in =
      reinterpret_cast<const sockaddr_in*>(two.data());
  return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
}

bool is_match_ipv6(
    const SocketAddress& one,
    const SocketAddress& two) {
  const sockaddr_in6* one_in =
      reinterpret_cast<const sockaddr_in6*>(one.data());
  const sockaddr_in6* two_in =
      reinterpret_cast<const sockaddr_in6*>(two.data());
  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
}

bool is_match_ipv4_ipv6(
    const SocketAddress& ipv4,
    const SocketAddress& ipv6) {
  const sockaddr_in* check_ipv4 =
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
  const sockaddr_in6* check_ipv6 =
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());

  const uint8_t* ptr =
      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);

  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
         memcmp(ptr + sizeof(mask),
                &check_ipv4->sin_addr,
                sizeof(uint32_t)) == 0;
}

SocketAddress::CompareResult compare_ipv4(
    const SocketAddress& one,
    const SocketAddress& two) {
  const sockaddr_in* one_in =
      reinterpret_cast<const sockaddr_in*>(one.data());
  const sockaddr_in* two_in =
      reinterpret_cast<const sockaddr_in*>(two.data());
  const uint32_t s_addr_one = ntohl(one_in->sin_addr.s_addr);
  const uint32_t s_addr_two = ntohl(two_in->sin_addr.s_addr);

  if (s_addr_one < s_addr_two)
    return SocketAddress::CompareResult::LESS_THAN;
  else if (s_addr_one == s_addr_two)
    return SocketAddress::CompareResult::SAME;
  else
    return SocketAddress::CompareResult::GREATER_THAN;
}

SocketAddress::CompareResult compare_ipv6(
    const SocketAddress& one,
    const SocketAddress& two) {
  const sockaddr_in6* one_in =
      reinterpret_cast<const sockaddr_in6*>(one.data());
  const sockaddr_in6* two_in =
      reinterpret_cast<const sockaddr_in6*>(two.data());
  int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
  if (ret < 0)
    return SocketAddress::CompareResult::LESS_THAN;
  else if (ret > 0)
    return SocketAddress::CompareResult::GREATER_THAN;
  return SocketAddress::CompareResult::SAME;
}

SocketAddress::CompareResult compare_ipv4_ipv6(
    const SocketAddress& ipv4,
    const SocketAddress& ipv6) {
  const sockaddr_in* ipv4_in =
      reinterpret_cast<const sockaddr_in*>(ipv4.data());
  const sockaddr_in6 * ipv6_in =
      reinterpret_cast<const sockaddr_in6*>(ipv6.data());

  const uint8_t* ptr =
      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);

  if (memcmp(ptr, mask, sizeof(mask)) != 0)
    return SocketAddress::CompareResult::NOT_COMPARABLE;

  int ret = memcmp(
      &ipv4_in->sin_addr,
      ptr + sizeof(mask),
      sizeof(uint32_t));

  if (ret < 0)
    return SocketAddress::CompareResult::LESS_THAN;
  else if (ret > 0)
    return SocketAddress::CompareResult::GREATER_THAN;
  return SocketAddress::CompareResult::SAME;
}

bool in_network_ipv4(
    const SocketAddress& ip,
    const SocketAddress& net,
    int prefix) {
  uint32_t mask = ((1ull << prefix) - 1) << (32 - prefix);

  const sockaddr_in* ip_in =
      reinterpret_cast<const sockaddr_in*>(ip.data());
  const sockaddr_in* net_in =
      reinterpret_cast<const sockaddr_in*>(net.data());

  return (htonl(ip_in->sin_addr.s_addr) & mask) ==
         (htonl(net_in->sin_addr.s_addr) & mask);
}

bool in_network_ipv6(
    const SocketAddress& ip,
    const SocketAddress& net,
    int prefix) {
  // Special case, if prefix == 128, then just do a
  // straight comparison.
  if (prefix == 128)
    return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;

  uint8_t r = prefix % 8;
  int len = (prefix - r) / 8;
  uint8_t mask = ((1 << r) - 1) << (8 - r);

  const sockaddr_in6* ip_in =
      reinterpret_cast<const sockaddr_in6*>(ip.data());
  const sockaddr_in6* net_in =
      reinterpret_cast<const sockaddr_in6*>(net.data());

  if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
    return false;

  const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
      ip_in->sin6_addr.s6_addr);
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
      net_in->sin6_addr.s6_addr);

  return (p1[len] & mask) == (p2[len] & mask);
}

bool in_network_ipv4_ipv6(
    const SocketAddress& ip,
    const SocketAddress& net,
    int prefix) {

  if (prefix == 128)
    return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;

  uint8_t r = prefix % 8;
  int len = (prefix - r) / 8;
  uint8_t mask = ((1 << r) - 1) << (8 - r);

  const sockaddr_in* ip_in =
      reinterpret_cast<const sockaddr_in*>(ip.data());
  const sockaddr_in6* net_in =
      reinterpret_cast<const sockaddr_in6*>(net.data());

  uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
  uint8_t* ptr = ip_mask;
  memcpy(ptr + 12, &ip_in->sin_addr, 4);

  if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
    return false;

  ptr += len;
  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
      net_in->sin6_addr.s6_addr);

  return (ptr[0] & mask) == (p2[len] & mask);
}

bool in_network_ipv6_ipv4(
    const SocketAddress& ip,
    const SocketAddress& net,
    int prefix) {
  if (prefix == 32)
    return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;

  uint32_t m = ((1ull << prefix) - 1) << (32 - prefix);

  const sockaddr_in6* ip_in =
      reinterpret_cast<const sockaddr_in6*>(ip.data());
  const sockaddr_in* net_in =
      reinterpret_cast<const sockaddr_in*>(net.data());

  const uint8_t* ptr =
      reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);

  if (memcmp(ptr, mask, sizeof(mask)) != 0)
    return false;

  ptr += sizeof(mask);
  uint32_t check = ReadUint32BE(ptr);

  return (check & m) == (htonl(net_in->sin_addr.s_addr) & m);
}
}  // namespace

// TODO(@jasnell): The implementations of is_match, compare, and
// is_in_network have not been performance optimized and could
// likely benefit from work on more performant approaches.

bool SocketAddress::is_match(const SocketAddress& other) const {
  switch (family()) {
    case AF_INET:
      switch (other.family()) {
        case AF_INET: return is_match_ipv4(*this, other);
        case AF_INET6: return is_match_ipv4_ipv6(*this, other);
      }
      break;
    case AF_INET6:
      switch (other.family()) {
        case AF_INET: return is_match_ipv4_ipv6(other, *this);
        case AF_INET6: return is_match_ipv6(*this, other);
      }
      break;
  }
  return false;
}

SocketAddress::CompareResult SocketAddress::compare(
    const SocketAddress& other) const {
  switch (family()) {
    case AF_INET:
      switch (other.family()) {
        case AF_INET: return compare_ipv4(*this, other);
        case AF_INET6: return compare_ipv4_ipv6(*this, other);
      }
      break;
    case AF_INET6:
      switch (other.family()) {
        case AF_INET: {
          CompareResult c = compare_ipv4_ipv6(other, *this);
          switch (c) {
            case SocketAddress::CompareResult::NOT_COMPARABLE:
              // Fall through
            case SocketAddress::CompareResult::SAME:
              return c;
            case SocketAddress::CompareResult::GREATER_THAN:
              return SocketAddress::CompareResult::LESS_THAN;
            case SocketAddress::CompareResult::LESS_THAN:
              return SocketAddress::CompareResult::GREATER_THAN;
          }
          break;
        }
        case AF_INET6: return compare_ipv6(*this, other);
      }
      break;
  }
  return SocketAddress::CompareResult::NOT_COMPARABLE;
}

bool SocketAddress::is_in_network(
    const SocketAddress& other,
    int prefix) const {

  switch (family()) {
    case AF_INET:
      switch (other.family()) {
        case AF_INET: return in_network_ipv4(*this, other, prefix);
        case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
      }
      break;
    case AF_INET6:
      switch (other.family()) {
        case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
        case AF_INET6: return in_network_ipv6(*this, other, prefix);
      }
      break;
  }

  return false;
}

SocketAddressBlockList::SocketAddressBlockList(
    std::shared_ptr<SocketAddressBlockList> parent)
    : parent_(parent) {}

void SocketAddressBlockList::AddSocketAddress(
    const std::shared_ptr<SocketAddress>& address) {
  Mutex::ScopedLock lock(mutex_);
  std::unique_ptr<Rule> rule =
      std::make_unique<SocketAddressRule>(address);
  rules_.emplace_front(std::move(rule));
  address_rules_[*address.get()] = rules_.begin();
}

void SocketAddressBlockList::RemoveSocketAddress(
    const std::shared_ptr<SocketAddress>& address) {
  Mutex::ScopedLock lock(mutex_);
  auto it = address_rules_.find(*address.get());
  if (it != std::end(address_rules_)) {
    rules_.erase(it->second);
    address_rules_.erase(it);
  }
}

void SocketAddressBlockList::AddSocketAddressRange(
    const std::shared_ptr<SocketAddress>& start,
    const std::shared_ptr<SocketAddress>& end) {
  Mutex::ScopedLock lock(mutex_);
  std::unique_ptr<Rule> rule =
      std::make_unique<SocketAddressRangeRule>(start, end);
  rules_.emplace_front(std::move(rule));
}

void SocketAddressBlockList::AddSocketAddressMask(
    const std::shared_ptr<SocketAddress>& network,
    int prefix) {
  Mutex::ScopedLock lock(mutex_);
  std::unique_ptr<Rule> rule =
      std::make_unique<SocketAddressMaskRule>(network, prefix);
  rules_.emplace_front(std::move(rule));
}

bool SocketAddressBlockList::Apply(
    const std::shared_ptr<SocketAddress>& address) {
  Mutex::ScopedLock lock(mutex_);
  for (const auto& rule : rules_) {
    if (rule->Apply(address))
      return true;
  }
  return parent_ ? parent_->Apply(address) : false;
}

SocketAddressBlockList::SocketAddressRule::SocketAddressRule(
    const std::shared_ptr<SocketAddress>& address_)
    : address(address_) {}

SocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
    const std::shared_ptr<SocketAddress>& start_,
    const std::shared_ptr<SocketAddress>& end_)
    : start(start_),
      end(end_) {}

SocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
    const std::shared_ptr<SocketAddress>& network_,
    int prefix_)
    : network(network_),
      prefix(prefix_) {}

bool SocketAddressBlockList::SocketAddressRule::Apply(
    const std::shared_ptr<SocketAddress>& address) {
  return this->address->is_match(*address.get());
}

std::string SocketAddressBlockList::SocketAddressRule::ToString() {
  std::string ret = "Address: ";
  ret += address->family() == AF_INET ? "IPv4" : "IPv6";
  ret += " ";
  ret += address->address();
  return ret;
}

bool SocketAddressBlockList::SocketAddressRangeRule::Apply(
    const std::shared_ptr<SocketAddress>& address) {
  return *address.get() >= *start.get() &&
         *address.get() <= *end.get();
}

std::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
  std::string ret = "Range: ";
  ret += start->family() == AF_INET ? "IPv4" : "IPv6";
  ret += " ";
  ret += start->address();
  ret += "-";
  ret += end->address();
  return ret;
}

bool SocketAddressBlockList::SocketAddressMaskRule::Apply(
    const std::shared_ptr<SocketAddress>& address) {
  return address->is_in_network(*network.get(), prefix);
}

std::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
  std::string ret = "Subnet: ";
  ret += network->family() == AF_INET ? "IPv4" : "IPv6";
  ret += " ";
  ret += network->address();
  ret += "/" + std::to_string(prefix);
  return ret;
}

MaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
  Mutex::ScopedLock lock(mutex_);
  std::vector<Local<Value>> rules;
  if (!ListRules(env, &rules))
    return MaybeLocal<Array>();
  return Array::New(env->isolate(), rules.data(), rules.size());
}

bool SocketAddressBlockList::ListRules(
    Environment* env,
    std::vector<v8::Local<v8::Value>>* rules) {
  if (parent_ && !parent_->ListRules(env, rules))
    return false;
  for (const auto& rule : rules_) {
    Local<Value> str;
    if (!rule->ToV8String(env).ToLocal(&str))
      return false;
    rules->push_back(str);
  }
  return true;
}

void SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
  tracker->TrackField("rules", rules_);
}

void SocketAddressBlockList::SocketAddressRule::MemoryInfo(
    node::MemoryTracker* tracker) const {
  tracker->TrackField("address", address);
}

void SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
    node::MemoryTracker* tracker) const {
  tracker->TrackField("start", start);
  tracker->TrackField("end", end);
}

void SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
    node::MemoryTracker* tracker) const {
  tracker->TrackField("network", network);
}

SocketAddressBlockListWrap::SocketAddressBlockListWrap(
    Environment* env,
    Local<Object> wrap,
    std::shared_ptr<SocketAddressBlockList> blocklist)
    : BaseObject(env, wrap),
      blocklist_(std::move(blocklist)) {
  MakeWeak();
}

BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
    Environment* env) {
  Local<Object> obj;
  if (!env->blocklist_constructor_template()
          ->InstanceTemplate()
          ->NewInstance(env->context()).ToLocal(&obj)) {
    return BaseObjectPtr<SocketAddressBlockListWrap>();
  }
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
      MakeBaseObject<SocketAddressBlockListWrap>(env, obj);
  CHECK(wrap);
  return wrap;
}

BaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
    Environment* env,
    std::shared_ptr<SocketAddressBlockList> blocklist) {
  Local<Object> obj;
  if (!env->blocklist_constructor_template()
          ->InstanceTemplate()
          ->NewInstance(env->context()).ToLocal(&obj)) {
    return BaseObjectPtr<SocketAddressBlockListWrap>();
  }
  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
      MakeBaseObject<SocketAddressBlockListWrap>(
          env,
          obj,
          std::move(blocklist));
  CHECK(wrap);
  return wrap;
}

void SocketAddressBlockListWrap::New(
    const FunctionCallbackInfo<Value>& args) {
  CHECK(args.IsConstructCall());
  Environment* env = Environment::GetCurrent(args);
  new SocketAddressBlockListWrap(env, args.This());
}

void SocketAddressBlockListWrap::AddAddress(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  SocketAddressBlockListWrap* wrap;
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());

  CHECK(SocketAddressBase::HasInstance(env, args[0]));
  SocketAddressBase* addr;
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);

  wrap->blocklist_->AddSocketAddress(addr->address());

  args.GetReturnValue().Set(true);
}

void SocketAddressBlockListWrap::AddRange(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  SocketAddressBlockListWrap* wrap;
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());

  CHECK(SocketAddressBase::HasInstance(env, args[0]));
  CHECK(SocketAddressBase::HasInstance(env, args[1]));

  SocketAddressBase* start_addr;
  SocketAddressBase* end_addr;
  ASSIGN_OR_RETURN_UNWRAP(&start_addr, args[0]);
  ASSIGN_OR_RETURN_UNWRAP(&end_addr, args[1]);

  // Starting address must come before the end address
  if (*start_addr->address().get() > *end_addr->address().get())
    return args.GetReturnValue().Set(false);

  wrap->blocklist_->AddSocketAddressRange(
      start_addr->address(),
      end_addr->address());

  args.GetReturnValue().Set(true);
}

void SocketAddressBlockListWrap::AddSubnet(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  SocketAddressBlockListWrap* wrap;
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());

  CHECK(SocketAddressBase::HasInstance(env, args[0]));
  CHECK(args[1]->IsInt32());

  SocketAddressBase* addr;
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);

  int32_t prefix;
  if (!args[1]->Int32Value(env->context()).To(&prefix)) {
    return;
  }

  CHECK_IMPLIES(addr->address()->family() == AF_INET, prefix <= 32);
  CHECK_IMPLIES(addr->address()->family() == AF_INET6, prefix <= 128);
  CHECK_GE(prefix, 0);

  wrap->blocklist_->AddSocketAddressMask(addr->address(), prefix);

  args.GetReturnValue().Set(true);
}

void SocketAddressBlockListWrap::Check(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  SocketAddressBlockListWrap* wrap;
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());

  CHECK(SocketAddressBase::HasInstance(env, args[0]));
  SocketAddressBase* addr;
  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);

  args.GetReturnValue().Set(wrap->blocklist_->Apply(addr->address()));
}

void SocketAddressBlockListWrap::GetRules(
    const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  SocketAddressBlockListWrap* wrap;
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
  Local<Array> rules;
  if (wrap->blocklist_->ListRules(env).ToLocal(&rules))
    args.GetReturnValue().Set(rules);
}

void SocketAddressBlockListWrap::MemoryInfo(MemoryTracker* tracker) const {
  blocklist_->MemoryInfo(tracker);
}

std::unique_ptr<worker::TransferData>
SocketAddressBlockListWrap::CloneForMessaging() const {
  return std::make_unique<TransferData>(this);
}

bool SocketAddressBlockListWrap::HasInstance(
    Environment* env,
    Local<Value> value) {
  return GetConstructorTemplate(env)->HasInstance(value);
}

Local<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
    Environment* env) {
  Local<FunctionTemplate> tmpl = env->blocklist_constructor_template();
  if (tmpl.IsEmpty()) {
    Isolate* isolate = env->isolate();
    tmpl = NewFunctionTemplate(isolate, SocketAddressBlockListWrap::New);
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
    tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
    SetProtoMethod(isolate, tmpl, "addAddress", AddAddress);
    SetProtoMethod(isolate, tmpl, "addRange", AddRange);
    SetProtoMethod(isolate, tmpl, "addSubnet", AddSubnet);
    SetProtoMethod(isolate, tmpl, "check", Check);
    SetProtoMethod(isolate, tmpl, "getRules", GetRules);
    env->set_blocklist_constructor_template(tmpl);
  }
  return tmpl;
}

void SocketAddressBlockListWrap::Initialize(
    Local<Object> target,
    Local<Value> unused,
    Local<Context> context,
    void* priv) {
  Environment* env = Environment::GetCurrent(context);

  SetConstructorFunction(context,
                         target,
                         "BlockList",
                         GetConstructorTemplate(env),
                         SetConstructorFunctionFlag::NONE);

  SocketAddressBase::Initialize(env, target);

  NODE_DEFINE_CONSTANT(target, AF_INET);
  NODE_DEFINE_CONSTANT(target, AF_INET6);
}

BaseObjectPtr<BaseObject> SocketAddressBlockListWrap::TransferData::Deserialize(
    Environment* env,
    Local<Context> context,
    std::unique_ptr<worker::TransferData> self) {
  return New(env, std::move(blocklist_));
}

void SocketAddressBlockListWrap::TransferData::MemoryInfo(
    MemoryTracker* tracker) const {
  blocklist_->MemoryInfo(tracker);
}

bool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) {
  return GetConstructorTemplate(env)->HasInstance(value);
}

Local<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
    Environment* env) {
  Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template();
  if (tmpl.IsEmpty()) {
    Isolate* isolate = env->isolate();
    tmpl = NewFunctionTemplate(isolate, New);
    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
    tmpl->InstanceTemplate()->SetInternalFieldCount(
        SocketAddressBase::kInternalFieldCount);
    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
    SetProtoMethod(isolate, tmpl, "detail", Detail);
    SetProtoMethod(isolate, tmpl, "legacyDetail", LegacyDetail);
    SetProtoMethodNoSideEffect(isolate, tmpl, "flowlabel", GetFlowLabel);
    env->set_socketaddress_constructor_template(tmpl);
  }
  return tmpl;
}

void SocketAddressBase::Initialize(Environment* env, Local<Object> target) {
  SetConstructorFunction(env->context(),
                         target,
                         "SocketAddress",
                         GetConstructorTemplate(env),
                         SetConstructorFunctionFlag::NONE);
}

BaseObjectPtr<SocketAddressBase> SocketAddressBase::Create(
    Environment* env,
    std::shared_ptr<SocketAddress> address) {
  Local<Object> obj;
  if (!GetConstructorTemplate(env)
          ->InstanceTemplate()
          ->NewInstance(env->context()).ToLocal(&obj)) {
    return BaseObjectPtr<SocketAddressBase>();
  }

  return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address));
}

void SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  CHECK(args.IsConstructCall());
  CHECK(args[0]->IsString());  // address
  CHECK(args[1]->IsInt32());  // port
  CHECK(args[2]->IsInt32());  // family
  CHECK(args[3]->IsUint32());  // flow label

  Utf8Value address(env->isolate(), args[0]);
  int32_t port = args[1].As<Int32>()->Value();
  int32_t family = args[2].As<Int32>()->Value();
  uint32_t flow_label = args[3].As<Uint32>()->Value();

  std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>();

  if (!SocketAddress::New(family, *address, port, addr.get()))
    return THROW_ERR_INVALID_ADDRESS(env);

  addr->set_flow_label(flow_label);

  new SocketAddressBase(env, args.This(), std::move(addr));
}

void SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  CHECK(args[0]->IsObject());
  Local<Object> detail = args[0].As<Object>();

  SocketAddressBase* base;
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());

  Local<Value> address;
  if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address))
    return;

  if (detail->Set(env->context(), env->address_string(), address).IsJust() &&
      detail->Set(
          env->context(),
          env->port_string(),
          Int32::New(env->isolate(), base->address_->port())).IsJust() &&
      detail->Set(
          env->context(),
          env->family_string(),
          Int32::New(env->isolate(), base->address_->family())).IsJust() &&
      detail->Set(
          env->context(),
          env->flowlabel_string(),
          Uint32::New(env->isolate(), base->address_->flow_label()))
              .IsJust()) {
    args.GetReturnValue().Set(detail);
  }
}

void SocketAddressBase::GetFlowLabel(const FunctionCallbackInfo<Value>& args) {
  SocketAddressBase* base;
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
  args.GetReturnValue().Set(base->address_->flow_label());
}

void SocketAddressBase::LegacyDetail(const FunctionCallbackInfo<Value>& args) {
  Environment* env = Environment::GetCurrent(args);
  SocketAddressBase* base;
  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
  Local<Object> address;
  if (!base->address_->ToJS(env).ToLocal(&address)) return;
  args.GetReturnValue().Set(address);
}

SocketAddressBase::SocketAddressBase(
    Environment* env,
    Local<Object> wrap,
    std::shared_ptr<SocketAddress> address)
    : BaseObject(env, wrap),
      address_(std::move(address)) {
  MakeWeak();
}

void SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackField("address", address_);
}

std::unique_ptr<worker::TransferData>
SocketAddressBase::CloneForMessaging() const {
  return std::make_unique<TransferData>(this);
}

void SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const {
  tracker->TrackField("address", address_);
}

BaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize(
    Environment* env,
    v8::Local<v8::Context> context,
    std::unique_ptr<worker::TransferData> self) {
  return SocketAddressBase::Create(env, std::move(address_));
}

}  // namespace node

NODE_MODULE_CONTEXT_AWARE_INTERNAL(
    block_list,
    node::SocketAddressBlockListWrap::Initialize)
