@@ -13,7 +13,8 @@ import type {
1313 VerifyCallback ,
1414} from './types' ;
1515import type { Connection , ConnectionErrorCode , SendInfo } from './native/types' ;
16- import { Lock , LockBox , Monitor , RWLockWriter } from '@matrixai/async-locks' ;
16+ import type { Monitor } from '@matrixai/async-locks' ;
17+ import { Lock , LockBox , RWLockWriter } from '@matrixai/async-locks' ;
1718import {
1819 ready ,
1920 running ,
@@ -515,29 +516,34 @@ class QUICConnection extends EventTarget {
515516 this . logger . debug ( 'streams destroyed' ) ;
516517 this . stopKeepAliveIntervalTimer ( ) ;
517518
518- mon = mon ?? new Monitor < RWLockWriter > ( this . lockbox , RWLockWriter ) ;
519519 // Trigger closing connection in the background and await close later.
520- void mon . withF ( this . lockCode , async ( mon ) => {
521- // If this is already closed, then `Done` will be thrown
522- // Otherwise it can send `CONNECTION_CLOSE` frame
523- // This can be 0x1c close at the QUIC layer or no errors
524- // Or it can be 0x1d for application close with an error
525- // Upon receiving a `CONNECTION_CLOSE`, you can send back
526- // 1 packet containing a `CONNECTION_CLOSE` frame too
527- // (with `NO_ERROR` code if appropriate)
528- // It must enter into a draining state, and no other packets can be sent
529- try {
530- this . conn . close ( applicationError , errorCode , Buffer . from ( errorMessage ) ) ;
531- // If we get a `Done` exception we don't bother calling send
532- // The send only gets sent if the `Done` is not the case
533- await this . send ( mon ) ;
534- } catch ( e ) {
535- // Ignore 'Done' if already closed
536- if ( e . message !== 'Done' ) {
537- // No other exceptions are expected
538- never ( ) ;
520+ void utils . withMonitor ( mon , this . lockbox , RWLockWriter , async ( mon ) => {
521+ await mon . withF ( this . lockCode , async ( mon ) => {
522+ // If this is already closed, then `Done` will be thrown
523+ // Otherwise it can send `CONNECTION_CLOSE` frame
524+ // This can be 0x1c close at the QUIC layer or no errors
525+ // Or it can be 0x1d for application close with an error
526+ // Upon receiving a `CONNECTION_CLOSE`, you can send back
527+ // 1 packet containing a `CONNECTION_CLOSE` frame too
528+ // (with `NO_ERROR` code if appropriate)
529+ // It must enter into a draining state, and no other packets can be sent
530+ try {
531+ this . conn . close (
532+ applicationError ,
533+ errorCode ,
534+ Buffer . from ( errorMessage ) ,
535+ ) ;
536+ // If we get a `Done` exception we don't bother calling send
537+ // The send only gets sent if the `Done` is not the case
538+ await this . send ( mon ) ;
539+ } catch ( e ) {
540+ // Ignore 'Done' if already closed
541+ if ( e . message !== 'Done' ) {
542+ // No other exceptions are expected
543+ never ( ) ;
544+ }
539545 }
540- }
546+ } ) ;
541547 } ) ;
542548
543549 if ( this . conn . isClosed ( ) ) {
@@ -750,17 +756,14 @@ class QUICConnection extends EventTarget {
750756 * Any errors must be emitted as events.
751757 * @internal
752758 */
753- public async send (
754- mon : Monitor < RWLockWriter > = new Monitor < RWLockWriter > (
755- this . lockbox ,
756- RWLockWriter ,
757- ) ,
758- ) : Promise < void > {
759- if ( ! mon . isLocked ( this . lockCode ) ) {
760- return mon . withF ( this . lockCode , async ( mon ) => {
761- return this . send ( mon ) ;
762- } ) ;
763- }
759+ public async send ( mon ?: Monitor < RWLockWriter > ) : Promise < void > {
760+ await utils . withMonitor ( mon , this . lockbox , RWLockWriter , async ( mon ) => {
761+ if ( ! mon . isLocked ( this . lockCode ) ) {
762+ return mon . withF ( this . lockCode , async ( mon ) => {
763+ return this . send ( mon ) ;
764+ } ) ;
765+ }
766+ } ) ;
764767
765768 const sendBuffer = new Uint8Array ( quiche . MAX_DATAGRAM_SIZE ) ;
766769 let sendLength : number ;
@@ -914,17 +917,15 @@ class QUICConnection extends EventTarget {
914917 this . resolveClosedP ( ) ;
915918 // If we are still running and not stopping then we need to stop
916919 if ( this [ running ] && this [ status ] !== 'stopping' ) {
917- const mon = new Monitor ( this . lockbox , RWLockWriter ) ;
918920 // Background stopping, we don't want to block the timer resolving
919- void this . stop ( { force : true } , mon ) ;
921+ void this . stop ( { force : true } ) ;
920922 }
921923 logger . debug ( 'CLEANING UP TIMER' ) ;
922924 return ;
923925 }
924926
925- const mon = new Monitor ( this . lockbox , RWLockWriter ) ;
926927 // There may be data to send after timing out
927- void this . send ( mon ) ;
928+ void this . send ( ) ;
928929
929930 // Note that a `0` timeout is still a valid timeout
930931 const timeout = this . conn . timeout ( ) ;
@@ -982,9 +983,8 @@ class QUICConnection extends EventTarget {
982983 // Intelligently schedule a PING frame.
983984 // If the connection has already sent ack-eliciting frames
984985 // then this is a noop.
985- const mon = new Monitor ( this . lockbox , RWLockWriter ) ;
986986 this . conn . sendAckEliciting ( ) ;
987- await this . send ( mon ) ;
987+ await this . send ( ) ;
988988 this . keepAliveIntervalTimer = new Timer ( {
989989 delay : ms ,
990990 handler : keepAliveHandler ,
0 commit comments