diff --git a/src/node_quic_session.cc b/src/node_quic_session.cc index 6fef1bad66..9fe34de2da 100644 --- a/src/node_quic_session.cc +++ b/src/node_quic_session.cc @@ -1865,6 +1865,7 @@ bool QuicSession::Receive( // If processing the packet puts us into draining period, there's // absolutely nothing left for us to do except silently close // and destroy this QuicSession. + GetConnectionCloseInfo(); SilentClose(); return true; } else { @@ -1890,6 +1891,14 @@ bool QuicSession::ReceiveClientInitial(const ngtcp2_cid* dcid) { initial_connection_close_ == NGTCP2_NO_ERROR; } +// Captures the error code and family information from a received +// connection close frame. +void QuicSession::GetConnectionCloseInfo() { + ngtcp2_connection_close_error_code close_code; + ngtcp2_conn_get_connection_close_error_code(Connection(), &close_code); + SetLastError(QuicError(close_code)); +} + bool QuicSession::ReceivePacket( ngtcp2_path* path, const uint8_t* data, diff --git a/src/node_quic_session.h b/src/node_quic_session.h index 7243b51d54..2b39c3b1db 100644 --- a/src/node_quic_session.h +++ b/src/node_quic_session.h @@ -938,6 +938,7 @@ class QuicSession : public AsyncWrap, void ExtendMaxStreamsRemoteUni(uint64_t max_streams); void ExtendMaxStreamsRemoteBidi(uint64_t max_streams); int GetNewConnectionID(ngtcp2_cid* cid, uint8_t* token, size_t cidlen); + void GetConnectionCloseInfo(); void HandshakeCompleted(); void PathValidation( const ngtcp2_path* path, diff --git a/src/node_quic_util-inl.h b/src/node_quic_util-inl.h index 4a5fdcef97..ccec61b047 100644 --- a/src/node_quic_util-inl.h +++ b/src/node_quic_util-inl.h @@ -185,6 +185,21 @@ QuicError::QuicError( } } +QuicError::QuicError(ngtcp2_connection_close_error_code ccec) : + code(ccec.error_code), family(QUIC_ERROR_SESSION) { + switch (ccec.type) { + case NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_APPLICATION: + family = QUIC_ERROR_APPLICATION; + break; + case NGTCP2_CONNECTION_CLOSE_ERROR_CODE_TYPE_TRANSPORT: + if (code & NGTCP2_CRYPTO_ERROR) + family = QUIC_ERROR_CRYPTO; + break; + default: + UNREACHABLE(); + } +} + QuicError::QuicError( Environment* env, v8::Local codeArg, diff --git a/src/node_quic_util.h b/src/node_quic_util.h index 5bcbd964a1..a0585f56c5 100644 --- a/src/node_quic_util.h +++ b/src/node_quic_util.h @@ -85,6 +85,7 @@ struct QuicError { inline QuicError( int32_t family_ = QUIC_ERROR_SESSION, uint64_t code_ = NGTCP2_NO_ERROR); + inline QuicError(ngtcp2_connection_close_error_code code); inline QuicError( Environment* env, v8::Local codeArg,