@@ -2,28 +2,33 @@ import type { PromiseCancellable } from '@matrixai/async-cancellable';
2
2
import type { ContextTimed } from '@matrixai/contexts' ;
3
3
import type QUICSocket from './QUICSocket' ;
4
4
import 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' ;
6
14
import 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' ;
10
16
import {
11
- StartStop ,
12
17
ready ,
13
- status ,
14
18
running ,
19
+ StartStop ,
20
+ status ,
15
21
} from '@matrixai/async-init/dist/StartStop' ;
16
22
import Logger from '@matrixai/logger' ;
17
- import { Lock , LockBox } from '@matrixai/async-locks' ;
18
23
import { Timer } from '@matrixai/timer' ;
19
24
import { context , timedCancellable } from '@matrixai/contexts/dist/decorators' ;
20
25
import { buildQuicheConfig } from './config' ;
21
26
import QUICStream from './QUICStream' ;
22
27
import { quiche } from './native' ;
23
28
import * as events from './events' ;
24
29
import * as utils from './utils' ;
25
- import * as errors from './errors' ;
26
30
import { never } from './utils' ;
31
+ import * as errors from './errors' ;
27
32
28
33
// FIXME
29
34
type VerifyCallback = ( certs : Array < string > ) => void ;
@@ -369,7 +374,45 @@ class QUICConnection extends EventTarget {
369
374
// Waits for the first short packet after establishment
370
375
// This ensures that TLS has been established and verified on both sides
371
376
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
+ } ) ;
373
416
this . logger . warn ( 'secured' ) ;
374
417
// After this is done
375
418
// We need to established the keep alive interval time
@@ -460,6 +503,14 @@ class QUICConnection extends EventTarget {
460
503
// But during `start` we are just waiting
461
504
this . socket . connectionMap . delete ( this . connectionId ) ;
462
505
506
+ if ( this . conn . isTimedOut ( ) ) {
507
+ this . dispatchEvent (
508
+ new events . QUICConnectionErrorEvent ( {
509
+ detail : new errors . ErrorQUICConnectionIdleTimeOut ( ) ,
510
+ } ) ,
511
+ ) ;
512
+ }
513
+
463
514
// Emit error if peer error
464
515
const peerError = this . conn . peerError ( ) ;
465
516
if ( peerError != null ) {
@@ -469,15 +520,12 @@ class QUICConnection extends EventTarget {
469
520
this . logger . info ( message ) ;
470
521
this . dispatchEvent (
471
522
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 ,
479
527
} ,
480
- ) ,
528
+ } ) ,
481
529
} ) ,
482
530
) ;
483
531
}
@@ -490,15 +538,12 @@ class QUICConnection extends EventTarget {
490
538
this . logger . info ( message ) ;
491
539
this . dispatchEvent (
492
540
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
+ } ) ,
502
547
} ) ,
503
548
) ;
504
549
}
@@ -578,7 +623,7 @@ class QUICConnection extends EventTarget {
578
623
// Short indicates that the peer has completed TLS verification
579
624
if ( ! this . shortReceived ) {
580
625
const header = quiche . Header . fromSlice ( data , quiche . MAX_CONN_ID_LEN ) ;
581
- // if short frame
626
+ // If short frame
582
627
if ( header . ty === 5 ) {
583
628
this . shortReceived = true ;
584
629
this . conn . sendAckEliciting ( ) ;
@@ -594,7 +639,7 @@ class QUICConnection extends EventTarget {
594
639
if ( this . count >= 1 ) {
595
640
this . secured = true ;
596
641
this . resolveSecureEstablishedP ( ) ;
597
- // this .dispatchEvent(new events.QUICConnectionRemoteSecureEvent()); TODO
642
+ // This .dispatchEvent(new events.QUICConnectionRemoteSecureEvent()); TODO
598
643
}
599
644
this . count += 1 ;
600
645
}
@@ -757,9 +802,7 @@ class QUICConnection extends EventTarget {
757
802
this . customVerified = true ;
758
803
const peerCerts = this . conn . peerCertChain ( ) ;
759
804
if ( peerCerts == null ) never ( ) ;
760
- const peerCertsPem = peerCerts . map ( ( c ) =>
761
- utils . certificateDERToPEM ( c ) ,
762
- ) ;
805
+ const peerCertsPem = peerCerts . map ( ( c ) => utils . certificateDERToPEM ( c ) ) ;
763
806
// Dispatching certs available event
764
807
// this.dispatchEvent(new events.QUICConnectionRemoteCertEvent()); TODO
765
808
try {
@@ -833,6 +876,7 @@ class QUICConnection extends EventTarget {
833
876
const connTimeOutHandler = async ( ) => {
834
877
// This can only be called when the timeout has occurred
835
878
// This transitions the connection state
879
+ this . logger . debug ( 'CALLING ON TIMEOUT' ) ;
836
880
this . conn . onTimeout ( ) ;
837
881
838
882
// At this point...
@@ -847,26 +891,16 @@ class QUICConnection extends EventTarget {
847
891
// So if it is timed out, it gets closed too
848
892
// But if it is is timed out due to idle we raise an error
849
893
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
-
868
894
// At the same time, we may in fact be closed too
869
895
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
+
870
904
// We actually finally closed here
871
905
// Actually the question is that this could be an error
872
906
// The act of closing is an error?
@@ -903,8 +937,9 @@ class QUICConnection extends EventTarget {
903
937
const timeout = this . conn . timeout ( ) ;
904
938
// If this is `null`, then technically there's nothing to do
905
939
if ( timeout == null ) return ;
940
+ // Allow an extra 1ms for the delay to fully complete so we can avoid a repeated 0ms delay
906
941
this . connTimeOutTimer = new Timer ( {
907
- delay : timeout ,
942
+ delay : timeout + 1 ,
908
943
handler : connTimeOutHandler ,
909
944
} ) ;
910
945
} ;
@@ -916,6 +951,7 @@ class QUICConnection extends EventTarget {
916
951
if ( this . connTimeOutTimer != null ) {
917
952
this . connTimeOutTimer . cancel ( ) ;
918
953
}
954
+ this . logger . debug ( `timeout created with delay ${ timeout } ` ) ;
919
955
this . connTimeOutTimer = new Timer ( {
920
956
delay : timeout ,
921
957
handler : connTimeOutHandler ,
0 commit comments