11cb0ef41Sopenharmony_ci#include "node_sockaddr-inl.h"  // NOLINT(build/include)
21cb0ef41Sopenharmony_ci#include "env-inl.h"
31cb0ef41Sopenharmony_ci#include "base64-inl.h"
41cb0ef41Sopenharmony_ci#include "base_object-inl.h"
51cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h"
61cb0ef41Sopenharmony_ci#include "node_errors.h"
71cb0ef41Sopenharmony_ci#include "uv.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include <memory>
101cb0ef41Sopenharmony_ci#include <string>
111cb0ef41Sopenharmony_ci#include <vector>
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace node {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciusing v8::Array;
161cb0ef41Sopenharmony_ciusing v8::Context;
171cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
181cb0ef41Sopenharmony_ciusing v8::FunctionTemplate;
191cb0ef41Sopenharmony_ciusing v8::Int32;
201cb0ef41Sopenharmony_ciusing v8::Isolate;
211cb0ef41Sopenharmony_ciusing v8::Local;
221cb0ef41Sopenharmony_ciusing v8::MaybeLocal;
231cb0ef41Sopenharmony_ciusing v8::Object;
241cb0ef41Sopenharmony_ciusing v8::Uint32;
251cb0ef41Sopenharmony_ciusing v8::Value;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cinamespace {
281cb0ef41Sopenharmony_citemplate <typename T, typename F>
291cb0ef41Sopenharmony_ciSocketAddress FromUVHandle(F fn, const T& handle) {
301cb0ef41Sopenharmony_ci  SocketAddress addr;
311cb0ef41Sopenharmony_ci  int len = sizeof(sockaddr_storage);
321cb0ef41Sopenharmony_ci  if (fn(&handle, addr.storage(), &len) == 0)
331cb0ef41Sopenharmony_ci    CHECK_EQ(static_cast<size_t>(len), addr.length());
341cb0ef41Sopenharmony_ci  else
351cb0ef41Sopenharmony_ci    addr.storage()->sa_family = 0;
361cb0ef41Sopenharmony_ci  return addr;
371cb0ef41Sopenharmony_ci}
381cb0ef41Sopenharmony_ci}  // namespace
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_cibool SocketAddress::ToSockAddr(
411cb0ef41Sopenharmony_ci    int32_t family,
421cb0ef41Sopenharmony_ci    const char* host,
431cb0ef41Sopenharmony_ci    uint32_t port,
441cb0ef41Sopenharmony_ci    sockaddr_storage* addr) {
451cb0ef41Sopenharmony_ci  switch (family) {
461cb0ef41Sopenharmony_ci    case AF_INET:
471cb0ef41Sopenharmony_ci      return uv_ip4_addr(
481cb0ef41Sopenharmony_ci          host,
491cb0ef41Sopenharmony_ci          port,
501cb0ef41Sopenharmony_ci          reinterpret_cast<sockaddr_in*>(addr)) == 0;
511cb0ef41Sopenharmony_ci    case AF_INET6:
521cb0ef41Sopenharmony_ci      return uv_ip6_addr(
531cb0ef41Sopenharmony_ci          host,
541cb0ef41Sopenharmony_ci          port,
551cb0ef41Sopenharmony_ci          reinterpret_cast<sockaddr_in6*>(addr)) == 0;
561cb0ef41Sopenharmony_ci    default:
571cb0ef41Sopenharmony_ci      UNREACHABLE();
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_cibool SocketAddress::New(
621cb0ef41Sopenharmony_ci    const char* host,
631cb0ef41Sopenharmony_ci    uint32_t port,
641cb0ef41Sopenharmony_ci    SocketAddress* addr) {
651cb0ef41Sopenharmony_ci  return New(AF_INET, host, port, addr) || New(AF_INET6, host, port, addr);
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_cibool SocketAddress::New(
691cb0ef41Sopenharmony_ci    int32_t family,
701cb0ef41Sopenharmony_ci    const char* host,
711cb0ef41Sopenharmony_ci    uint32_t port,
721cb0ef41Sopenharmony_ci    SocketAddress* addr) {
731cb0ef41Sopenharmony_ci  return ToSockAddr(family, host, port,
741cb0ef41Sopenharmony_ci                    reinterpret_cast<sockaddr_storage*>(addr->storage()));
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_cisize_t SocketAddress::Hash::operator()(const SocketAddress& addr) const {
781cb0ef41Sopenharmony_ci  size_t hash = 0;
791cb0ef41Sopenharmony_ci  switch (addr.family()) {
801cb0ef41Sopenharmony_ci    case AF_INET: {
811cb0ef41Sopenharmony_ci      const sockaddr_in* ipv4 =
821cb0ef41Sopenharmony_ci          reinterpret_cast<const sockaddr_in*>(addr.raw());
831cb0ef41Sopenharmony_ci      hash_combine(&hash, ipv4->sin_port, ipv4->sin_addr.s_addr);
841cb0ef41Sopenharmony_ci      break;
851cb0ef41Sopenharmony_ci    }
861cb0ef41Sopenharmony_ci    case AF_INET6: {
871cb0ef41Sopenharmony_ci      const sockaddr_in6* ipv6 =
881cb0ef41Sopenharmony_ci          reinterpret_cast<const sockaddr_in6*>(addr.raw());
891cb0ef41Sopenharmony_ci      const uint64_t* a =
901cb0ef41Sopenharmony_ci          reinterpret_cast<const uint64_t*>(&ipv6->sin6_addr);
911cb0ef41Sopenharmony_ci      hash_combine(&hash, ipv6->sin6_port, a[0], a[1]);
921cb0ef41Sopenharmony_ci      break;
931cb0ef41Sopenharmony_ci    }
941cb0ef41Sopenharmony_ci    default:
951cb0ef41Sopenharmony_ci      UNREACHABLE();
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci  return hash;
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ciSocketAddress SocketAddress::FromSockName(const uv_tcp_t& handle) {
1011cb0ef41Sopenharmony_ci  return FromUVHandle(uv_tcp_getsockname, handle);
1021cb0ef41Sopenharmony_ci}
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ciSocketAddress SocketAddress::FromSockName(const uv_udp_t& handle) {
1051cb0ef41Sopenharmony_ci  return FromUVHandle(uv_udp_getsockname, handle);
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ciSocketAddress SocketAddress::FromPeerName(const uv_tcp_t& handle) {
1091cb0ef41Sopenharmony_ci  return FromUVHandle(uv_tcp_getpeername, handle);
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ciSocketAddress SocketAddress::FromPeerName(const uv_udp_t& handle) {
1131cb0ef41Sopenharmony_ci  return FromUVHandle(uv_udp_getpeername, handle);
1141cb0ef41Sopenharmony_ci}
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_cinamespace {
1171cb0ef41Sopenharmony_ciconstexpr uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_cibool is_match_ipv4(
1201cb0ef41Sopenharmony_ci    const SocketAddress& one,
1211cb0ef41Sopenharmony_ci    const SocketAddress& two) {
1221cb0ef41Sopenharmony_ci  const sockaddr_in* one_in =
1231cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(one.data());
1241cb0ef41Sopenharmony_ci  const sockaddr_in* two_in =
1251cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(two.data());
1261cb0ef41Sopenharmony_ci  return memcmp(&one_in->sin_addr, &two_in->sin_addr, sizeof(uint32_t)) == 0;
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_cibool is_match_ipv6(
1301cb0ef41Sopenharmony_ci    const SocketAddress& one,
1311cb0ef41Sopenharmony_ci    const SocketAddress& two) {
1321cb0ef41Sopenharmony_ci  const sockaddr_in6* one_in =
1331cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(one.data());
1341cb0ef41Sopenharmony_ci  const sockaddr_in6* two_in =
1351cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(two.data());
1361cb0ef41Sopenharmony_ci  return memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16) == 0;
1371cb0ef41Sopenharmony_ci}
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_cibool is_match_ipv4_ipv6(
1401cb0ef41Sopenharmony_ci    const SocketAddress& ipv4,
1411cb0ef41Sopenharmony_ci    const SocketAddress& ipv6) {
1421cb0ef41Sopenharmony_ci  const sockaddr_in* check_ipv4 =
1431cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(ipv4.data());
1441cb0ef41Sopenharmony_ci  const sockaddr_in6* check_ipv6 =
1451cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  const uint8_t* ptr =
1481cb0ef41Sopenharmony_ci      reinterpret_cast<const uint8_t*>(&check_ipv6->sin6_addr);
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  return memcmp(ptr, mask, sizeof(mask)) == 0 &&
1511cb0ef41Sopenharmony_ci         memcmp(ptr + sizeof(mask),
1521cb0ef41Sopenharmony_ci                &check_ipv4->sin_addr,
1531cb0ef41Sopenharmony_ci                sizeof(uint32_t)) == 0;
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciSocketAddress::CompareResult compare_ipv4(
1571cb0ef41Sopenharmony_ci    const SocketAddress& one,
1581cb0ef41Sopenharmony_ci    const SocketAddress& two) {
1591cb0ef41Sopenharmony_ci  const sockaddr_in* one_in =
1601cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(one.data());
1611cb0ef41Sopenharmony_ci  const sockaddr_in* two_in =
1621cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(two.data());
1631cb0ef41Sopenharmony_ci  const uint32_t s_addr_one = ntohl(one_in->sin_addr.s_addr);
1641cb0ef41Sopenharmony_ci  const uint32_t s_addr_two = ntohl(two_in->sin_addr.s_addr);
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  if (s_addr_one < s_addr_two)
1671cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::LESS_THAN;
1681cb0ef41Sopenharmony_ci  else if (s_addr_one == s_addr_two)
1691cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::SAME;
1701cb0ef41Sopenharmony_ci  else
1711cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::GREATER_THAN;
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ciSocketAddress::CompareResult compare_ipv6(
1751cb0ef41Sopenharmony_ci    const SocketAddress& one,
1761cb0ef41Sopenharmony_ci    const SocketAddress& two) {
1771cb0ef41Sopenharmony_ci  const sockaddr_in6* one_in =
1781cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(one.data());
1791cb0ef41Sopenharmony_ci  const sockaddr_in6* two_in =
1801cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(two.data());
1811cb0ef41Sopenharmony_ci  int ret = memcmp(&one_in->sin6_addr, &two_in->sin6_addr, 16);
1821cb0ef41Sopenharmony_ci  if (ret < 0)
1831cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::LESS_THAN;
1841cb0ef41Sopenharmony_ci  else if (ret > 0)
1851cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::GREATER_THAN;
1861cb0ef41Sopenharmony_ci  return SocketAddress::CompareResult::SAME;
1871cb0ef41Sopenharmony_ci}
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ciSocketAddress::CompareResult compare_ipv4_ipv6(
1901cb0ef41Sopenharmony_ci    const SocketAddress& ipv4,
1911cb0ef41Sopenharmony_ci    const SocketAddress& ipv6) {
1921cb0ef41Sopenharmony_ci  const sockaddr_in* ipv4_in =
1931cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(ipv4.data());
1941cb0ef41Sopenharmony_ci  const sockaddr_in6 * ipv6_in =
1951cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(ipv6.data());
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  const uint8_t* ptr =
1981cb0ef41Sopenharmony_ci      reinterpret_cast<const uint8_t*>(&ipv6_in->sin6_addr);
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  if (memcmp(ptr, mask, sizeof(mask)) != 0)
2011cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::NOT_COMPARABLE;
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  int ret = memcmp(
2041cb0ef41Sopenharmony_ci      &ipv4_in->sin_addr,
2051cb0ef41Sopenharmony_ci      ptr + sizeof(mask),
2061cb0ef41Sopenharmony_ci      sizeof(uint32_t));
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  if (ret < 0)
2091cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::LESS_THAN;
2101cb0ef41Sopenharmony_ci  else if (ret > 0)
2111cb0ef41Sopenharmony_ci    return SocketAddress::CompareResult::GREATER_THAN;
2121cb0ef41Sopenharmony_ci  return SocketAddress::CompareResult::SAME;
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_cibool in_network_ipv4(
2161cb0ef41Sopenharmony_ci    const SocketAddress& ip,
2171cb0ef41Sopenharmony_ci    const SocketAddress& net,
2181cb0ef41Sopenharmony_ci    int prefix) {
2191cb0ef41Sopenharmony_ci  uint32_t mask = ((1ull << prefix) - 1) << (32 - prefix);
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  const sockaddr_in* ip_in =
2221cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(ip.data());
2231cb0ef41Sopenharmony_ci  const sockaddr_in* net_in =
2241cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(net.data());
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  return (htonl(ip_in->sin_addr.s_addr) & mask) ==
2271cb0ef41Sopenharmony_ci         (htonl(net_in->sin_addr.s_addr) & mask);
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_cibool in_network_ipv6(
2311cb0ef41Sopenharmony_ci    const SocketAddress& ip,
2321cb0ef41Sopenharmony_ci    const SocketAddress& net,
2331cb0ef41Sopenharmony_ci    int prefix) {
2341cb0ef41Sopenharmony_ci  // Special case, if prefix == 128, then just do a
2351cb0ef41Sopenharmony_ci  // straight comparison.
2361cb0ef41Sopenharmony_ci  if (prefix == 128)
2371cb0ef41Sopenharmony_ci    return compare_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  uint8_t r = prefix % 8;
2401cb0ef41Sopenharmony_ci  int len = (prefix - r) / 8;
2411cb0ef41Sopenharmony_ci  uint8_t mask = ((1 << r) - 1) << (8 - r);
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  const sockaddr_in6* ip_in =
2441cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(ip.data());
2451cb0ef41Sopenharmony_ci  const sockaddr_in6* net_in =
2461cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(net.data());
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  if (memcmp(&ip_in->sin6_addr, &net_in->sin6_addr, len) != 0)
2491cb0ef41Sopenharmony_ci    return false;
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci  const uint8_t* p1 = reinterpret_cast<const uint8_t*>(
2521cb0ef41Sopenharmony_ci      ip_in->sin6_addr.s6_addr);
2531cb0ef41Sopenharmony_ci  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
2541cb0ef41Sopenharmony_ci      net_in->sin6_addr.s6_addr);
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  return (p1[len] & mask) == (p2[len] & mask);
2571cb0ef41Sopenharmony_ci}
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_cibool in_network_ipv4_ipv6(
2601cb0ef41Sopenharmony_ci    const SocketAddress& ip,
2611cb0ef41Sopenharmony_ci    const SocketAddress& net,
2621cb0ef41Sopenharmony_ci    int prefix) {
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci  if (prefix == 128)
2651cb0ef41Sopenharmony_ci    return compare_ipv4_ipv6(ip, net) == SocketAddress::CompareResult::SAME;
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  uint8_t r = prefix % 8;
2681cb0ef41Sopenharmony_ci  int len = (prefix - r) / 8;
2691cb0ef41Sopenharmony_ci  uint8_t mask = ((1 << r) - 1) << (8 - r);
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  const sockaddr_in* ip_in =
2721cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(ip.data());
2731cb0ef41Sopenharmony_ci  const sockaddr_in6* net_in =
2741cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(net.data());
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  uint8_t ip_mask[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0};
2771cb0ef41Sopenharmony_ci  uint8_t* ptr = ip_mask;
2781cb0ef41Sopenharmony_ci  memcpy(ptr + 12, &ip_in->sin_addr, 4);
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci  if (memcmp(ptr, &net_in->sin6_addr, len) != 0)
2811cb0ef41Sopenharmony_ci    return false;
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci  ptr += len;
2841cb0ef41Sopenharmony_ci  const uint8_t* p2 = reinterpret_cast<const uint8_t*>(
2851cb0ef41Sopenharmony_ci      net_in->sin6_addr.s6_addr);
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  return (ptr[0] & mask) == (p2[len] & mask);
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_cibool in_network_ipv6_ipv4(
2911cb0ef41Sopenharmony_ci    const SocketAddress& ip,
2921cb0ef41Sopenharmony_ci    const SocketAddress& net,
2931cb0ef41Sopenharmony_ci    int prefix) {
2941cb0ef41Sopenharmony_ci  if (prefix == 32)
2951cb0ef41Sopenharmony_ci    return compare_ipv4_ipv6(net, ip) == SocketAddress::CompareResult::SAME;
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci  uint32_t m = ((1ull << prefix) - 1) << (32 - prefix);
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  const sockaddr_in6* ip_in =
3001cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in6*>(ip.data());
3011cb0ef41Sopenharmony_ci  const sockaddr_in* net_in =
3021cb0ef41Sopenharmony_ci      reinterpret_cast<const sockaddr_in*>(net.data());
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci  const uint8_t* ptr =
3051cb0ef41Sopenharmony_ci      reinterpret_cast<const uint8_t*>(&ip_in->sin6_addr);
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  if (memcmp(ptr, mask, sizeof(mask)) != 0)
3081cb0ef41Sopenharmony_ci    return false;
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci  ptr += sizeof(mask);
3111cb0ef41Sopenharmony_ci  uint32_t check = ReadUint32BE(ptr);
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci  return (check & m) == (htonl(net_in->sin_addr.s_addr) & m);
3141cb0ef41Sopenharmony_ci}
3151cb0ef41Sopenharmony_ci}  // namespace
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci// TODO(@jasnell): The implementations of is_match, compare, and
3181cb0ef41Sopenharmony_ci// is_in_network have not been performance optimized and could
3191cb0ef41Sopenharmony_ci// likely benefit from work on more performant approaches.
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_cibool SocketAddress::is_match(const SocketAddress& other) const {
3221cb0ef41Sopenharmony_ci  switch (family()) {
3231cb0ef41Sopenharmony_ci    case AF_INET:
3241cb0ef41Sopenharmony_ci      switch (other.family()) {
3251cb0ef41Sopenharmony_ci        case AF_INET: return is_match_ipv4(*this, other);
3261cb0ef41Sopenharmony_ci        case AF_INET6: return is_match_ipv4_ipv6(*this, other);
3271cb0ef41Sopenharmony_ci      }
3281cb0ef41Sopenharmony_ci      break;
3291cb0ef41Sopenharmony_ci    case AF_INET6:
3301cb0ef41Sopenharmony_ci      switch (other.family()) {
3311cb0ef41Sopenharmony_ci        case AF_INET: return is_match_ipv4_ipv6(other, *this);
3321cb0ef41Sopenharmony_ci        case AF_INET6: return is_match_ipv6(*this, other);
3331cb0ef41Sopenharmony_ci      }
3341cb0ef41Sopenharmony_ci      break;
3351cb0ef41Sopenharmony_ci  }
3361cb0ef41Sopenharmony_ci  return false;
3371cb0ef41Sopenharmony_ci}
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ciSocketAddress::CompareResult SocketAddress::compare(
3401cb0ef41Sopenharmony_ci    const SocketAddress& other) const {
3411cb0ef41Sopenharmony_ci  switch (family()) {
3421cb0ef41Sopenharmony_ci    case AF_INET:
3431cb0ef41Sopenharmony_ci      switch (other.family()) {
3441cb0ef41Sopenharmony_ci        case AF_INET: return compare_ipv4(*this, other);
3451cb0ef41Sopenharmony_ci        case AF_INET6: return compare_ipv4_ipv6(*this, other);
3461cb0ef41Sopenharmony_ci      }
3471cb0ef41Sopenharmony_ci      break;
3481cb0ef41Sopenharmony_ci    case AF_INET6:
3491cb0ef41Sopenharmony_ci      switch (other.family()) {
3501cb0ef41Sopenharmony_ci        case AF_INET: {
3511cb0ef41Sopenharmony_ci          CompareResult c = compare_ipv4_ipv6(other, *this);
3521cb0ef41Sopenharmony_ci          switch (c) {
3531cb0ef41Sopenharmony_ci            case SocketAddress::CompareResult::NOT_COMPARABLE:
3541cb0ef41Sopenharmony_ci              // Fall through
3551cb0ef41Sopenharmony_ci            case SocketAddress::CompareResult::SAME:
3561cb0ef41Sopenharmony_ci              return c;
3571cb0ef41Sopenharmony_ci            case SocketAddress::CompareResult::GREATER_THAN:
3581cb0ef41Sopenharmony_ci              return SocketAddress::CompareResult::LESS_THAN;
3591cb0ef41Sopenharmony_ci            case SocketAddress::CompareResult::LESS_THAN:
3601cb0ef41Sopenharmony_ci              return SocketAddress::CompareResult::GREATER_THAN;
3611cb0ef41Sopenharmony_ci          }
3621cb0ef41Sopenharmony_ci          break;
3631cb0ef41Sopenharmony_ci        }
3641cb0ef41Sopenharmony_ci        case AF_INET6: return compare_ipv6(*this, other);
3651cb0ef41Sopenharmony_ci      }
3661cb0ef41Sopenharmony_ci      break;
3671cb0ef41Sopenharmony_ci  }
3681cb0ef41Sopenharmony_ci  return SocketAddress::CompareResult::NOT_COMPARABLE;
3691cb0ef41Sopenharmony_ci}
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_cibool SocketAddress::is_in_network(
3721cb0ef41Sopenharmony_ci    const SocketAddress& other,
3731cb0ef41Sopenharmony_ci    int prefix) const {
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci  switch (family()) {
3761cb0ef41Sopenharmony_ci    case AF_INET:
3771cb0ef41Sopenharmony_ci      switch (other.family()) {
3781cb0ef41Sopenharmony_ci        case AF_INET: return in_network_ipv4(*this, other, prefix);
3791cb0ef41Sopenharmony_ci        case AF_INET6: return in_network_ipv4_ipv6(*this, other, prefix);
3801cb0ef41Sopenharmony_ci      }
3811cb0ef41Sopenharmony_ci      break;
3821cb0ef41Sopenharmony_ci    case AF_INET6:
3831cb0ef41Sopenharmony_ci      switch (other.family()) {
3841cb0ef41Sopenharmony_ci        case AF_INET: return in_network_ipv6_ipv4(*this, other, prefix);
3851cb0ef41Sopenharmony_ci        case AF_INET6: return in_network_ipv6(*this, other, prefix);
3861cb0ef41Sopenharmony_ci      }
3871cb0ef41Sopenharmony_ci      break;
3881cb0ef41Sopenharmony_ci  }
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  return false;
3911cb0ef41Sopenharmony_ci}
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ciSocketAddressBlockList::SocketAddressBlockList(
3941cb0ef41Sopenharmony_ci    std::shared_ptr<SocketAddressBlockList> parent)
3951cb0ef41Sopenharmony_ci    : parent_(parent) {}
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_civoid SocketAddressBlockList::AddSocketAddress(
3981cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address) {
3991cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
4001cb0ef41Sopenharmony_ci  std::unique_ptr<Rule> rule =
4011cb0ef41Sopenharmony_ci      std::make_unique<SocketAddressRule>(address);
4021cb0ef41Sopenharmony_ci  rules_.emplace_front(std::move(rule));
4031cb0ef41Sopenharmony_ci  address_rules_[*address.get()] = rules_.begin();
4041cb0ef41Sopenharmony_ci}
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_civoid SocketAddressBlockList::RemoveSocketAddress(
4071cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address) {
4081cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
4091cb0ef41Sopenharmony_ci  auto it = address_rules_.find(*address.get());
4101cb0ef41Sopenharmony_ci  if (it != std::end(address_rules_)) {
4111cb0ef41Sopenharmony_ci    rules_.erase(it->second);
4121cb0ef41Sopenharmony_ci    address_rules_.erase(it);
4131cb0ef41Sopenharmony_ci  }
4141cb0ef41Sopenharmony_ci}
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_civoid SocketAddressBlockList::AddSocketAddressRange(
4171cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& start,
4181cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& end) {
4191cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
4201cb0ef41Sopenharmony_ci  std::unique_ptr<Rule> rule =
4211cb0ef41Sopenharmony_ci      std::make_unique<SocketAddressRangeRule>(start, end);
4221cb0ef41Sopenharmony_ci  rules_.emplace_front(std::move(rule));
4231cb0ef41Sopenharmony_ci}
4241cb0ef41Sopenharmony_ci
4251cb0ef41Sopenharmony_civoid SocketAddressBlockList::AddSocketAddressMask(
4261cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& network,
4271cb0ef41Sopenharmony_ci    int prefix) {
4281cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
4291cb0ef41Sopenharmony_ci  std::unique_ptr<Rule> rule =
4301cb0ef41Sopenharmony_ci      std::make_unique<SocketAddressMaskRule>(network, prefix);
4311cb0ef41Sopenharmony_ci  rules_.emplace_front(std::move(rule));
4321cb0ef41Sopenharmony_ci}
4331cb0ef41Sopenharmony_ci
4341cb0ef41Sopenharmony_cibool SocketAddressBlockList::Apply(
4351cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address) {
4361cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
4371cb0ef41Sopenharmony_ci  for (const auto& rule : rules_) {
4381cb0ef41Sopenharmony_ci    if (rule->Apply(address))
4391cb0ef41Sopenharmony_ci      return true;
4401cb0ef41Sopenharmony_ci  }
4411cb0ef41Sopenharmony_ci  return parent_ ? parent_->Apply(address) : false;
4421cb0ef41Sopenharmony_ci}
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ciSocketAddressBlockList::SocketAddressRule::SocketAddressRule(
4451cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address_)
4461cb0ef41Sopenharmony_ci    : address(address_) {}
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ciSocketAddressBlockList::SocketAddressRangeRule::SocketAddressRangeRule(
4491cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& start_,
4501cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& end_)
4511cb0ef41Sopenharmony_ci    : start(start_),
4521cb0ef41Sopenharmony_ci      end(end_) {}
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ciSocketAddressBlockList::SocketAddressMaskRule::SocketAddressMaskRule(
4551cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& network_,
4561cb0ef41Sopenharmony_ci    int prefix_)
4571cb0ef41Sopenharmony_ci    : network(network_),
4581cb0ef41Sopenharmony_ci      prefix(prefix_) {}
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_cibool SocketAddressBlockList::SocketAddressRule::Apply(
4611cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address) {
4621cb0ef41Sopenharmony_ci  return this->address->is_match(*address.get());
4631cb0ef41Sopenharmony_ci}
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_cistd::string SocketAddressBlockList::SocketAddressRule::ToString() {
4661cb0ef41Sopenharmony_ci  std::string ret = "Address: ";
4671cb0ef41Sopenharmony_ci  ret += address->family() == AF_INET ? "IPv4" : "IPv6";
4681cb0ef41Sopenharmony_ci  ret += " ";
4691cb0ef41Sopenharmony_ci  ret += address->address();
4701cb0ef41Sopenharmony_ci  return ret;
4711cb0ef41Sopenharmony_ci}
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_cibool SocketAddressBlockList::SocketAddressRangeRule::Apply(
4741cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address) {
4751cb0ef41Sopenharmony_ci  return *address.get() >= *start.get() &&
4761cb0ef41Sopenharmony_ci         *address.get() <= *end.get();
4771cb0ef41Sopenharmony_ci}
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_cistd::string SocketAddressBlockList::SocketAddressRangeRule::ToString() {
4801cb0ef41Sopenharmony_ci  std::string ret = "Range: ";
4811cb0ef41Sopenharmony_ci  ret += start->family() == AF_INET ? "IPv4" : "IPv6";
4821cb0ef41Sopenharmony_ci  ret += " ";
4831cb0ef41Sopenharmony_ci  ret += start->address();
4841cb0ef41Sopenharmony_ci  ret += "-";
4851cb0ef41Sopenharmony_ci  ret += end->address();
4861cb0ef41Sopenharmony_ci  return ret;
4871cb0ef41Sopenharmony_ci}
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_cibool SocketAddressBlockList::SocketAddressMaskRule::Apply(
4901cb0ef41Sopenharmony_ci    const std::shared_ptr<SocketAddress>& address) {
4911cb0ef41Sopenharmony_ci  return address->is_in_network(*network.get(), prefix);
4921cb0ef41Sopenharmony_ci}
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_cistd::string SocketAddressBlockList::SocketAddressMaskRule::ToString() {
4951cb0ef41Sopenharmony_ci  std::string ret = "Subnet: ";
4961cb0ef41Sopenharmony_ci  ret += network->family() == AF_INET ? "IPv4" : "IPv6";
4971cb0ef41Sopenharmony_ci  ret += " ";
4981cb0ef41Sopenharmony_ci  ret += network->address();
4991cb0ef41Sopenharmony_ci  ret += "/" + std::to_string(prefix);
5001cb0ef41Sopenharmony_ci  return ret;
5011cb0ef41Sopenharmony_ci}
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ciMaybeLocal<Array> SocketAddressBlockList::ListRules(Environment* env) {
5041cb0ef41Sopenharmony_ci  Mutex::ScopedLock lock(mutex_);
5051cb0ef41Sopenharmony_ci  std::vector<Local<Value>> rules;
5061cb0ef41Sopenharmony_ci  if (!ListRules(env, &rules))
5071cb0ef41Sopenharmony_ci    return MaybeLocal<Array>();
5081cb0ef41Sopenharmony_ci  return Array::New(env->isolate(), rules.data(), rules.size());
5091cb0ef41Sopenharmony_ci}
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_cibool SocketAddressBlockList::ListRules(
5121cb0ef41Sopenharmony_ci    Environment* env,
5131cb0ef41Sopenharmony_ci    std::vector<v8::Local<v8::Value>>* rules) {
5141cb0ef41Sopenharmony_ci  if (parent_ && !parent_->ListRules(env, rules))
5151cb0ef41Sopenharmony_ci    return false;
5161cb0ef41Sopenharmony_ci  for (const auto& rule : rules_) {
5171cb0ef41Sopenharmony_ci    Local<Value> str;
5181cb0ef41Sopenharmony_ci    if (!rule->ToV8String(env).ToLocal(&str))
5191cb0ef41Sopenharmony_ci      return false;
5201cb0ef41Sopenharmony_ci    rules->push_back(str);
5211cb0ef41Sopenharmony_ci  }
5221cb0ef41Sopenharmony_ci  return true;
5231cb0ef41Sopenharmony_ci}
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_civoid SocketAddressBlockList::MemoryInfo(node::MemoryTracker* tracker) const {
5261cb0ef41Sopenharmony_ci  tracker->TrackField("rules", rules_);
5271cb0ef41Sopenharmony_ci}
5281cb0ef41Sopenharmony_ci
5291cb0ef41Sopenharmony_civoid SocketAddressBlockList::SocketAddressRule::MemoryInfo(
5301cb0ef41Sopenharmony_ci    node::MemoryTracker* tracker) const {
5311cb0ef41Sopenharmony_ci  tracker->TrackField("address", address);
5321cb0ef41Sopenharmony_ci}
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_civoid SocketAddressBlockList::SocketAddressRangeRule::MemoryInfo(
5351cb0ef41Sopenharmony_ci    node::MemoryTracker* tracker) const {
5361cb0ef41Sopenharmony_ci  tracker->TrackField("start", start);
5371cb0ef41Sopenharmony_ci  tracker->TrackField("end", end);
5381cb0ef41Sopenharmony_ci}
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_civoid SocketAddressBlockList::SocketAddressMaskRule::MemoryInfo(
5411cb0ef41Sopenharmony_ci    node::MemoryTracker* tracker) const {
5421cb0ef41Sopenharmony_ci  tracker->TrackField("network", network);
5431cb0ef41Sopenharmony_ci}
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ciSocketAddressBlockListWrap::SocketAddressBlockListWrap(
5461cb0ef41Sopenharmony_ci    Environment* env,
5471cb0ef41Sopenharmony_ci    Local<Object> wrap,
5481cb0ef41Sopenharmony_ci    std::shared_ptr<SocketAddressBlockList> blocklist)
5491cb0ef41Sopenharmony_ci    : BaseObject(env, wrap),
5501cb0ef41Sopenharmony_ci      blocklist_(std::move(blocklist)) {
5511cb0ef41Sopenharmony_ci  MakeWeak();
5521cb0ef41Sopenharmony_ci}
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ciBaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
5551cb0ef41Sopenharmony_ci    Environment* env) {
5561cb0ef41Sopenharmony_ci  Local<Object> obj;
5571cb0ef41Sopenharmony_ci  if (!env->blocklist_constructor_template()
5581cb0ef41Sopenharmony_ci          ->InstanceTemplate()
5591cb0ef41Sopenharmony_ci          ->NewInstance(env->context()).ToLocal(&obj)) {
5601cb0ef41Sopenharmony_ci    return BaseObjectPtr<SocketAddressBlockListWrap>();
5611cb0ef41Sopenharmony_ci  }
5621cb0ef41Sopenharmony_ci  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
5631cb0ef41Sopenharmony_ci      MakeBaseObject<SocketAddressBlockListWrap>(env, obj);
5641cb0ef41Sopenharmony_ci  CHECK(wrap);
5651cb0ef41Sopenharmony_ci  return wrap;
5661cb0ef41Sopenharmony_ci}
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ciBaseObjectPtr<SocketAddressBlockListWrap> SocketAddressBlockListWrap::New(
5691cb0ef41Sopenharmony_ci    Environment* env,
5701cb0ef41Sopenharmony_ci    std::shared_ptr<SocketAddressBlockList> blocklist) {
5711cb0ef41Sopenharmony_ci  Local<Object> obj;
5721cb0ef41Sopenharmony_ci  if (!env->blocklist_constructor_template()
5731cb0ef41Sopenharmony_ci          ->InstanceTemplate()
5741cb0ef41Sopenharmony_ci          ->NewInstance(env->context()).ToLocal(&obj)) {
5751cb0ef41Sopenharmony_ci    return BaseObjectPtr<SocketAddressBlockListWrap>();
5761cb0ef41Sopenharmony_ci  }
5771cb0ef41Sopenharmony_ci  BaseObjectPtr<SocketAddressBlockListWrap> wrap =
5781cb0ef41Sopenharmony_ci      MakeBaseObject<SocketAddressBlockListWrap>(
5791cb0ef41Sopenharmony_ci          env,
5801cb0ef41Sopenharmony_ci          obj,
5811cb0ef41Sopenharmony_ci          std::move(blocklist));
5821cb0ef41Sopenharmony_ci  CHECK(wrap);
5831cb0ef41Sopenharmony_ci  return wrap;
5841cb0ef41Sopenharmony_ci}
5851cb0ef41Sopenharmony_ci
5861cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::New(
5871cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
5881cb0ef41Sopenharmony_ci  CHECK(args.IsConstructCall());
5891cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
5901cb0ef41Sopenharmony_ci  new SocketAddressBlockListWrap(env, args.This());
5911cb0ef41Sopenharmony_ci}
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::AddAddress(
5941cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
5951cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
5961cb0ef41Sopenharmony_ci  SocketAddressBlockListWrap* wrap;
5971cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  CHECK(SocketAddressBase::HasInstance(env, args[0]));
6001cb0ef41Sopenharmony_ci  SocketAddressBase* addr;
6011cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
6021cb0ef41Sopenharmony_ci
6031cb0ef41Sopenharmony_ci  wrap->blocklist_->AddSocketAddress(addr->address());
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(true);
6061cb0ef41Sopenharmony_ci}
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::AddRange(
6091cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
6101cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
6111cb0ef41Sopenharmony_ci  SocketAddressBlockListWrap* wrap;
6121cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  CHECK(SocketAddressBase::HasInstance(env, args[0]));
6151cb0ef41Sopenharmony_ci  CHECK(SocketAddressBase::HasInstance(env, args[1]));
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci  SocketAddressBase* start_addr;
6181cb0ef41Sopenharmony_ci  SocketAddressBase* end_addr;
6191cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&start_addr, args[0]);
6201cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&end_addr, args[1]);
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  // Starting address must come before the end address
6231cb0ef41Sopenharmony_ci  if (*start_addr->address().get() > *end_addr->address().get())
6241cb0ef41Sopenharmony_ci    return args.GetReturnValue().Set(false);
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci  wrap->blocklist_->AddSocketAddressRange(
6271cb0ef41Sopenharmony_ci      start_addr->address(),
6281cb0ef41Sopenharmony_ci      end_addr->address());
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(true);
6311cb0ef41Sopenharmony_ci}
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::AddSubnet(
6341cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
6351cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
6361cb0ef41Sopenharmony_ci  SocketAddressBlockListWrap* wrap;
6371cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci  CHECK(SocketAddressBase::HasInstance(env, args[0]));
6401cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());
6411cb0ef41Sopenharmony_ci
6421cb0ef41Sopenharmony_ci  SocketAddressBase* addr;
6431cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci  int32_t prefix;
6461cb0ef41Sopenharmony_ci  if (!args[1]->Int32Value(env->context()).To(&prefix)) {
6471cb0ef41Sopenharmony_ci    return;
6481cb0ef41Sopenharmony_ci  }
6491cb0ef41Sopenharmony_ci
6501cb0ef41Sopenharmony_ci  CHECK_IMPLIES(addr->address()->family() == AF_INET, prefix <= 32);
6511cb0ef41Sopenharmony_ci  CHECK_IMPLIES(addr->address()->family() == AF_INET6, prefix <= 128);
6521cb0ef41Sopenharmony_ci  CHECK_GE(prefix, 0);
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ci  wrap->blocklist_->AddSocketAddressMask(addr->address(), prefix);
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(true);
6571cb0ef41Sopenharmony_ci}
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::Check(
6601cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
6611cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
6621cb0ef41Sopenharmony_ci  SocketAddressBlockListWrap* wrap;
6631cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ci  CHECK(SocketAddressBase::HasInstance(env, args[0]));
6661cb0ef41Sopenharmony_ci  SocketAddressBase* addr;
6671cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&addr, args[0]);
6681cb0ef41Sopenharmony_ci
6691cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(wrap->blocklist_->Apply(addr->address()));
6701cb0ef41Sopenharmony_ci}
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::GetRules(
6731cb0ef41Sopenharmony_ci    const FunctionCallbackInfo<Value>& args) {
6741cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
6751cb0ef41Sopenharmony_ci  SocketAddressBlockListWrap* wrap;
6761cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
6771cb0ef41Sopenharmony_ci  Local<Array> rules;
6781cb0ef41Sopenharmony_ci  if (wrap->blocklist_->ListRules(env).ToLocal(&rules))
6791cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(rules);
6801cb0ef41Sopenharmony_ci}
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::MemoryInfo(MemoryTracker* tracker) const {
6831cb0ef41Sopenharmony_ci  blocklist_->MemoryInfo(tracker);
6841cb0ef41Sopenharmony_ci}
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_cistd::unique_ptr<worker::TransferData>
6871cb0ef41Sopenharmony_ciSocketAddressBlockListWrap::CloneForMessaging() const {
6881cb0ef41Sopenharmony_ci  return std::make_unique<TransferData>(this);
6891cb0ef41Sopenharmony_ci}
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_cibool SocketAddressBlockListWrap::HasInstance(
6921cb0ef41Sopenharmony_ci    Environment* env,
6931cb0ef41Sopenharmony_ci    Local<Value> value) {
6941cb0ef41Sopenharmony_ci  return GetConstructorTemplate(env)->HasInstance(value);
6951cb0ef41Sopenharmony_ci}
6961cb0ef41Sopenharmony_ci
6971cb0ef41Sopenharmony_ciLocal<FunctionTemplate> SocketAddressBlockListWrap::GetConstructorTemplate(
6981cb0ef41Sopenharmony_ci    Environment* env) {
6991cb0ef41Sopenharmony_ci  Local<FunctionTemplate> tmpl = env->blocklist_constructor_template();
7001cb0ef41Sopenharmony_ci  if (tmpl.IsEmpty()) {
7011cb0ef41Sopenharmony_ci    Isolate* isolate = env->isolate();
7021cb0ef41Sopenharmony_ci    tmpl = NewFunctionTemplate(isolate, SocketAddressBlockListWrap::New);
7031cb0ef41Sopenharmony_ci    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "BlockList"));
7041cb0ef41Sopenharmony_ci    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
7051cb0ef41Sopenharmony_ci    tmpl->InstanceTemplate()->SetInternalFieldCount(kInternalFieldCount);
7061cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "addAddress", AddAddress);
7071cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "addRange", AddRange);
7081cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "addSubnet", AddSubnet);
7091cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "check", Check);
7101cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "getRules", GetRules);
7111cb0ef41Sopenharmony_ci    env->set_blocklist_constructor_template(tmpl);
7121cb0ef41Sopenharmony_ci  }
7131cb0ef41Sopenharmony_ci  return tmpl;
7141cb0ef41Sopenharmony_ci}
7151cb0ef41Sopenharmony_ci
7161cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::Initialize(
7171cb0ef41Sopenharmony_ci    Local<Object> target,
7181cb0ef41Sopenharmony_ci    Local<Value> unused,
7191cb0ef41Sopenharmony_ci    Local<Context> context,
7201cb0ef41Sopenharmony_ci    void* priv) {
7211cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(context);
7221cb0ef41Sopenharmony_ci
7231cb0ef41Sopenharmony_ci  SetConstructorFunction(context,
7241cb0ef41Sopenharmony_ci                         target,
7251cb0ef41Sopenharmony_ci                         "BlockList",
7261cb0ef41Sopenharmony_ci                         GetConstructorTemplate(env),
7271cb0ef41Sopenharmony_ci                         SetConstructorFunctionFlag::NONE);
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ci  SocketAddressBase::Initialize(env, target);
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, AF_INET);
7321cb0ef41Sopenharmony_ci  NODE_DEFINE_CONSTANT(target, AF_INET6);
7331cb0ef41Sopenharmony_ci}
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ciBaseObjectPtr<BaseObject> SocketAddressBlockListWrap::TransferData::Deserialize(
7361cb0ef41Sopenharmony_ci    Environment* env,
7371cb0ef41Sopenharmony_ci    Local<Context> context,
7381cb0ef41Sopenharmony_ci    std::unique_ptr<worker::TransferData> self) {
7391cb0ef41Sopenharmony_ci  return New(env, std::move(blocklist_));
7401cb0ef41Sopenharmony_ci}
7411cb0ef41Sopenharmony_ci
7421cb0ef41Sopenharmony_civoid SocketAddressBlockListWrap::TransferData::MemoryInfo(
7431cb0ef41Sopenharmony_ci    MemoryTracker* tracker) const {
7441cb0ef41Sopenharmony_ci  blocklist_->MemoryInfo(tracker);
7451cb0ef41Sopenharmony_ci}
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_cibool SocketAddressBase::HasInstance(Environment* env, Local<Value> value) {
7481cb0ef41Sopenharmony_ci  return GetConstructorTemplate(env)->HasInstance(value);
7491cb0ef41Sopenharmony_ci}
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ciLocal<FunctionTemplate> SocketAddressBase::GetConstructorTemplate(
7521cb0ef41Sopenharmony_ci    Environment* env) {
7531cb0ef41Sopenharmony_ci  Local<FunctionTemplate> tmpl = env->socketaddress_constructor_template();
7541cb0ef41Sopenharmony_ci  if (tmpl.IsEmpty()) {
7551cb0ef41Sopenharmony_ci    Isolate* isolate = env->isolate();
7561cb0ef41Sopenharmony_ci    tmpl = NewFunctionTemplate(isolate, New);
7571cb0ef41Sopenharmony_ci    tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "SocketAddress"));
7581cb0ef41Sopenharmony_ci    tmpl->InstanceTemplate()->SetInternalFieldCount(
7591cb0ef41Sopenharmony_ci        SocketAddressBase::kInternalFieldCount);
7601cb0ef41Sopenharmony_ci    tmpl->Inherit(BaseObject::GetConstructorTemplate(env));
7611cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "detail", Detail);
7621cb0ef41Sopenharmony_ci    SetProtoMethod(isolate, tmpl, "legacyDetail", LegacyDetail);
7631cb0ef41Sopenharmony_ci    SetProtoMethodNoSideEffect(isolate, tmpl, "flowlabel", GetFlowLabel);
7641cb0ef41Sopenharmony_ci    env->set_socketaddress_constructor_template(tmpl);
7651cb0ef41Sopenharmony_ci  }
7661cb0ef41Sopenharmony_ci  return tmpl;
7671cb0ef41Sopenharmony_ci}
7681cb0ef41Sopenharmony_ci
7691cb0ef41Sopenharmony_civoid SocketAddressBase::Initialize(Environment* env, Local<Object> target) {
7701cb0ef41Sopenharmony_ci  SetConstructorFunction(env->context(),
7711cb0ef41Sopenharmony_ci                         target,
7721cb0ef41Sopenharmony_ci                         "SocketAddress",
7731cb0ef41Sopenharmony_ci                         GetConstructorTemplate(env),
7741cb0ef41Sopenharmony_ci                         SetConstructorFunctionFlag::NONE);
7751cb0ef41Sopenharmony_ci}
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_ciBaseObjectPtr<SocketAddressBase> SocketAddressBase::Create(
7781cb0ef41Sopenharmony_ci    Environment* env,
7791cb0ef41Sopenharmony_ci    std::shared_ptr<SocketAddress> address) {
7801cb0ef41Sopenharmony_ci  Local<Object> obj;
7811cb0ef41Sopenharmony_ci  if (!GetConstructorTemplate(env)
7821cb0ef41Sopenharmony_ci          ->InstanceTemplate()
7831cb0ef41Sopenharmony_ci          ->NewInstance(env->context()).ToLocal(&obj)) {
7841cb0ef41Sopenharmony_ci    return BaseObjectPtr<SocketAddressBase>();
7851cb0ef41Sopenharmony_ci  }
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ci  return MakeBaseObject<SocketAddressBase>(env, obj, std::move(address));
7881cb0ef41Sopenharmony_ci}
7891cb0ef41Sopenharmony_ci
7901cb0ef41Sopenharmony_civoid SocketAddressBase::New(const FunctionCallbackInfo<Value>& args) {
7911cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
7921cb0ef41Sopenharmony_ci  CHECK(args.IsConstructCall());
7931cb0ef41Sopenharmony_ci  CHECK(args[0]->IsString());  // address
7941cb0ef41Sopenharmony_ci  CHECK(args[1]->IsInt32());  // port
7951cb0ef41Sopenharmony_ci  CHECK(args[2]->IsInt32());  // family
7961cb0ef41Sopenharmony_ci  CHECK(args[3]->IsUint32());  // flow label
7971cb0ef41Sopenharmony_ci
7981cb0ef41Sopenharmony_ci  Utf8Value address(env->isolate(), args[0]);
7991cb0ef41Sopenharmony_ci  int32_t port = args[1].As<Int32>()->Value();
8001cb0ef41Sopenharmony_ci  int32_t family = args[2].As<Int32>()->Value();
8011cb0ef41Sopenharmony_ci  uint32_t flow_label = args[3].As<Uint32>()->Value();
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci  std::shared_ptr<SocketAddress> addr = std::make_shared<SocketAddress>();
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci  if (!SocketAddress::New(family, *address, port, addr.get()))
8061cb0ef41Sopenharmony_ci    return THROW_ERR_INVALID_ADDRESS(env);
8071cb0ef41Sopenharmony_ci
8081cb0ef41Sopenharmony_ci  addr->set_flow_label(flow_label);
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci  new SocketAddressBase(env, args.This(), std::move(addr));
8111cb0ef41Sopenharmony_ci}
8121cb0ef41Sopenharmony_ci
8131cb0ef41Sopenharmony_civoid SocketAddressBase::Detail(const FunctionCallbackInfo<Value>& args) {
8141cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
8151cb0ef41Sopenharmony_ci  CHECK(args[0]->IsObject());
8161cb0ef41Sopenharmony_ci  Local<Object> detail = args[0].As<Object>();
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci  SocketAddressBase* base;
8191cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ci  Local<Value> address;
8221cb0ef41Sopenharmony_ci  if (!ToV8Value(env->context(), base->address_->address()).ToLocal(&address))
8231cb0ef41Sopenharmony_ci    return;
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_ci  if (detail->Set(env->context(), env->address_string(), address).IsJust() &&
8261cb0ef41Sopenharmony_ci      detail->Set(
8271cb0ef41Sopenharmony_ci          env->context(),
8281cb0ef41Sopenharmony_ci          env->port_string(),
8291cb0ef41Sopenharmony_ci          Int32::New(env->isolate(), base->address_->port())).IsJust() &&
8301cb0ef41Sopenharmony_ci      detail->Set(
8311cb0ef41Sopenharmony_ci          env->context(),
8321cb0ef41Sopenharmony_ci          env->family_string(),
8331cb0ef41Sopenharmony_ci          Int32::New(env->isolate(), base->address_->family())).IsJust() &&
8341cb0ef41Sopenharmony_ci      detail->Set(
8351cb0ef41Sopenharmony_ci          env->context(),
8361cb0ef41Sopenharmony_ci          env->flowlabel_string(),
8371cb0ef41Sopenharmony_ci          Uint32::New(env->isolate(), base->address_->flow_label()))
8381cb0ef41Sopenharmony_ci              .IsJust()) {
8391cb0ef41Sopenharmony_ci    args.GetReturnValue().Set(detail);
8401cb0ef41Sopenharmony_ci  }
8411cb0ef41Sopenharmony_ci}
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_civoid SocketAddressBase::GetFlowLabel(const FunctionCallbackInfo<Value>& args) {
8441cb0ef41Sopenharmony_ci  SocketAddressBase* base;
8451cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
8461cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(base->address_->flow_label());
8471cb0ef41Sopenharmony_ci}
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_civoid SocketAddressBase::LegacyDetail(const FunctionCallbackInfo<Value>& args) {
8501cb0ef41Sopenharmony_ci  Environment* env = Environment::GetCurrent(args);
8511cb0ef41Sopenharmony_ci  SocketAddressBase* base;
8521cb0ef41Sopenharmony_ci  ASSIGN_OR_RETURN_UNWRAP(&base, args.Holder());
8531cb0ef41Sopenharmony_ci  Local<Object> address;
8541cb0ef41Sopenharmony_ci  if (!base->address_->ToJS(env).ToLocal(&address)) return;
8551cb0ef41Sopenharmony_ci  args.GetReturnValue().Set(address);
8561cb0ef41Sopenharmony_ci}
8571cb0ef41Sopenharmony_ci
8581cb0ef41Sopenharmony_ciSocketAddressBase::SocketAddressBase(
8591cb0ef41Sopenharmony_ci    Environment* env,
8601cb0ef41Sopenharmony_ci    Local<Object> wrap,
8611cb0ef41Sopenharmony_ci    std::shared_ptr<SocketAddress> address)
8621cb0ef41Sopenharmony_ci    : BaseObject(env, wrap),
8631cb0ef41Sopenharmony_ci      address_(std::move(address)) {
8641cb0ef41Sopenharmony_ci  MakeWeak();
8651cb0ef41Sopenharmony_ci}
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_civoid SocketAddressBase::MemoryInfo(MemoryTracker* tracker) const {
8681cb0ef41Sopenharmony_ci  tracker->TrackField("address", address_);
8691cb0ef41Sopenharmony_ci}
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_cistd::unique_ptr<worker::TransferData>
8721cb0ef41Sopenharmony_ciSocketAddressBase::CloneForMessaging() const {
8731cb0ef41Sopenharmony_ci  return std::make_unique<TransferData>(this);
8741cb0ef41Sopenharmony_ci}
8751cb0ef41Sopenharmony_ci
8761cb0ef41Sopenharmony_civoid SocketAddressBase::TransferData::MemoryInfo(MemoryTracker* tracker) const {
8771cb0ef41Sopenharmony_ci  tracker->TrackField("address", address_);
8781cb0ef41Sopenharmony_ci}
8791cb0ef41Sopenharmony_ci
8801cb0ef41Sopenharmony_ciBaseObjectPtr<BaseObject> SocketAddressBase::TransferData::Deserialize(
8811cb0ef41Sopenharmony_ci    Environment* env,
8821cb0ef41Sopenharmony_ci    v8::Local<v8::Context> context,
8831cb0ef41Sopenharmony_ci    std::unique_ptr<worker::TransferData> self) {
8841cb0ef41Sopenharmony_ci  return SocketAddressBase::Create(env, std::move(address_));
8851cb0ef41Sopenharmony_ci}
8861cb0ef41Sopenharmony_ci
8871cb0ef41Sopenharmony_ci}  // namespace node
8881cb0ef41Sopenharmony_ci
8891cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(
8901cb0ef41Sopenharmony_ci    block_list, node::SocketAddressBlockListWrap::Initialize)
891