@@ -673,10 +673,12 @@ setCallbacks({
673673 * @param {number } errorType
674674 * @param {number } code
675675 * @param {string } [reason]
676+ * @param {string } [errorName] Decoded TLS alert name when `code` is a
677+ * CRYPTO_ERROR; otherwise undefined.
676678 */
677- onSessionClose ( errorType , code , reason ) {
678- debug ( 'session close callback' , errorType , code , reason ) ;
679- this [ kOwner ] [ kFinishClose ] ( errorType , code , reason ) ;
679+ onSessionClose ( errorType , code , reason , errorName ) {
680+ debug ( 'session close callback' , errorType , code , reason , errorName ) ;
681+ this [ kOwner ] [ kFinishClose ] ( errorType , code , reason , errorName ) ;
680682 } ,
681683
682684 /**
@@ -968,21 +970,50 @@ class QuicError extends Error {
968970 }
969971}
970972
971- // Converts a raw QuicError array [type, code, reason] from C++ into a
972- // proper Node.js Error object.
973+ // Build the human-readable message for an ERR_QUIC_TRANSPORT_ERROR or
974+ // ERR_QUIC_APPLICATION_ERROR. `errorName` is the symbolic name for
975+ // the wire code when known: either the OpenSSL-decoded TLS alert
976+ // (CRYPTO_ERROR; 0x100..0x1ff) or one of the named transport codes
977+ // from RFC 9000 (e.g. PROTOCOL_VIOLATION). Otherwise undefined.
978+ // `reason` is the peer-supplied UTF-8 reason string from the
979+ // CONNECTION_CLOSE / RESET_STREAM frame, often empty.
980+ function quicErrorMessage ( prefix , errorCode , reason , errorName ) {
981+ let msg = `${ prefix } ` ;
982+ msg += errorName ? `${ errorName } (${ errorCode } )` : `${ errorCode } ` ;
983+ if ( reason ) msg += `: ${ reason } ` ;
984+ return msg ;
985+ }
986+
987+ function makeQuicError ( ErrorClass , prefix , type , errorCode , reason , errorName ) {
988+ const err = new ErrorClass (
989+ quicErrorMessage ( prefix , errorCode , reason , errorName ) ) ;
990+ err . errorCode = errorCode ;
991+ err . type = type ;
992+ if ( reason ) err . reason = reason ;
993+ if ( errorName ) err . errorName = errorName ;
994+ return err ;
995+ }
996+
973997function convertQuicError ( error ) {
974998 const type = error [ 0 ] ;
975999 const code = error [ 1 ] ;
9761000 const reason = error [ 2 ] ;
1001+ const errorName = error [ 3 ] ;
9771002 switch ( type ) {
9781003 case 'transport' :
979- return new ERR_QUIC_TRANSPORT_ERROR ( code , reason ) ;
1004+ return makeQuicError ( ERR_QUIC_TRANSPORT_ERROR ,
1005+ 'QUIC transport error' ,
1006+ 'transport' , code , reason , errorName ) ;
9801007 case 'application' :
981- return new ERR_QUIC_APPLICATION_ERROR ( code , reason ) ;
1008+ return makeQuicError ( ERR_QUIC_APPLICATION_ERROR ,
1009+ 'QUIC application error' ,
1010+ 'application' , code , reason , errorName ) ;
9821011 case 'version_negotiation' :
9831012 return new ERR_QUIC_VERSION_NEGOTIATION_ERROR ( ) ;
9841013 default :
985- return new ERR_QUIC_TRANSPORT_ERROR ( code , reason ) ;
1014+ return makeQuicError ( ERR_QUIC_TRANSPORT_ERROR ,
1015+ 'QUIC transport error' ,
1016+ 'transport' , code , reason , errorName ) ;
9861017 }
9871018}
9881019
@@ -3463,7 +3494,7 @@ class QuicSession {
34633494 * @param {number } code
34643495 * @param {string } [reason]
34653496 */
3466- [ kFinishClose ] ( errorType , code , reason ) {
3497+ [ kFinishClose ] ( errorType , code , reason , errorName ) {
34673498 // If code is zero, then we closed without an error. Yay! We can destroy
34683499 // safely without specifying an error.
34693500 if ( code === 0n ) {
@@ -3472,7 +3503,8 @@ class QuicSession {
34723503 return ;
34733504 }
34743505
3475- debug ( 'finishing closing the session with an error' , errorType , code , reason ) ;
3506+ debug ( 'finishing closing the session with an error' ,
3507+ errorType , code , reason , errorName ) ;
34763508
34773509 // If the local side initiated this close with an error code (via
34783510 // close({ code })), this is an intentional shutdown; not an error.
@@ -3499,10 +3531,14 @@ class QuicSession {
34993531 // session would leak with `closed` hanging forever.
35003532 switch ( errorType ) {
35013533 case 0 : /* Transport Error */
3502- this . destroy ( new ERR_QUIC_TRANSPORT_ERROR ( code , reason ) ) ;
3534+ this . destroy ( makeQuicError ( ERR_QUIC_TRANSPORT_ERROR ,
3535+ 'QUIC transport error' ,
3536+ 'transport' , code , reason , errorName ) ) ;
35033537 break ;
35043538 case 1 : /* Application Error */
3505- this . destroy ( new ERR_QUIC_APPLICATION_ERROR ( code , reason ) ) ;
3539+ this . destroy ( makeQuicError ( ERR_QUIC_APPLICATION_ERROR ,
3540+ 'QUIC application error' ,
3541+ 'application' , code , reason , errorName ) ) ;
35063542 break ;
35073543 case 2 : /* Version Negotiation Error */
35083544 this . destroy ( new ERR_QUIC_VERSION_NEGOTIATION_ERROR ( ) ) ;
@@ -3511,7 +3547,9 @@ class QuicSession {
35113547 this . destroy ( ) ;
35123548 break ;
35133549 default :
3514- this . destroy ( new ERR_QUIC_TRANSPORT_ERROR ( code , reason ) ) ;
3550+ this . destroy ( makeQuicError ( ERR_QUIC_TRANSPORT_ERROR ,
3551+ 'QUIC transport error' ,
3552+ 'transport' , code , reason , errorName ) ) ;
35153553 break ;
35163554 }
35173555 }
0 commit comments