diff --git a/node.gyp b/node.gyp index 09f4756d0a..baf4e5393b 100644 --- a/node.gyp +++ b/node.gyp @@ -1166,6 +1166,7 @@ ], 'sources': [ 'test/cctest/test_quic_buffer.cc', + 'test/cctest/test_quic_cid.cc', 'test/cctest/test_quic_verifyhostnameidentity.cc' ] }], diff --git a/src/quic/node_quic_crypto.cc b/src/quic/node_quic_crypto.cc index d25394c5fb..f53358aaf3 100644 --- a/src/quic/node_quic_crypto.cc +++ b/src/quic/node_quic_crypto.cc @@ -106,7 +106,7 @@ void GenerateRandData(uint8_t* buf, size_t len) { bool GenerateResetToken( uint8_t* token, const uint8_t* secret, - const ngtcp2_cid* cid) { + const QuicCID& cid) { ngtcp2_crypto_ctx ctx; ngtcp2_crypto_ctx_initial(&ctx); return NGTCP2_OK(ngtcp2_crypto_hkdf_expand( @@ -123,7 +123,7 @@ bool GenerateRetryToken( uint8_t* token, size_t* tokenlen, const sockaddr* addr, - const ngtcp2_cid* ocid, + const QuicCID& ocid, const uint8_t* token_secret) { std::array plaintext; uint8_t rand_data[kTokenRandLen]; @@ -180,7 +180,7 @@ bool InvalidRetryToken( const uint8_t* token, size_t tokenlen, const sockaddr* addr, - ngtcp2_cid* ocid, + QuicCID* ocid, const uint8_t* token_secret, uint64_t verification_expiration) { @@ -245,7 +245,10 @@ bool InvalidRetryToken( if (t + verification_expiration * NGTCP2_SECONDS < now) return true; - ngtcp2_cid_init(ocid, plaintext.data() + addrlen + sizeof(uint64_t), cil); + ngtcp2_cid_init( + ocid->cid(), + plaintext.data() + addrlen + sizeof(uint64_t), + cil); return false; } @@ -786,7 +789,7 @@ bool SetCryptoSecrets( bool DeriveAndInstallInitialKey( QuicSession* session, - const ngtcp2_cid* dcid) { + const QuicCID& dcid) { uint8_t initial_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t rx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; uint8_t tx_secret[NGTCP2_CRYPTO_INITIAL_SECRETLEN]; @@ -807,7 +810,7 @@ bool DeriveAndInstallInitialKey( tx_key, tx_iv, tx_hp, - dcid, + dcid.cid(), session->crypto_context()->side())); } diff --git a/src/quic/node_quic_crypto.h b/src/quic/node_quic_crypto.h index 5207f96777..c54137e2a9 100644 --- a/src/quic/node_quic_crypto.h +++ b/src/quic/node_quic_crypto.h @@ -51,7 +51,7 @@ void InitializeTLS(QuicSession* session); // client hello. bool DeriveAndInstallInitialKey( QuicSession* session, - const ngtcp2_cid* dcid); + const QuicCID& dcid); // Generates a stateless reset token using HKDF with the // cid and token secret as input. The token secret is @@ -67,7 +67,7 @@ bool DeriveAndInstallInitialKey( bool GenerateResetToken( uint8_t* token, const uint8_t* secret, - const ngtcp2_cid* cid); + const QuicCID& cid); // The Retry Token is an encrypted token that is sent to the client // by the server as part of the path validation flow. The plaintext @@ -82,7 +82,7 @@ bool GenerateRetryToken( uint8_t* token, size_t* tokenlen, const sockaddr* addr, - const ngtcp2_cid* ocid, + const QuicCID& ocid, const uint8_t* token_secret); // Verifies the validity of a retry token. Returns true if the @@ -91,7 +91,7 @@ bool InvalidRetryToken( const uint8_t* token, size_t tokenlen, const sockaddr* addr, - ngtcp2_cid* ocid, + QuicCID* ocid, const uint8_t* token_secret, uint64_t verification_expiration); diff --git a/src/quic/node_quic_session-inl.h b/src/quic/node_quic_session-inl.h index 2d138e79dc..c997c8bcd4 100644 --- a/src/quic/node_quic_session-inl.h +++ b/src/quic/node_quic_session-inl.h @@ -23,7 +23,7 @@ namespace quic { void QuicSessionConfig::GenerateStatelessResetToken( StatelessResetTokenStrategy strategy, QuicSession* session, - ngtcp2_cid* cid) { + const QuicCID& cid) { transport_params.stateless_reset_token_present = 1; strategy( session, @@ -36,18 +36,18 @@ void QuicSessionConfig::GeneratePreferredAddressToken( ConnectionIDStrategy connection_id_strategy, StatelessResetTokenStrategy stateless_reset_strategy, QuicSession* session, - ngtcp2_cid* pscid) { + QuicCID* pscid) { - connection_id_strategy(session, pscid, kScidLen); + connection_id_strategy(session, pscid->cid(), kScidLen); stateless_reset_strategy( session, - pscid, + *pscid, transport_params.preferred_address.stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN); - transport_params.preferred_address.cid = *pscid; + transport_params.preferred_address.cid = **pscid; } -void QuicSessionConfig::set_original_connection_id(const ngtcp2_cid* ocid) { +void QuicSessionConfig::set_original_connection_id(const QuicCID& ocid) { if (ocid) { transport_params.original_connection_id = *ocid; transport_params.original_connection_id_present = 1; @@ -130,7 +130,7 @@ void QuicCryptoContext::set_tls_alert(int err) { // Derives and installs the initial keying material for a newly // created session. -bool QuicCryptoContext::SetupInitialKey(const ngtcp2_cid* dcid) { +bool QuicCryptoContext::SetupInitialKey(const QuicCID& dcid) { Debug(session(), "Deriving and installing initial keys"); return DeriveAndInstallInitialKey(session(), dcid); } @@ -176,13 +176,13 @@ Environment* QuicApplication::env() const { } // Every QUIC session will have multiple CIDs associated with it. -void QuicSession::AssociateCID(ngtcp2_cid* cid) { - socket()->AssociateCID(QuicCID(cid), QuicCID(scid_)); +void QuicSession::AssociateCID(const QuicCID& cid) { + socket()->AssociateCID(cid, scid_); } -void QuicSession::DisassociateCID(const ngtcp2_cid* cid) { +void QuicSession::DisassociateCID(const QuicCID& cid) { if (is_server()) - socket()->DisassociateCID(QuicCID(cid)); + socket()->DisassociateCID(cid); } void QuicSession::ExtendMaxStreamData(int64_t stream_id, uint64_t max_data) { @@ -284,11 +284,15 @@ void QuicSession::GetConnectionCloseInfo() { } // Removes the given connection id from the QuicSession. -void QuicSession::RemoveConnectionID(const ngtcp2_cid* cid) { +void QuicSession::RemoveConnectionID(const QuicCID& cid) { if (!is_flag_set(QUICSESSION_FLAG_DESTROYED)) DisassociateCID(cid); } +QuicCID QuicSession::dcid() const { + return QuicCID(ngtcp2_conn_get_dcid(connection())); +} + // The retransmit timer allows us to trigger retransmission // of packets in case they are considered lost. The exact amount // of time is determined internally by ngtcp2 according to the diff --git a/src/quic/node_quic_session.cc b/src/quic/node_quic_session.cc index cca626eef6..55c429b6f2 100644 --- a/src/quic/node_quic_session.cc +++ b/src/quic/node_quic_session.cc @@ -708,7 +708,7 @@ void QuicSession::RandomConnectionIDStrategy( // additional state. void QuicSession::CryptoStatelessResetTokenStrategy( QuicSession* session, - ngtcp2_cid* cid, + const QuicCID& cid, uint8_t* token, size_t tokenlen) { // For the current time, we limit stateless reset token lengths to @@ -1249,11 +1249,11 @@ QuicSession::QuicSession( QuicSocket* socket, const QuicSessionConfig& config, Local wrap, - const ngtcp2_cid* rcid, + const QuicCID& rcid, const SocketAddress& local_addr, const struct sockaddr* remote_addr, - const ngtcp2_cid* dcid, - const ngtcp2_cid* ocid, + const QuicCID& dcid, + const QuicCID& ocid, uint32_t version, const std::string& alpn, uint32_t options, @@ -1298,7 +1298,7 @@ QuicSession::QuicSession( AsyncWrap::PROVIDER_QUICCLIENTSESSION, alpn, hostname, - nullptr, // rcid only used on the server + QuicCID(), options, preferred_address_strategy) { CHECK(InitClient( @@ -1320,7 +1320,7 @@ QuicSession::QuicSession( AsyncWrap::ProviderType provider_type, const std::string& alpn, const std::string& hostname, - const ngtcp2_cid* rcid, + const QuicCID& rcid, uint32_t options, PreferredAddressStrategy preferred_address_strategy, uint64_t initial_connection_close) @@ -1335,6 +1335,7 @@ QuicSession::QuicSession( initial_connection_close_(initial_connection_close), idle_(new Timer(socket->env(), [this]() { OnIdleTimeout(); })), retransmit_(new Timer(socket->env(), [this]() { MaybeTimeout(); })), + rcid_(rcid), state_(env()->isolate(), IDX_QUIC_SESSION_STATE_COUNT) { PushListener(&default_listener_); set_connection_id_strategy(RandomConnectionIDStrategy); @@ -1342,8 +1343,6 @@ QuicSession::QuicSession( set_preferred_address_strategy(preferred_address_strategy); crypto_context_.reset(new QuicCryptoContext(this, ctx, side, options)); application_.reset(SelectApplication(this)); - if (rcid != nullptr) - rcid_ = *rcid; // TODO(@jasnell): For now, the following is a check rather than properly // handled. Before this code moves out of experimental, this should be @@ -1465,23 +1464,19 @@ void QuicSession::AckedStreamDataOffset( // here is that any CID's associated with the session have to // be associated with the new QuicSocket. void QuicSession::AddToSocket(QuicSocket* socket) { - QuicCID scid(scid_); - socket->AddSession(scid, BaseObjectPtr(this)); + socket->AddSession(scid_, BaseObjectPtr(this)); switch (crypto_context_->side()) { case NGTCP2_CRYPTO_SIDE_SERVER: { - socket->AssociateCID(QuicCID(rcid_), scid); - - if (pscid_.datalen) - socket->AssociateCID(QuicCID(pscid_), scid); - + socket->AssociateCID(rcid_, scid_); + socket->AssociateCID(pscid_, scid_); break; } case NGTCP2_CRYPTO_SIDE_CLIENT: { std::vector cids(ngtcp2_conn_get_num_scid(connection())); ngtcp2_conn_get_scid(connection(), cids.data()); for (const ngtcp2_cid& cid : cids) - socket->AssociateCID(QuicCID(&cid), scid); + socket->AssociateCID(QuicCID(&cid), scid_); break; } default: @@ -1621,13 +1616,9 @@ int QuicSession::GetNewConnectionID( DCHECK(!is_flag_set(QUICSESSION_FLAG_DESTROYED)); CHECK_NOT_NULL(connection_id_strategy_); connection_id_strategy_(this, cid, cidlen); - stateless_reset_strategy_( - this, - cid, - token, - NGTCP2_STATELESS_RESET_TOKENLEN); - - AssociateCID(cid); + QuicCID cid_(cid); + stateless_reset_strategy_(this, cid_, token, NGTCP2_STATELESS_RESET_TOKENLEN); + AssociateCID(cid_); return 0; } @@ -1737,9 +1728,7 @@ bool QuicSession::ReceiveRetry() { return false; Debug(this, "A retry packet was received. Restarting the handshake."); IncrementStat(&QuicSessionStats::retry_count); - return DeriveAndInstallInitialKey( - this, - ngtcp2_conn_get_dcid(connection())); + return DeriveAndInstallInitialKey(this, dcid()); } // When the QuicSocket receives a QUIC packet, it is forwarded on to here @@ -1868,7 +1857,7 @@ bool QuicSession::Receive( // a new connection has been initiated. The very first step to // establishing a communication channel is to setup the keys // that will be used to secure the communication. -bool QuicSession::ReceiveClientInitial(const ngtcp2_cid* dcid) { +bool QuicSession::ReceiveClientInitial(const QuicCID& dcid) { if (UNLIKELY(is_flag_set(QUICSESSION_FLAG_DESTROYED))) return false; Debug(this, "Receiving client initial parameters."); @@ -1908,8 +1897,8 @@ bool QuicSession::ReceivePacket( if (err == NGTCP2_ERR_RETRY && is_server()) { socket()->SendRetry( negotiated_version(), - QuicCID(scid()), - QuicCID(rcid()), + scid_, + rcid_, local_address_, remote_address_.data()); ImmediateClose(); @@ -1967,10 +1956,8 @@ bool QuicSession::ReceiveStreamData( // the session object will be destroyed automatically. void QuicSession::RemoveFromSocket() { if (is_server()) { - socket_->DisassociateCID(QuicCID(rcid_)); - - if (pscid_.datalen > 0) - socket_->DisassociateCID(QuicCID(pscid_)); + socket_->DisassociateCID(rcid_); + socket_->DisassociateCID(pscid_); } std::vector cids(ngtcp2_conn_get_num_scid(connection())); @@ -1990,7 +1977,7 @@ void QuicSession::RemoveFromSocket() { } Debug(this, "Removed from the QuicSocket."); - socket_->RemoveSession(QuicCID(scid_), remote_address_); + socket_->RemoveSession(scid_, remote_address_); socket_.reset(); } @@ -2570,11 +2557,11 @@ QuicSession::InitialPacketResult QuicSession::Accept( BaseObjectPtr QuicSession::CreateServer( QuicSocket* socket, const QuicSessionConfig& config, - const ngtcp2_cid* rcid, + const QuicCID& rcid, const SocketAddress& local_addr, const struct sockaddr* remote_addr, - const ngtcp2_cid* dcid, - const ngtcp2_cid* ocid, + const QuicCID& dcid, + const QuicCID& ocid, uint32_t version, const std::string& alpn, uint32_t options, @@ -2611,8 +2598,8 @@ void QuicSession::InitServer( QuicSessionConfig config, const SocketAddress& local_addr, const struct sockaddr* remote_addr, - const ngtcp2_cid* dcid, - const ngtcp2_cid* ocid, + const QuicCID& dcid, + const QuicCID& ocid, uint32_t version, QlogMode qlog) { @@ -2627,12 +2614,12 @@ void QuicSession::InitServer( config.set_original_connection_id(ocid); - connection_id_strategy_(this, &scid_, kScidLen); + connection_id_strategy_(this, scid_.cid(), kScidLen); config.GenerateStatelessResetToken( stateless_reset_strategy_, this, - &scid_); + scid_); config.GeneratePreferredAddressToken( connection_id_strategy_, @@ -2649,8 +2636,8 @@ void QuicSession::InitServer( CHECK_EQ( ngtcp2_conn_server_new( &conn, - dcid, - &scid_, + dcid.cid(), + scid_.cid(), &path, version, &callbacks[crypto_context_->side()], @@ -2796,7 +2783,7 @@ bool QuicSession::InitClient( ExtendMaxStreamsBidi(DEFAULT_MAX_STREAMS_BIDI); ExtendMaxStreamsUni(DEFAULT_MAX_STREAMS_UNI); - connection_id_strategy_(this, &scid_, NGTCP2_MAX_CIDLEN); + connection_id_strategy_(this, scid_.cid(), NGTCP2_MAX_CIDLEN); ngtcp2_cid dcid; if (dcid_value->IsArrayBufferView()) { @@ -2819,7 +2806,7 @@ bool QuicSession::InitClient( ngtcp2_conn_client_new( &conn, &dcid, - &scid_, + scid_.cid(), &path, NGTCP2_PROTO_VER, &callbacks[crypto_context_->side()], @@ -2832,8 +2819,7 @@ bool QuicSession::InitClient( InitializeTLS(this); - CHECK(DeriveAndInstallInitialKey( - this, ngtcp2_conn_get_dcid(connection()))); + CHECK(DeriveAndInstallInitialKey(this, this->dcid())); // Remote Transport Params if (early_transport_params->IsArrayBufferView()) { @@ -2886,7 +2872,7 @@ int QuicSession::OnReceiveClientInitial( void* user_data) { QuicSession* session = static_cast(user_data); QuicSession::Ngtcp2CallbackScope callback_scope(session); - if (!session->ReceiveClientInitial(dcid)) { + if (!session->ReceiveClientInitial(QuicCID(dcid))) { Debug(session, "Receiving initial client handshake failed"); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -3233,7 +3219,7 @@ int QuicSession::OnRemoveConnectionID( const ngtcp2_cid* cid, void* user_data) { QuicSession* session = static_cast(user_data); - session->RemoveConnectionID(cid); + session->RemoveConnectionID(QuicCID(cid)); return 0; } diff --git a/src/quic/node_quic_session.h b/src/quic/node_quic_session.h index 47925f0c49..96aabb03ff 100644 --- a/src/quic/node_quic_session.h +++ b/src/quic/node_quic_session.h @@ -48,7 +48,7 @@ typedef void(*ConnectionIDStrategy)( typedef void(*StatelessResetTokenStrategy)( QuicSession* session, - ngtcp2_cid* cid, + const QuicCID& cid, uint8_t* token, size_t tokenlen); @@ -87,20 +87,20 @@ class QuicSessionConfig : public ngtcp2_settings { void Set(Environment* env, const struct sockaddr* preferred_addr = nullptr); - inline void set_original_connection_id(const ngtcp2_cid* ocid); + inline void set_original_connection_id(const QuicCID& ocid); // Generates the stateless reset token for the settings_ inline void GenerateStatelessResetToken( StatelessResetTokenStrategy strategy, QuicSession* session, - ngtcp2_cid* cid); + const QuicCID& cid); // If the preferred address is set, generates the associated tokens inline void GeneratePreferredAddressToken( ConnectionIDStrategy connection_id_strategy, StatelessResetTokenStrategy stateless_reset_strategy, QuicSession* session, - ngtcp2_cid* pscid); + QuicCID* pscid); inline void set_qlog(const ngtcp2_qlog_settings& qlog); }; @@ -399,7 +399,7 @@ class QuicCryptoContext : public MemoryRetainer { inline void set_tls_alert(int err); - inline bool SetupInitialKey(const ngtcp2_cid* dcid); + inline bool SetupInitialKey(const QuicCID& dcid); ngtcp2_crypto_side side() const { return side_; } @@ -627,11 +627,11 @@ class QuicSession : public AsyncWrap, static BaseObjectPtr CreateServer( QuicSocket* socket, const QuicSessionConfig& config, - const ngtcp2_cid* rcid, + const QuicCID& rcid, const SocketAddress& local_addr, const struct sockaddr* remote_addr, - const ngtcp2_cid* dcid, - const ngtcp2_cid* ocid, + const QuicCID& dcid, + const QuicCID& ocid, uint32_t version, const std::string& alpn = NGTCP2_ALPN_H3, uint32_t options = 0, @@ -675,7 +675,7 @@ class QuicSession : public AsyncWrap, // is always required. const std::string& alpn, const std::string& hostname, - const ngtcp2_cid* rcid, + const QuicCID& rcid, uint32_t options = 0, PreferredAddressStrategy preferred_address_strategy = IgnorePreferredAddressStrategy, @@ -686,11 +686,11 @@ class QuicSession : public AsyncWrap, QuicSocket* socket, const QuicSessionConfig& config, v8::Local wrap, - const ngtcp2_cid* rcid, + const QuicCID& rcid, const SocketAddress& local_addr, const struct sockaddr* remote_addr, - const ngtcp2_cid* dcid, - const ngtcp2_cid* ocid, + const QuicCID& dcid, + const QuicCID& ocid, uint32_t version, const std::string& alpn, uint32_t options, @@ -716,6 +716,7 @@ class QuicSession : public AsyncWrap, ~QuicSession() override; std::string diagnostic_name() const override; + inline QuicCID dcid() const; QuicApplication* application() const { return application_.get(); } @@ -797,11 +798,6 @@ class QuicSession : public AsyncWrap, // a single address is one of the benefits of QUIC. const SocketAddress& remote_address() const { return remote_address_; } - const ngtcp2_cid* scid() const { return &scid_; } - - // Only used with server sessions - const ngtcp2_cid* rcid() const { return &rcid_; } - inline QuicSocket* socket() const; ngtcp2_conn* connection() const { return connection_.get(); } @@ -1066,7 +1062,7 @@ class QuicSession : public AsyncWrap, static void CryptoStatelessResetTokenStrategy( QuicSession* session, - ngtcp2_cid* cid, + const QuicCID& cid, uint8_t* token, size_t tokenlen); @@ -1075,8 +1071,8 @@ class QuicSession : public AsyncWrap, QuicSessionConfig config, const SocketAddress& local_addr, const struct sockaddr* remote_addr, - const ngtcp2_cid* dcid, - const ngtcp2_cid* ocid, + const QuicCID& dcid, + const QuicCID& ocid, uint32_t version, QlogMode qlog); @@ -1095,9 +1091,9 @@ class QuicSession : public AsyncWrap, int64_t stream_id, uint64_t offset, size_t datalen); - inline void AssociateCID(ngtcp2_cid* cid); - inline void DisassociateCID(const ngtcp2_cid* cid); + inline void AssociateCID(const QuicCID& cid); + inline void DisassociateCID(const QuicCID& cid); inline void ExtendMaxStreamData(int64_t stream_id, uint64_t max_data); void ExtendMaxStreams(bool bidi, uint64_t max_streams); inline void ExtendMaxStreamsUni(uint64_t max_streams); @@ -1110,10 +1106,10 @@ class QuicSession : public AsyncWrap, void PathValidation( const ngtcp2_path* path, ngtcp2_path_validation_result res); - bool ReceiveClientInitial(const ngtcp2_cid* dcid); + bool ReceiveClientInitial(const QuicCID& dcid); bool ReceivePacket(ngtcp2_path* path, const uint8_t* data, ssize_t nread); bool ReceiveRetry(); - inline void RemoveConnectionID(const ngtcp2_cid* cid); + inline void RemoveConnectionID(const QuicCID& cid); void ScheduleRetransmit(); bool SendPacket(std::unique_ptr packet); inline void set_local_address(const ngtcp2_addr* addr); @@ -1410,9 +1406,9 @@ class QuicSession : public AsyncWrap, TimerPointer idle_; TimerPointer retransmit_; - ngtcp2_cid scid_; - ngtcp2_cid rcid_; - ngtcp2_cid pscid_{}; + QuicCID scid_; + QuicCID rcid_; + QuicCID pscid_; ngtcp2_transport_params transport_params_; std::unique_ptr conn_closebuf_; diff --git a/src/quic/node_quic_socket-inl.h b/src/quic/node_quic_socket-inl.h index 9d073ccf0a..59d5f571ac 100644 --- a/src/quic/node_quic_socket-inl.h +++ b/src/quic/node_quic_socket-inl.h @@ -60,12 +60,15 @@ void QuicEndpoint::WaitForPendingCallbacks() { void QuicSocket::AssociateCID( const QuicCID& cid, const QuicCID& scid) { - dcid_to_scid_[cid] = scid; + if (cid && scid) + dcid_to_scid_[cid] = scid; } void QuicSocket::DisassociateCID(const QuicCID& cid) { - Debug(this, "Removing association for cid %s", cid.ToHex().c_str()); - dcid_to_scid_.erase(cid); + if (cid) { + Debug(this, "Removing association for cid %s", cid.ToHex().c_str()); + dcid_to_scid_.erase(cid); + } } void QuicSocket::AssociateStatelessResetToken( diff --git a/src/quic/node_quic_socket.cc b/src/quic/node_quic_socket.cc index a82c037786..e7465fc00a 100644 --- a/src/quic/node_quic_socket.cc +++ b/src/quic/node_quic_socket.cc @@ -658,7 +658,7 @@ bool QuicSocket::SendStatelessReset( if (pktlen < kMinStatelessResetLen) return false; - GenerateResetToken(token, reset_token_secret_, cid.cid()); + GenerateResetToken(token, reset_token_secret_, cid); EntropySource(random, kRandlen); auto packet = QuicPacket::Create("stateless reset", pktlen); @@ -707,14 +707,8 @@ bool QuicSocket::SendRetry( // Retry tokens are generated cryptographically. They // aren't super expensive but they are still not zero-cost. - if (!GenerateRetryToken( - token, - &tokenlen, - remote_addr, - dcid.cid(), - token_secret_)) { + if (!GenerateRetryToken(token, &tokenlen, remote_addr, dcid, token_secret_)) return false; - } ngtcp2_pkt_hd hd; hd.version = version; @@ -724,7 +718,7 @@ bool QuicSocket::SendRetry( hd.token = nullptr; hd.tokenlen = 0; hd.len = 0; - hd.dcid = *scid.cid(); + hd.dcid = *scid; hd.scid.datalen = kScidLen; EntropySource(hd.scid.data, kScidLen); @@ -764,8 +758,7 @@ BaseObjectPtr QuicSocket::AcceptInitialPacket( HandleScope handle_scope(env()->isolate()); Context::Scope context_scope(env()->context()); ngtcp2_pkt_hd hd; - ngtcp2_cid ocid; - ngtcp2_cid* ocid_ptr = nullptr; + QuicCID ocid; uint64_t initial_connection_close = NGTCP2_NO_ERROR; // If the QuicSocket is not listening, the paket will be ignored. @@ -850,7 +843,6 @@ BaseObjectPtr QuicSocket::AcceptInitialPacket( } Debug(this, "A valid retry token was found. Continuing."); set_validated_address(remote_addr); - ocid_ptr = &ocid; } else { Debug(this, "Skipping validation for recently validated address."); } @@ -860,11 +852,11 @@ BaseObjectPtr QuicSocket::AcceptInitialPacket( QuicSession::CreateServer( this, server_session_config_, - dcid.cid(), + dcid, local_addr, remote_addr, - scid.cid(), - ocid_ptr, + scid, + ocid, version, server_alpn_, server_options_, diff --git a/src/quic/node_quic_util.h b/src/quic/node_quic_util.h index 8c9abb9825..83a0ab1070 100644 --- a/src/quic/node_quic_util.h +++ b/src/quic/node_quic_util.h @@ -223,10 +223,15 @@ class QuicCID : public MemoryRetainer { const ngtcp2_cid& operator*() const { return cid_; } const ngtcp2_cid* operator->() const { return &cid_; } const ngtcp2_cid* cid() const { return &cid_; } + ngtcp2_cid* cid() { return &cid_; } + operator bool() const { return cid_.datalen > 0; } const uint8_t* data() const { return cid_.data; } size_t length() const { return cid_.datalen; } + unsigned char* data() { return reinterpret_cast(cid_.data); } + void set_length(size_t length) { cid_.datalen = length; } + SET_NO_MEMORY_INFO() SET_MEMORY_INFO_NAME(QuicCID) SET_SELF_SIZE(QuicCID) diff --git a/test/cctest/test_quic_cid.cc b/test/cctest/test_quic_cid.cc new file mode 100644 index 0000000000..37e9e00e11 --- /dev/null +++ b/test/cctest/test_quic_cid.cc @@ -0,0 +1,31 @@ +#include "quic/node_quic_util-inl.h" +#include "node_sockaddr-inl.h" +#include "util-inl.h" +#include "ngtcp2/ngtcp2.h" +#include "gtest/gtest.h" +#include +#include + +using node::quic::QuicCID; + +TEST(QuicCID, Simple) { + ngtcp2_cid cid1; + ngtcp2_cid cid2; + uint8_t data1[3] = { 'a', 'b', 'c' }; + uint8_t data2[4] = { 1, 2, 3, 4 }; + ngtcp2_cid_init(&cid1, data1, 3); + ngtcp2_cid_init(&cid2, data2, 4); + + QuicCID qcid1(cid1); + CHECK(qcid1); + CHECK_EQ(qcid1.length(), 3); + CHECK_EQ(qcid1.ToHex(), "616263"); + + QuicCID qcid2(cid2); + qcid1 = qcid2; + CHECK_EQ(qcid1.ToHex(), qcid2.ToHex()); + + qcid1.set_length(5); + memset(qcid1.data(), 1, 5); + CHECK_EQ(qcid1.ToHex(), "0101010101"); +}