@@ -23,6 +23,7 @@ import { quiche } from './native';
2323import * as events from './events' ;
2424import * as utils from './utils' ;
2525import * as errors from './errors' ;
26+ import { never } from './utils' ;
2627
2728/**
2829 * Think of this as equivalent to `net.Socket`.
@@ -193,6 +194,12 @@ class QUICConnection extends EventTarget {
193194 public readonly lockbox = new LockBox < RWLockWriter > ( ) ;
194195 public readonly lockCode = 'Lock' ; // TODO: more unique code
195196
197+ protected customVerified = false ;
198+ protected shortReceived = false ;
199+ protected shortSent = false ;
200+ protected secured = false ;
201+ protected count = 0 ;
202+
196203 public constructor ( {
197204 type,
198205 scid,
@@ -353,10 +360,8 @@ class QUICConnection extends EventTarget {
353360 this . socket . connectionMap . set ( this . connectionId , this ) ;
354361 // Waits for the first short packet after establishment
355362 // This ensures that TLS has been established and verified on both sides
356- console . log ( 'sending' ) ;
357363 await this . send ( ) ;
358- console . log ( 'waiting secured' ) ;
359- // await this.secureEstablishedP;
364+ await this . secureEstablishedP ;
360365 this . logger . warn ( 'secured' ) ;
361366 // After this is done
362367 // We need to established the keep alive interval time
@@ -447,6 +452,49 @@ class QUICConnection extends EventTarget {
447452 // But during `start` we are just waiting
448453 this . socket . connectionMap . delete ( this . connectionId ) ;
449454
455+ // Emit error if peer error
456+ const peerError = this . conn . peerError ( ) ;
457+ if ( peerError != null ) {
458+ const message = `Connection errored out with peerError ${ Buffer . from (
459+ peerError . reason ,
460+ ) . toString ( ) } (${ peerError . errorCode } )`;
461+ this . logger . info ( message ) ;
462+ this . dispatchEvent (
463+ new events . QUICConnectionErrorEvent ( {
464+ detail : new errors . ErrorQUICConnectionInternal (
465+ message ,
466+ {
467+ data : {
468+ type : 'local' ,
469+ ...peerError ,
470+ }
471+ } ,
472+ ) ,
473+ } ) ,
474+ ) ;
475+ }
476+
477+ const localError = this . conn . localError ( ) ;
478+ if ( localError != null ) {
479+ const message = `connection failed with localError ${ Buffer . from (
480+ localError . reason ,
481+ ) . toString ( ) } (${ localError . errorCode } )`;
482+ this . logger . info ( message ) ;
483+ this . dispatchEvent (
484+ new events . QUICConnectionErrorEvent ( {
485+ detail : new errors . ErrorQUICConnectionInternal (
486+ message ,
487+ {
488+ data : {
489+ type : 'local' ,
490+ ...localError ,
491+ }
492+ }
493+ ) ,
494+ } ) ,
495+ ) ;
496+ }
497+
450498 this . dispatchEvent ( new events . QUICConnectionStopEvent ( ) ) ;
451499 this . logger . info ( `Stopped ${ this . constructor . name } ` ) ;
452500 }
@@ -518,39 +566,37 @@ class QUICConnection extends EventTarget {
518566 this . lastErrorMessage = e . message ;
519567 }
520568
569+ // Checking if the packet was a short frame.
570+ // Short indicates that the peer has completed TLS verification
571+ if ( ! this . shortReceived ) {
572+ const header = quiche . Header . fromSlice ( data , quiche . MAX_CONN_ID_LEN ) ;
573+ // if short frame
574+ if ( header . ty === 5 ) {
575+ this . shortReceived = true ;
576+ this . conn . sendAckEliciting ( ) ;
577+ }
578+ }
579+
580+ if (
581+ ! this . secured &&
582+ this . shortReceived &&
583+ this . shortReceived &&
584+ ! this . conn . isDraining ( )
585+ ) {
586+ if ( this . count >= 1 ) {
587+ this . secured = true ;
588+ this . resolveSecureEstablishedP ( ) ;
589+ // this.dispatchEvent(new events.QUICConnectionRemoteSecureEvent()); TODO
590+ }
591+ this . count += 1 ;
592+ }
593+
521594 // We don't actually "fail"
522595 // the closedP until we proceed
523596 // But note that if there's an error
524597
525598 if ( this . conn . isEstablished ( ) ) {
526599 this . resolveEstablishedP ( ) ;
527-
528- if ( this . type === 'server' ) {
529- // For server connections, if we are established
530- // we are secure established
531- this . resolveSecureEstablishedP ( ) ;
532- } else if ( this . type === 'client' ) {
533- // We need a hueristic to indicate whether we are securely established
534- // If we are already established
535- // AND IF, we are getting a packet after establishment
536- // And we didn't result in an error
537- // Neither draining, nor closed, nor timed out
538- // For server connections
539- // If we are already established, then we are secure established
540- // To know if the server is also established
541- // We need to know the NEXT recv after we are already established
542- // So we received something, and that allows us to be established
543- // UPON the next recv
544- // We need to ensure:
545- // 1. No errors
546- // 2. Not draining
547- // 3. No
548- // YES the main thing is that there is no errors
549- // I think that's the KEY
550- // But we must only switch
551- // If were "already" established
552- // That this wasn't the first time we were established
553- }
554600 }
555601
556602 // We also need to know whether this is our first short frame
@@ -586,7 +632,7 @@ class QUICConnection extends EventTarget {
586632 }
587633 readIds . push ( quicStream . streamId ) ;
588634 quicStream . read ( ) ;
589- // QuicStream.dispatchEvent(new events.QUICStreamReadableEvent ()); // TODO: remove?
635+ // QuicStream.dispatchEvent(new events.QUICStreamReadablaeEvent ()); // TODO: remove?
590636 }
591637 if ( readIds . length > 0 ) {
592638 this . logger . info ( `processed reads for ${ readIds } ` ) ;
@@ -691,6 +737,50 @@ class QUICConnection extends EventTarget {
691737 ) ;
692738 this . logger . debug ( `sent ${ sendLength } bytes` ) ;
693739 }
740+ // Handling custom TLS verification, this must be done after the following conditions.
741+ // 1. Connection established.
742+ // 2. Certs available.
743+ // 3. Sent after connection has established.
744+ if (
745+ ! this . customVerified &&
746+ this . conn . isEstablished ( ) &&
747+ this . conn . peerCertChain ( ) != null
748+ ) {
749+ this . customVerified = true ;
750+ const peerCerts = this . conn . peerCertChain ( ) ;
751+ if ( peerCerts == null ) never ( ) ;
752+ const peerCertsPem = peerCerts . map ( ( c ) =>
753+ utils . certificateDERToPEM ( c ) ,
754+ ) ;
755+ // Dispatching certs available event
756+ // this.dispatchEvent(new events.QUICConnectionRemoteCertEvent()); TODO
757+ try {
758+ // if (this.verifyCallback != null) this.verifyCallback(peerCertsPem); TODO
759+ this . conn . sendAckEliciting ( ) ;
760+ } catch ( e ) {
761+ // Force the connection to end.
762+ // Error 304 indicates cert chain failed verification.
763+ // Error 372 indicates cert chain was missing.
764+ this . conn . close (
765+ false ,
766+ 304 ,
767+ Buffer . from ( `Custom TLSFail: ${ e . message } ` ) ,
768+ ) ;
769+ }
770+ }
771+
772+ // Check the header type
773+ if ( ! this . shortSent ) {
774+ const header = quiche . Header . fromSlice (
775+ sendBuffer ,
776+ quiche . MAX_CONN_ID_LEN ,
777+ ) ;
778+ // If short frame
779+ if ( header . ty === 5 ) {
780+ // Short was sent, locally secured
781+ this . shortSent = true ;
782+ }
783+ }
694784 } catch ( e ) {
695785 // If called `stop` due to an error here
696786 // we MUST not call `this.send` again
0 commit comments