/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/quic/preferredaddress.cc
158 строк
5 KB
James M Snell
quic: flip preferred address policy default to 'ignore'
25 май 2026, 05:14
25 май 2026, 05:14
444ba16
Код
Авторство
О чём код?
#if HAVE_OPENSSL && HAVE_QUIC #include "guard.h" #ifndef OPENSSL_NO_QUIC #include <env-inl.h> #include <ngtcp2/ngtcp2.h> #include <node_errors.h> #include <node_realm-inl.h> #include <node_sockaddr-inl.h> #include <util-inl.h> #include <uv.h> #include <v8.h> #include "cid.h" #include "preferredaddress.h" namespace node { using v8::Just; using v8::Local; using v8::Maybe; using v8::Object; using v8::Value; namespace quic { namespace { template <int FAMILY> std::optional<const PreferredAddress::AddressInfo> get_address_info( const ngtcp2_preferred_addr& paddr) { PreferredAddress::AddressInfo address; address.family = FAMILY; if constexpr (FAMILY == AF_INET) { if (!paddr.ipv4_present) return std::nullopt; address.port = paddr.ipv4.sin_port; if (uv_inet_ntop( FAMILY, &paddr.ipv4.sin_addr, address.host, sizeof(address.host)) != 0) return std::nullopt; } else { if (!paddr.ipv6_present) return std::nullopt; address.port = paddr.ipv6.sin6_port; if (uv_inet_ntop(FAMILY, &paddr.ipv6.sin6_addr, address.host, sizeof(address.host)) != 0) return std::nullopt; } return address; } template <int FAMILY> void copy_to_transport_params(ngtcp2_transport_params* params, const sockaddr* addr) { params->preferred_addr_present = 1; if constexpr (FAMILY == AF_INET) { params->preferred_addr.ipv4_present = 1; memcpy(¶ms->preferred_addr.ipv4, addr, sizeof(sockaddr_in)); } else { DCHECK_EQ(FAMILY, AF_INET6); params->preferred_addr.ipv6_present = 1; memcpy(¶ms->preferred_addr.ipv6, addr, sizeof(sockaddr_in6)); } } bool resolve(const PreferredAddress::AddressInfo& address, uv_getaddrinfo_t* req) { addrinfo hints{}; hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; hints.ai_family = address.family; hints.ai_socktype = SOCK_DGRAM; // ngtcp2 requires the selection of the preferred address // to be synchronous, which means we have to do a sync resolve // using uv_getaddrinfo here. return uv_getaddrinfo(nullptr, req, nullptr, address.host, std::to_string(address.port).data(), &hints) == 0 && req->addrinfo != nullptr; } } // namespace PreferredAddress::PreferredAddress(ngtcp2_path* dest, const ngtcp2_preferred_addr* paddr) : dest_(dest), paddr_(paddr) { DCHECK_NOT_NULL(paddr); DCHECK_NOT_NULL(dest); } std::optional<const PreferredAddress::AddressInfo> PreferredAddress::ipv4() const { return get_address_info<AF_INET>(*paddr_); } std::optional<const PreferredAddress::AddressInfo> PreferredAddress::ipv6() const { return get_address_info<AF_INET6>(*paddr_); } void PreferredAddress::Use(const AddressInfo& address) { uv_getaddrinfo_t req; auto on_exit = OnScopeLeave([&] { if (req.addrinfo != nullptr) uv_freeaddrinfo(req.addrinfo); }); if (resolve(address, &req)) { DCHECK_NOT_NULL(req.addrinfo); dest_->remote.addrlen = req.addrinfo->ai_addrlen; memcpy(dest_->remote.addr, req.addrinfo->ai_addr, req.addrinfo->ai_addrlen); } } void PreferredAddress::Set(ngtcp2_transport_params* params, const sockaddr* addr) { DCHECK_NOT_NULL(params); DCHECK_NOT_NULL(addr); switch (addr->sa_family) { case AF_INET: return copy_to_transport_params<AF_INET>(params, addr); case AF_INET6: return copy_to_transport_params<AF_INET6>(params, addr); default: UNREACHABLE("Unreachable"); } // Any other value is just ignored. } Maybe<PreferredAddress::Policy> PreferredAddress::tryGetPolicy( Environment* env, Local<Value> value) { return value->IsUndefined() ? Just(Policy::USE_PREFERRED) : Just(FromV8Value<Policy>(value)); } void PreferredAddress::Initialize(Environment* env, Local<Object> target) { // The QUIC_* constants are expected to be exported out to be used on // the JavaScript side of the API. static constexpr auto PREFERRED_ADDRESS_USE = static_cast<uint8_t>(Policy::USE_PREFERRED); static constexpr auto PREFERRED_ADDRESS_IGNORE = static_cast<uint8_t>(Policy::IGNORE_PREFERRED); static constexpr auto DEFAULT_PREFERRED_ADDRESS_POLICY = static_cast<uint8_t>(Policy::IGNORE_PREFERRED); NODE_DEFINE_CONSTANT(target, PREFERRED_ADDRESS_IGNORE); NODE_DEFINE_CONSTANT(target, PREFERRED_ADDRESS_USE); NODE_DEFINE_CONSTANT(target, DEFAULT_PREFERRED_ADDRESS_POLICY); } const CID PreferredAddress::cid() const { return CID(&paddr_->cid); } } // namespace quic } // namespace node #endif // OPENSSL_NO_QUIC #endif // HAVE_OPENSSL && HAVE_QUIC