@@ -2,28 +2,33 @@ import type { PromiseCancellable } from '@matrixai/async-cancellable';
22import type { ContextTimed } from '@matrixai/contexts' ;
33import type QUICSocket from './QUICSocket' ;
44import type QUICConnectionId from './QUICConnectionId' ;
5- import type { Host , Port , RemoteInfo , StreamId } from './types' ;
5+ import type {
6+ Host ,
7+ Port ,
8+ QUICConfig ,
9+ RemoteInfo ,
10+ StreamCodeToReason ,
11+ StreamId ,
12+ StreamReasonToCode ,
13+ } from './types' ;
614import type { Connection , ConnectionErrorCode , SendInfo } from './native/types' ;
7- import type { StreamCodeToReason , StreamReasonToCode } from './types' ;
8- import type { QUICConfig } from './types' ;
9- import { Monitor , RWLockWriter } from '@matrixai/async-locks' ;
15+ import { Lock , LockBox , Monitor , RWLockWriter } from '@matrixai/async-locks' ;
1016import {
11- StartStop ,
1217 ready ,
13- status ,
1418 running ,
19+ StartStop ,
20+ status ,
1521} from '@matrixai/async-init/dist/StartStop' ;
1622import Logger from '@matrixai/logger' ;
17- import { Lock , LockBox } from '@matrixai/async-locks' ;
1823import { Timer } from '@matrixai/timer' ;
1924import { context , timedCancellable } from '@matrixai/contexts/dist/decorators' ;
2025import { buildQuicheConfig } from './config' ;
2126import QUICStream from './QUICStream' ;
2227import { quiche } from './native' ;
2328import * as events from './events' ;
2429import * as utils from './utils' ;
25- import * as errors from './errors' ;
2630import { never } from './utils' ;
31+ import * as errors from './errors' ;
2732
2833// FIXME
2934type VerifyCallback = ( certs : Array < string > ) => void ;
@@ -369,7 +374,45 @@ class QUICConnection extends EventTarget {
369374 // Waits for the first short packet after establishment
370375 // This ensures that TLS has been established and verified on both sides
371376 await this . send ( ) ;
372- await this . secureEstablishedP ;
377+ await this . secureEstablishedP . catch ( ( e ) => {
378+ this . socket . connectionMap . delete ( this . connectionId ) ;
379+
380+ if ( this . conn . isTimedOut ( ) ) {
381+ // We don't dispatch an event here, it was already done in the timeout.
382+ throw new errors . ErrorQUICConnectionStartTimeOut ( ) ;
383+ }
384+
385+ // Emit error if local error
386+ const localError = this . conn . localError ( ) ;
387+ if ( localError != null ) {
388+ const message = `connection start failed with localError ${ Buffer . from (
389+ localError . reason ,
390+ ) . toString ( ) } (${ localError . errorCode } )`;
391+ this . logger . info ( message ) ;
392+ throw new errors . ErrorQUICConnectionInternal ( message , {
393+ data : {
394+ type : 'local' ,
395+ ...localError ,
396+ } ,
397+ } ) ;
398+ }
399+ // Emit error if peer error
400+ const peerError = this . conn . peerError ( ) ;
401+ if ( peerError != null ) {
402+ const message = `Connection start failed with peerError ${ Buffer . from (
403+ peerError . reason ,
404+ ) . toString ( ) } (${ peerError . errorCode } )`;
405+ this . logger . info ( message ) ;
406+ throw new errors . ErrorQUICConnectionInternal ( message , {
407+ data : {
408+ type : 'local' ,
409+ ...peerError ,
410+ } ,
411+ } ) ;
412+ }
413+ // Throw the default error if none of the above were true, this shouldn't really happen
414+ throw e ;
415+ } ) ;
373416 this . logger . warn ( 'secured' ) ;
374417 // After this is done
375418 // We need to established the keep alive interval time
@@ -460,6 +503,14 @@ class QUICConnection extends EventTarget {
460503 // But during `start` we are just waiting
461504 this . socket . connectionMap . delete ( this . connectionId ) ;
462505
506+ if ( this . conn . isTimedOut ( ) ) {
507+ this . dispatchEvent (
508+ new events . QUICConnectionErrorEvent ( {
509+ detail : new errors . ErrorQUICConnectionIdleTimeOut ( ) ,
510+ } ) ,
511+ ) ;
512+ }
513+
463514 // Emit error if peer error
464515 const peerError = this . conn . peerError ( ) ;
465516 if ( peerError != null ) {
@@ -469,15 +520,12 @@ class QUICConnection extends EventTarget {
469520 this . logger . info ( message ) ;
470521 this . dispatchEvent (
471522 new events . QUICConnectionErrorEvent ( {
472- detail : new errors . ErrorQUICConnectionInternal (
473- message ,
474- {
475- data : {
476- type : 'local' ,
477- ...peerError ,
478- }
523+ detail : new errors . ErrorQUICConnectionInternal ( message , {
524+ data : {
525+ type : 'local' ,
526+ ...peerError ,
479527 } ,
480- ) ,
528+ } ) ,
481529 } ) ,
482530 ) ;
483531 }
@@ -490,15 +538,12 @@ class QUICConnection extends EventTarget {
490538 this . logger . info ( message ) ;
491539 this . dispatchEvent (
492540 new events . QUICConnectionErrorEvent ( {
493- detail : new errors . ErrorQUICConnectionInternal (
494- message ,
495- {
496- data : {
497- type : 'local' ,
498- ...localError ,
499- }
500- }
501- ) ,
541+ detail : new errors . ErrorQUICConnectionInternal ( message , {
542+ data : {
543+ type : 'local' ,
544+ ...localError ,
545+ } ,
546+ } ) ,
502547 } ) ,
503548 ) ;
504549 }
@@ -578,7 +623,7 @@ class QUICConnection extends EventTarget {
578623 // Short indicates that the peer has completed TLS verification
579624 if ( ! this . shortReceived ) {
580625 const header = quiche . Header . fromSlice ( data , quiche . MAX_CONN_ID_LEN ) ;
581- // if short frame
626+ // If short frame
582627 if ( header . ty === 5 ) {
583628 this . shortReceived = true ;
584629 this . conn . sendAckEliciting ( ) ;
@@ -594,7 +639,7 @@ class QUICConnection extends EventTarget {
594639 if ( this . count >= 1 ) {
595640 this . secured = true ;
596641 this . resolveSecureEstablishedP ( ) ;
597- // this .dispatchEvent(new events.QUICConnectionRemoteSecureEvent()); TODO
642+ // This .dispatchEvent(new events.QUICConnectionRemoteSecureEvent()); TODO
598643 }
599644 this . count += 1 ;
600645 }
@@ -757,9 +802,7 @@ class QUICConnection extends EventTarget {
757802 this . customVerified = true ;
758803 const peerCerts = this . conn . peerCertChain ( ) ;
759804 if ( peerCerts == null ) never ( ) ;
760- const peerCertsPem = peerCerts . map ( ( c ) =>
761- utils . certificateDERToPEM ( c ) ,
762- ) ;
805+ const peerCertsPem = peerCerts . map ( ( c ) => utils . certificateDERToPEM ( c ) ) ;
763806 // Dispatching certs available event
764807 // this.dispatchEvent(new events.QUICConnectionRemoteCertEvent()); TODO
765808 try {
@@ -833,6 +876,7 @@ class QUICConnection extends EventTarget {
833876 const connTimeOutHandler = async ( ) => {
834877 // This can only be called when the timeout has occurred
835878 // This transitions the connection state
879+ this . logger . debug ( 'CALLING ON TIMEOUT' ) ;
836880 this . conn . onTimeout ( ) ;
837881
838882 // At this point...
@@ -847,26 +891,16 @@ class QUICConnection extends EventTarget {
847891 // So if it is timed out, it gets closed too
848892 // But if it is is timed out due to idle we raise an error
849893
850- if ( this . conn . isTimedOut ( ) ) {
851- // This is just a dispatch on the connection error
852- // Note that this may cause the client to attempt
853- // to stop the socket and stuff
854- // The client should ignore this event error
855- // Because it's actually being handled
856- // On the other hand...
857- // If we randomly fail here
858- // It's correct to properly raise an event
859- // To bubble up....
860-
861- this . dispatchEvent (
862- new events . QUICConnectionErrorEvent ( {
863- detail : new errors . ErrorQUICConnectionIdleTimeOut ( ) ,
864- } ) ,
865- ) ;
866- }
867-
868894 // At the same time, we may in fact be closed too
869895 if ( this . conn . isClosed ( ) ) {
896+ // If it was still starting waiting for the secure event,
897+ // we need to reject that promise.
898+ if ( this [ status ] === 'starting' ) {
899+ this . rejectSecureEstablishedP (
900+ new errors . ErrorQUICConnectionInternal ( 'Connection has closed!' ) ,
901+ ) ;
902+ }
903+
870904 // We actually finally closed here
871905 // Actually the question is that this could be an error
872906 // The act of closing is an error?
@@ -903,8 +937,9 @@ class QUICConnection extends EventTarget {
903937 const timeout = this . conn . timeout ( ) ;
904938 // If this is `null`, then technically there's nothing to do
905939 if ( timeout == null ) return ;
940+ // Allow an extra 1ms for the delay to fully complete so we can avoid a repeated 0ms delay
906941 this . connTimeOutTimer = new Timer ( {
907- delay : timeout ,
942+ delay : timeout + 1 ,
908943 handler : connTimeOutHandler ,
909944 } ) ;
910945 } ;
@@ -916,6 +951,7 @@ class QUICConnection extends EventTarget {
916951 if ( this . connTimeOutTimer != null ) {
917952 this . connTimeOutTimer . cancel ( ) ;
918953 }
954+ this . logger . debug ( `timeout created with delay ${ timeout } ` ) ;
919955 this . connTimeOutTimer = new Timer ( {
920956 delay : timeout ,
921957 handler : connTimeOutHandler ,
0 commit comments