11cb0ef41Sopenharmony_ci#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ci#include "packet.h" 41cb0ef41Sopenharmony_ci#include <base_object-inl.h> 51cb0ef41Sopenharmony_ci#include <crypto/crypto_util.h> 61cb0ef41Sopenharmony_ci#include <env-inl.h> 71cb0ef41Sopenharmony_ci#include <ngtcp2/ngtcp2.h> 81cb0ef41Sopenharmony_ci#include <ngtcp2/ngtcp2_crypto.h> 91cb0ef41Sopenharmony_ci#include <node_sockaddr-inl.h> 101cb0ef41Sopenharmony_ci#include <req_wrap-inl.h> 111cb0ef41Sopenharmony_ci#include <uv.h> 121cb0ef41Sopenharmony_ci#include <v8.h> 131cb0ef41Sopenharmony_ci#include <string> 141cb0ef41Sopenharmony_ci#include "bindingdata.h" 151cb0ef41Sopenharmony_ci#include "cid.h" 161cb0ef41Sopenharmony_ci#include "tokens.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace node { 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ciusing v8::FunctionTemplate; 211cb0ef41Sopenharmony_ciusing v8::Local; 221cb0ef41Sopenharmony_ciusing v8::Object; 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_cinamespace quic { 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace { 271cb0ef41Sopenharmony_cistatic constexpr size_t kRandlen = NGTCP2_MIN_STATELESS_RESET_RANDLEN * 5; 281cb0ef41Sopenharmony_cistatic constexpr size_t kMinStatelessResetLen = 41; 291cb0ef41Sopenharmony_cistatic constexpr size_t kMaxFreeList = 100; 301cb0ef41Sopenharmony_ci} // namespace 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cistruct Packet::Data final : public MemoryRetainer { 331cb0ef41Sopenharmony_ci MaybeStackBuffer<uint8_t, kDefaultMaxPacketLength> data_; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci // The diagnostic_label_ is used only as a debugging tool when 361cb0ef41Sopenharmony_ci // logging debug information about the packet. It identifies 371cb0ef41Sopenharmony_ci // the purpose of the packet. 381cb0ef41Sopenharmony_ci const std::string diagnostic_label_; 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci void MemoryInfo(MemoryTracker* tracker) const override { 411cb0ef41Sopenharmony_ci tracker->TrackFieldWithSize("data", data_.length()); 421cb0ef41Sopenharmony_ci } 431cb0ef41Sopenharmony_ci SET_MEMORY_INFO_NAME(Data) 441cb0ef41Sopenharmony_ci SET_SELF_SIZE(Data) 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci Data(size_t length, std::string_view diagnostic_label) 471cb0ef41Sopenharmony_ci : diagnostic_label_(diagnostic_label) { 481cb0ef41Sopenharmony_ci data_.AllocateSufficientStorage(length); 491cb0ef41Sopenharmony_ci } 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci size_t length() const { return data_.length(); } 521cb0ef41Sopenharmony_ci operator uv_buf_t() { 531cb0ef41Sopenharmony_ci return uv_buf_init(reinterpret_cast<char*>(data_.out()), data_.length()); 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci operator ngtcp2_vec() { return ngtcp2_vec{data_.out(), data_.length()}; } 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci std::string ToString() const { 581cb0ef41Sopenharmony_ci return diagnostic_label_ + ", " + std::to_string(length()); 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci}; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ciconst SocketAddress& Packet::destination() const { 631cb0ef41Sopenharmony_ci return destination_; 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_cibool Packet::is_sending() const { 671cb0ef41Sopenharmony_ci return !!handle_; 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_cisize_t Packet::length() const { 711cb0ef41Sopenharmony_ci return data_ ? data_->length() : 0; 721cb0ef41Sopenharmony_ci} 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ciPacket::operator uv_buf_t() const { 751cb0ef41Sopenharmony_ci return !data_ ? uv_buf_init(nullptr, 0) : *data_; 761cb0ef41Sopenharmony_ci} 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ciPacket::operator ngtcp2_vec() const { 791cb0ef41Sopenharmony_ci return !data_ ? ngtcp2_vec{nullptr, 0} : *data_; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_civoid Packet::Truncate(size_t len) { 831cb0ef41Sopenharmony_ci DCHECK(data_); 841cb0ef41Sopenharmony_ci DCHECK_LE(len, data_->length()); 851cb0ef41Sopenharmony_ci data_->data_.SetLength(len); 861cb0ef41Sopenharmony_ci} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ciLocal<FunctionTemplate> Packet::GetConstructorTemplate(Environment* env) { 891cb0ef41Sopenharmony_ci auto& state = BindingData::Get(env); 901cb0ef41Sopenharmony_ci Local<FunctionTemplate> tmpl = state.packet_constructor_template(); 911cb0ef41Sopenharmony_ci if (tmpl.IsEmpty()) { 921cb0ef41Sopenharmony_ci tmpl = NewFunctionTemplate(env->isolate(), IllegalConstructor); 931cb0ef41Sopenharmony_ci tmpl->Inherit(ReqWrap<uv_udp_send_t>::GetConstructorTemplate(env)); 941cb0ef41Sopenharmony_ci tmpl->InstanceTemplate()->SetInternalFieldCount( 951cb0ef41Sopenharmony_ci Packet::kInternalFieldCount); 961cb0ef41Sopenharmony_ci tmpl->SetClassName(state.packetwrap_string()); 971cb0ef41Sopenharmony_ci state.set_packet_constructor_template(tmpl); 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci return tmpl; 1001cb0ef41Sopenharmony_ci} 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::Create(Environment* env, 1031cb0ef41Sopenharmony_ci Listener* listener, 1041cb0ef41Sopenharmony_ci const SocketAddress& destination, 1051cb0ef41Sopenharmony_ci size_t length, 1061cb0ef41Sopenharmony_ci const char* diagnostic_label) { 1071cb0ef41Sopenharmony_ci auto& binding = BindingData::Get(env); 1081cb0ef41Sopenharmony_ci if (binding.packet_freelist.empty()) { 1091cb0ef41Sopenharmony_ci Local<Object> obj; 1101cb0ef41Sopenharmony_ci if (UNLIKELY(!GetConstructorTemplate(env) 1111cb0ef41Sopenharmony_ci ->InstanceTemplate() 1121cb0ef41Sopenharmony_ci ->NewInstance(env->context()) 1131cb0ef41Sopenharmony_ci .ToLocal(&obj))) { 1141cb0ef41Sopenharmony_ci return BaseObjectPtr<Packet>(); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci return MakeBaseObject<Packet>( 1181cb0ef41Sopenharmony_ci env, listener, obj, destination, length, diagnostic_label); 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci return FromFreeList(env, 1221cb0ef41Sopenharmony_ci std::make_shared<Data>(length, diagnostic_label), 1231cb0ef41Sopenharmony_ci listener, 1241cb0ef41Sopenharmony_ci destination); 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::Clone() const { 1281cb0ef41Sopenharmony_ci auto& binding = BindingData::Get(env()); 1291cb0ef41Sopenharmony_ci if (binding.packet_freelist.empty()) { 1301cb0ef41Sopenharmony_ci Local<Object> obj; 1311cb0ef41Sopenharmony_ci if (UNLIKELY(!GetConstructorTemplate(env()) 1321cb0ef41Sopenharmony_ci ->InstanceTemplate() 1331cb0ef41Sopenharmony_ci ->NewInstance(env()->context()) 1341cb0ef41Sopenharmony_ci .ToLocal(&obj))) { 1351cb0ef41Sopenharmony_ci return BaseObjectPtr<Packet>(); 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci return MakeBaseObject<Packet>(env(), listener_, obj, destination_, data_); 1391cb0ef41Sopenharmony_ci } 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci return FromFreeList(env(), data_, listener_, destination_); 1421cb0ef41Sopenharmony_ci} 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::FromFreeList(Environment* env, 1451cb0ef41Sopenharmony_ci std::shared_ptr<Data> data, 1461cb0ef41Sopenharmony_ci Listener* listener, 1471cb0ef41Sopenharmony_ci const SocketAddress& destination) { 1481cb0ef41Sopenharmony_ci auto& binding = BindingData::Get(env); 1491cb0ef41Sopenharmony_ci auto obj = binding.packet_freelist.back(); 1501cb0ef41Sopenharmony_ci binding.packet_freelist.pop_back(); 1511cb0ef41Sopenharmony_ci DCHECK_EQ(env, obj->env()); 1521cb0ef41Sopenharmony_ci auto packet = static_cast<Packet*>(obj.get()); 1531cb0ef41Sopenharmony_ci packet->data_ = std::move(data); 1541cb0ef41Sopenharmony_ci packet->destination_ = destination; 1551cb0ef41Sopenharmony_ci packet->listener_ = listener; 1561cb0ef41Sopenharmony_ci return BaseObjectPtr<Packet>(packet); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ciPacket::Packet(Environment* env, 1601cb0ef41Sopenharmony_ci Listener* listener, 1611cb0ef41Sopenharmony_ci Local<Object> object, 1621cb0ef41Sopenharmony_ci const SocketAddress& destination, 1631cb0ef41Sopenharmony_ci std::shared_ptr<Data> data) 1641cb0ef41Sopenharmony_ci : ReqWrap<uv_udp_send_t>(env, object, AsyncWrap::PROVIDER_QUIC_PACKET), 1651cb0ef41Sopenharmony_ci listener_(listener), 1661cb0ef41Sopenharmony_ci destination_(destination), 1671cb0ef41Sopenharmony_ci data_(std::move(data)) {} 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ciPacket::Packet(Environment* env, 1701cb0ef41Sopenharmony_ci Listener* listener, 1711cb0ef41Sopenharmony_ci Local<Object> object, 1721cb0ef41Sopenharmony_ci const SocketAddress& destination, 1731cb0ef41Sopenharmony_ci size_t length, 1741cb0ef41Sopenharmony_ci const char* diagnostic_label) 1751cb0ef41Sopenharmony_ci : Packet(env, 1761cb0ef41Sopenharmony_ci listener, 1771cb0ef41Sopenharmony_ci object, 1781cb0ef41Sopenharmony_ci destination, 1791cb0ef41Sopenharmony_ci std::make_shared<Data>(length, diagnostic_label)) {} 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ciint Packet::Send(uv_udp_t* handle, BaseObjectPtr<BaseObject> ref) { 1821cb0ef41Sopenharmony_ci if (is_sending()) return UV_EALREADY; 1831cb0ef41Sopenharmony_ci if (data_ == nullptr) return UV_EINVAL; 1841cb0ef41Sopenharmony_ci DCHECK(!is_sending()); 1851cb0ef41Sopenharmony_ci handle_ = std::move(ref); 1861cb0ef41Sopenharmony_ci uv_buf_t buf = *this; 1871cb0ef41Sopenharmony_ci return Dispatch( 1881cb0ef41Sopenharmony_ci uv_udp_send, 1891cb0ef41Sopenharmony_ci handle, 1901cb0ef41Sopenharmony_ci &buf, 1911cb0ef41Sopenharmony_ci 1, 1921cb0ef41Sopenharmony_ci destination().data(), 1931cb0ef41Sopenharmony_ci uv_udp_send_cb{[](uv_udp_send_t* req, int status) { 1941cb0ef41Sopenharmony_ci auto ptr = static_cast<Packet*>(ReqWrap<uv_udp_send_t>::from_req(req)); 1951cb0ef41Sopenharmony_ci ptr->Done(status); 1961cb0ef41Sopenharmony_ci // Do not try accessing ptr after this. We don't know if it 1971cb0ef41Sopenharmony_ci // was freelisted or destroyed. Either way, done means done. 1981cb0ef41Sopenharmony_ci }}); 1991cb0ef41Sopenharmony_ci} 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_civoid Packet::Done(int status) { 2021cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(listener_); 2031cb0ef41Sopenharmony_ci listener_->PacketDone(status); 2041cb0ef41Sopenharmony_ci handle_.reset(); 2051cb0ef41Sopenharmony_ci data_.reset(); 2061cb0ef41Sopenharmony_ci listener_ = nullptr; 2071cb0ef41Sopenharmony_ci Reset(); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci // As a performance optimization, we add this packet to a freelist 2101cb0ef41Sopenharmony_ci // rather than deleting it but only if the freelist isn't too 2111cb0ef41Sopenharmony_ci // big, we don't want to accumulate these things forever. 2121cb0ef41Sopenharmony_ci auto& binding = BindingData::Get(env()); 2131cb0ef41Sopenharmony_ci if (binding.packet_freelist.size() < kMaxFreeList) { 2141cb0ef41Sopenharmony_ci binding.packet_freelist.emplace_back(this); 2151cb0ef41Sopenharmony_ci } else { 2161cb0ef41Sopenharmony_ci delete this; 2171cb0ef41Sopenharmony_ci } 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_cistd::string Packet::ToString() const { 2211cb0ef41Sopenharmony_ci if (!data_) return "Packet (<empty>)"; 2221cb0ef41Sopenharmony_ci return "Packet (" + data_->ToString() + ")"; 2231cb0ef41Sopenharmony_ci} 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_civoid Packet::MemoryInfo(MemoryTracker* tracker) const { 2261cb0ef41Sopenharmony_ci tracker->TrackField("destination", destination_); 2271cb0ef41Sopenharmony_ci tracker->TrackField("data", data_); 2281cb0ef41Sopenharmony_ci tracker->TrackField("handle", handle_); 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::CreateRetryPacket( 2321cb0ef41Sopenharmony_ci Environment* env, 2331cb0ef41Sopenharmony_ci Listener* listener, 2341cb0ef41Sopenharmony_ci const PathDescriptor& path_descriptor, 2351cb0ef41Sopenharmony_ci const TokenSecret& token_secret) { 2361cb0ef41Sopenharmony_ci auto& random = CID::Factory::random(); 2371cb0ef41Sopenharmony_ci CID cid = random.Generate(); 2381cb0ef41Sopenharmony_ci RetryToken token(path_descriptor.version, 2391cb0ef41Sopenharmony_ci path_descriptor.remote_address, 2401cb0ef41Sopenharmony_ci cid, 2411cb0ef41Sopenharmony_ci path_descriptor.dcid, 2421cb0ef41Sopenharmony_ci token_secret); 2431cb0ef41Sopenharmony_ci if (!token) return BaseObjectPtr<Packet>(); 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci const ngtcp2_vec& vec = token; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci size_t pktlen = 2481cb0ef41Sopenharmony_ci vec.len + (2 * NGTCP2_MAX_CIDLEN) + path_descriptor.scid.length() + 8; 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci auto packet = 2511cb0ef41Sopenharmony_ci Create(env, listener, path_descriptor.remote_address, pktlen, "retry"); 2521cb0ef41Sopenharmony_ci if (!packet) return BaseObjectPtr<Packet>(); 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci ngtcp2_vec dest = *packet; 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci ssize_t nwrite = ngtcp2_crypto_write_retry(dest.base, 2571cb0ef41Sopenharmony_ci pktlen, 2581cb0ef41Sopenharmony_ci path_descriptor.version, 2591cb0ef41Sopenharmony_ci path_descriptor.scid, 2601cb0ef41Sopenharmony_ci cid, 2611cb0ef41Sopenharmony_ci path_descriptor.dcid, 2621cb0ef41Sopenharmony_ci vec.base, 2631cb0ef41Sopenharmony_ci vec.len); 2641cb0ef41Sopenharmony_ci if (nwrite <= 0) return BaseObjectPtr<Packet>(); 2651cb0ef41Sopenharmony_ci packet->Truncate(static_cast<size_t>(nwrite)); 2661cb0ef41Sopenharmony_ci return packet; 2671cb0ef41Sopenharmony_ci} 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::CreateConnectionClosePacket( 2701cb0ef41Sopenharmony_ci Environment* env, 2711cb0ef41Sopenharmony_ci Listener* listener, 2721cb0ef41Sopenharmony_ci const SocketAddress& destination, 2731cb0ef41Sopenharmony_ci ngtcp2_conn* conn, 2741cb0ef41Sopenharmony_ci const QuicError& error) { 2751cb0ef41Sopenharmony_ci auto packet = Packet::Create( 2761cb0ef41Sopenharmony_ci env, listener, destination, kDefaultMaxPacketLength, "connection close"); 2771cb0ef41Sopenharmony_ci ngtcp2_vec vec = *packet; 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci ssize_t nwrite = ngtcp2_conn_write_connection_close( 2801cb0ef41Sopenharmony_ci conn, nullptr, nullptr, vec.base, vec.len, error, uv_hrtime()); 2811cb0ef41Sopenharmony_ci if (nwrite < 0) return BaseObjectPtr<Packet>(); 2821cb0ef41Sopenharmony_ci packet->Truncate(static_cast<size_t>(nwrite)); 2831cb0ef41Sopenharmony_ci return packet; 2841cb0ef41Sopenharmony_ci} 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::CreateImmediateConnectionClosePacket( 2871cb0ef41Sopenharmony_ci Environment* env, 2881cb0ef41Sopenharmony_ci Listener* listener, 2891cb0ef41Sopenharmony_ci const SocketAddress& destination, 2901cb0ef41Sopenharmony_ci const PathDescriptor& path_descriptor, 2911cb0ef41Sopenharmony_ci const QuicError& reason) { 2921cb0ef41Sopenharmony_ci auto packet = Packet::Create(env, 2931cb0ef41Sopenharmony_ci listener, 2941cb0ef41Sopenharmony_ci path_descriptor.remote_address, 2951cb0ef41Sopenharmony_ci kDefaultMaxPacketLength, 2961cb0ef41Sopenharmony_ci "immediate connection close (endpoint)"); 2971cb0ef41Sopenharmony_ci ngtcp2_vec vec = *packet; 2981cb0ef41Sopenharmony_ci ssize_t nwrite = ngtcp2_crypto_write_connection_close( 2991cb0ef41Sopenharmony_ci vec.base, 3001cb0ef41Sopenharmony_ci vec.len, 3011cb0ef41Sopenharmony_ci path_descriptor.version, 3021cb0ef41Sopenharmony_ci path_descriptor.dcid, 3031cb0ef41Sopenharmony_ci path_descriptor.scid, 3041cb0ef41Sopenharmony_ci reason.code(), 3051cb0ef41Sopenharmony_ci // We do not bother sending a reason string here, even if 3061cb0ef41Sopenharmony_ci // there is one in the QuicError 3071cb0ef41Sopenharmony_ci nullptr, 3081cb0ef41Sopenharmony_ci 0); 3091cb0ef41Sopenharmony_ci if (nwrite <= 0) return BaseObjectPtr<Packet>(); 3101cb0ef41Sopenharmony_ci packet->Truncate(static_cast<size_t>(nwrite)); 3111cb0ef41Sopenharmony_ci return packet; 3121cb0ef41Sopenharmony_ci} 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::CreateStatelessResetPacket( 3151cb0ef41Sopenharmony_ci Environment* env, 3161cb0ef41Sopenharmony_ci Listener* listener, 3171cb0ef41Sopenharmony_ci const PathDescriptor& path_descriptor, 3181cb0ef41Sopenharmony_ci const TokenSecret& token_secret, 3191cb0ef41Sopenharmony_ci size_t source_len) { 3201cb0ef41Sopenharmony_ci // Per the QUIC spec, a stateless reset token must be strictly smaller than 3211cb0ef41Sopenharmony_ci // the packet that triggered it. This is one of the mechanisms to prevent 3221cb0ef41Sopenharmony_ci // infinite looping exchange of stateless tokens with the peer. An endpoint 3231cb0ef41Sopenharmony_ci // should never send a stateless reset token smaller than 41 bytes per the 3241cb0ef41Sopenharmony_ci // QUIC spec. The reason is that packets less than 41 bytes may allow an 3251cb0ef41Sopenharmony_ci // observer to reliably determine that it's a stateless reset. 3261cb0ef41Sopenharmony_ci size_t pktlen = source_len - 1; 3271cb0ef41Sopenharmony_ci if (pktlen < kMinStatelessResetLen) return BaseObjectPtr<Packet>(); 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci StatelessResetToken token(token_secret, path_descriptor.dcid); 3301cb0ef41Sopenharmony_ci uint8_t random[kRandlen]; 3311cb0ef41Sopenharmony_ci CHECK(crypto::CSPRNG(random, kRandlen).is_ok()); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci auto packet = Packet::Create(env, 3341cb0ef41Sopenharmony_ci listener, 3351cb0ef41Sopenharmony_ci path_descriptor.remote_address, 3361cb0ef41Sopenharmony_ci kDefaultMaxPacketLength, 3371cb0ef41Sopenharmony_ci "stateless reset"); 3381cb0ef41Sopenharmony_ci ngtcp2_vec vec = *packet; 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_ci ssize_t nwrite = ngtcp2_pkt_write_stateless_reset( 3411cb0ef41Sopenharmony_ci vec.base, pktlen, token, random, kRandlen); 3421cb0ef41Sopenharmony_ci if (nwrite <= static_cast<ssize_t>(kMinStatelessResetLen)) { 3431cb0ef41Sopenharmony_ci return BaseObjectPtr<Packet>(); 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci packet->Truncate(static_cast<size_t>(nwrite)); 3471cb0ef41Sopenharmony_ci return packet; 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ciBaseObjectPtr<Packet> Packet::CreateVersionNegotiationPacket( 3511cb0ef41Sopenharmony_ci Environment* env, 3521cb0ef41Sopenharmony_ci Listener* listener, 3531cb0ef41Sopenharmony_ci const PathDescriptor& path_descriptor) { 3541cb0ef41Sopenharmony_ci const auto generateReservedVersion = [&] { 3551cb0ef41Sopenharmony_ci socklen_t addrlen = path_descriptor.remote_address.length(); 3561cb0ef41Sopenharmony_ci uint32_t h = 0x811C9DC5u; 3571cb0ef41Sopenharmony_ci uint32_t ver = htonl(path_descriptor.version); 3581cb0ef41Sopenharmony_ci const uint8_t* p = path_descriptor.remote_address.raw(); 3591cb0ef41Sopenharmony_ci const uint8_t* ep = p + addrlen; 3601cb0ef41Sopenharmony_ci for (; p != ep; ++p) { 3611cb0ef41Sopenharmony_ci h ^= *p; 3621cb0ef41Sopenharmony_ci h *= 0x01000193u; 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci p = reinterpret_cast<const uint8_t*>(&ver); 3651cb0ef41Sopenharmony_ci ep = p + sizeof(path_descriptor.version); 3661cb0ef41Sopenharmony_ci for (; p != ep; ++p) { 3671cb0ef41Sopenharmony_ci h ^= *p; 3681cb0ef41Sopenharmony_ci h *= 0x01000193u; 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci h &= 0xf0f0f0f0u; 3711cb0ef41Sopenharmony_ci h |= NGTCP2_RESERVED_VERSION_MASK; 3721cb0ef41Sopenharmony_ci return h; 3731cb0ef41Sopenharmony_ci }; 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci uint32_t sv[3] = { 3761cb0ef41Sopenharmony_ci generateReservedVersion(), NGTCP2_PROTO_VER_MIN, NGTCP2_PROTO_VER_MAX}; 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci size_t pktlen = path_descriptor.dcid.length() + 3791cb0ef41Sopenharmony_ci path_descriptor.scid.length() + (sizeof(sv)) + 7; 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci auto packet = Packet::Create(env, 3821cb0ef41Sopenharmony_ci listener, 3831cb0ef41Sopenharmony_ci path_descriptor.remote_address, 3841cb0ef41Sopenharmony_ci kDefaultMaxPacketLength, 3851cb0ef41Sopenharmony_ci "version negotiation"); 3861cb0ef41Sopenharmony_ci ngtcp2_vec vec = *packet; 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ci ssize_t nwrite = 3891cb0ef41Sopenharmony_ci ngtcp2_pkt_write_version_negotiation(vec.base, 3901cb0ef41Sopenharmony_ci pktlen, 3911cb0ef41Sopenharmony_ci 0, 3921cb0ef41Sopenharmony_ci path_descriptor.dcid, 3931cb0ef41Sopenharmony_ci path_descriptor.dcid.length(), 3941cb0ef41Sopenharmony_ci path_descriptor.scid, 3951cb0ef41Sopenharmony_ci path_descriptor.scid.length(), 3961cb0ef41Sopenharmony_ci sv, 3971cb0ef41Sopenharmony_ci arraysize(sv)); 3981cb0ef41Sopenharmony_ci if (nwrite <= 0) return BaseObjectPtr<Packet>(); 3991cb0ef41Sopenharmony_ci packet->Truncate(static_cast<size_t>(nwrite)); 4001cb0ef41Sopenharmony_ci return packet; 4011cb0ef41Sopenharmony_ci} 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci} // namespace quic 4041cb0ef41Sopenharmony_ci} // namespace node 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ci#endif // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC 407