@@ -43,7 +43,11 @@ import {
4343 status ,
4444} from '@matrixai/async-init/dist/StartStop' ;
4545import { AbstractEvent , EventAll } from '@matrixai/events' ;
46- import { context , timedCancellable } from '@matrixai/contexts/dist/decorators' ;
46+ import {
47+ context ,
48+ timed ,
49+ timedCancellable ,
50+ } from '@matrixai/contexts/dist/decorators' ;
4751import { Semaphore } from '@matrixai/async-locks' ;
4852import { PromiseCancellable } from '@matrixai/async-cancellable' ;
4953import NodeConnection from './NodeConnection' ;
@@ -768,13 +772,15 @@ class NodeConnectionManager {
768772 * itself is such that we can pass targetNodeId as a parameter (as opposed to
769773 * an acquire function with no parameters).
770774 * @param targetNodeId Id of target node to communicate with
775+ * @param ctx
771776 * @returns ResourceAcquire Resource API for use in with contexts
772777 */
773778 public acquireConnection (
774779 targetNodeId : NodeId ,
780+ ctx : ContextTimed ,
775781 ) : ResourceAcquire < NodeConnection > {
776782 return async ( ) => {
777- await this . isAuthenticatedP ( targetNodeId ) ;
783+ await this . isAuthenticatedP ( targetNodeId , ctx ) ;
778784 return await this . acquireConnectionInternal ( targetNodeId ) ( ) ;
779785 } ;
780786 }
@@ -785,14 +791,22 @@ class NodeConnectionManager {
785791 * doesn't exist.
786792 * for use with normal arrow function
787793 * @param targetNodeId Id of target node to communicate with
794+ * @param ctx
788795 * @param f Function to handle communication
789796 */
790797 public async withConnF < T > (
791798 targetNodeId : NodeId ,
799+ ctx : Partial < ContextTimedInput > | undefined ,
800+ f : ( conn : NodeConnection ) => Promise < T > ,
801+ ) : Promise < T > ;
802+ @timedCancellable ( true )
803+ public async withConnF < T > (
804+ targetNodeId : NodeId ,
805+ @context ctx : ContextTimed ,
792806 f : ( conn : NodeConnection ) => Promise < T > ,
793807 ) : Promise < T > {
794808 return await withF (
795- [ this . acquireConnection ( targetNodeId ) ] ,
809+ [ this . acquireConnection ( targetNodeId , ctx ) ] ,
796810 async ( [ conn ] ) => {
797811 return await f ( conn ) ;
798812 } ,
@@ -805,14 +819,22 @@ class NodeConnectionManager {
805819 * doesn't exist.
806820 * for use with a generator function
807821 * @param targetNodeId Id of target node to communicate with
822+ * @param ctx
808823 * @param g Generator function to handle communication
809824 */
825+ public withConnG < T , TReturn , TNext > (
826+ targetNodeId : NodeId ,
827+ ctx : Partial < ContextTimedInput > | undefined ,
828+ g : ( conn : NodeConnection ) => AsyncGenerator < T , TReturn , TNext > ,
829+ ) : AsyncGenerator < T , TReturn , TNext > ;
810830 @ready ( new nodesErrors . ErrorNodeConnectionManagerNotRunning ( ) )
831+ @timed ( )
811832 public async * withConnG < T , TReturn , TNext > (
812833 targetNodeId : NodeId ,
834+ @context ctx : ContextTimed ,
813835 g : ( conn : NodeConnection ) => AsyncGenerator < T , TReturn , TNext > ,
814836 ) : AsyncGenerator < T , TReturn , TNext > {
815- const acquire = this . acquireConnection ( targetNodeId ) ;
837+ const acquire = this . acquireConnection ( targetNodeId , ctx ) ;
816838 const [ release , conn ] = await acquire ( ) ;
817839 let caughtError : Error | undefined ;
818840 try {
@@ -975,6 +997,7 @@ class NodeConnectionManager {
975997 }
976998 const { host, port } = await this . withConnF (
977999 nodeIdSignaller ,
1000+ ctx ,
9781001 async ( conn ) => {
9791002 const client = conn . getClient ( ) ;
9801003 const nodeIdSource = this . keyRing . getNodeId ( ) ;
@@ -1440,8 +1463,27 @@ class NodeConnectionManager {
14401463 * @param targetNodeId - NodeId of the node that needs to initiate hole punching.
14411464 * @param address - Address the target needs to punch to.
14421465 * @param requestSignature - `base64url` encoded signature
1466+ * @param ctx
14431467 */
1468+ public async handleNodesConnectionSignalInitial (
1469+ sourceNodeId : NodeId ,
1470+ targetNodeId : NodeId ,
1471+ address : {
1472+ host : Host ;
1473+ port : Port ;
1474+ } ,
1475+ requestSignature : string ,
1476+ ctx ?: Partial < ContextTimedInput > ,
1477+ ) : Promise < {
1478+ host : Host ;
1479+ port : Port ;
1480+ } > ;
14441481 @ready ( new nodesErrors . ErrorNodeManagerNotRunning ( ) )
1482+ @timedCancellable (
1483+ true ,
1484+ ( nodeConnectionManager : NodeConnectionManager ) =>
1485+ nodeConnectionManager . connectionConnectTimeoutTime ,
1486+ )
14451487 public async handleNodesConnectionSignalInitial (
14461488 sourceNodeId : NodeId ,
14471489 targetNodeId : NodeId ,
@@ -1450,6 +1492,7 @@ class NodeConnectionManager {
14501492 port : Port ;
14511493 } ,
14521494 requestSignature : string ,
1495+ @context ctx : ContextTimed ,
14531496 ) : Promise < {
14541497 host : Host ;
14551498 port : Port ;
@@ -1479,16 +1522,20 @@ class NodeConnectionManager {
14791522 this . keyRing . keyPair ,
14801523 data ,
14811524 ) ;
1482- const connectionSignalP = this . withConnF ( targetNodeId , async ( conn ) => {
1483- const client = conn . getClient ( ) ;
1484- await client . methods . nodesConnectionSignalFinal ( {
1485- sourceNodeIdEncoded : nodesUtils . encodeNodeId ( sourceNodeId ) ,
1486- targetNodeIdEncoded : nodesUtils . encodeNodeId ( targetNodeId ) ,
1487- address,
1488- requestSignature : requestSignature ,
1489- relaySignature : relaySignature . toString ( 'base64url' ) ,
1490- } ) ;
1491- } )
1525+ const connectionSignalP = this . withConnF (
1526+ targetNodeId ,
1527+ ctx ,
1528+ async ( conn ) => {
1529+ const client = conn . getClient ( ) ;
1530+ await client . methods . nodesConnectionSignalFinal ( {
1531+ sourceNodeIdEncoded : nodesUtils . encodeNodeId ( sourceNodeId ) ,
1532+ targetNodeIdEncoded : nodesUtils . encodeNodeId ( targetNodeId ) ,
1533+ address : address ,
1534+ requestSignature : requestSignature ,
1535+ relaySignature : relaySignature . toString ( 'base64url' ) ,
1536+ } ) ;
1537+ } ,
1538+ )
14921539 // Ignore results and failures, then are expected to happen and are allowed
14931540 . then (
14941541 ( ) => { } ,
@@ -1745,19 +1792,40 @@ class NodeConnectionManager {
17451792 * Returns a promise that resolves once the connection has authenticated,
17461793 * otherwise it rejects with the authentication failure
17471794 * @param nodeId
1795+ * @param ctx
17481796 */
1749- public async isAuthenticatedP ( nodeId : NodeId ) : Promise < void > {
1797+ public async isAuthenticatedP (
1798+ nodeId : NodeId ,
1799+ ctx ?: Partial < ContextTimedInput > ,
1800+ ) : Promise < void > ;
1801+ @timedCancellable (
1802+ true ,
1803+ ( nodeConnectionManager : NodeConnectionManager ) =>
1804+ nodeConnectionManager . connectionConnectTimeoutTime ,
1805+ )
1806+ public async isAuthenticatedP (
1807+ nodeId : NodeId ,
1808+ @context ctx : ContextTimed ,
1809+ ) : Promise < void > {
1810+ ctx . signal . throwIfAborted ( ) ;
17501811 const targetNodeIdString = nodeId . toString ( ) as NodeIdString ;
17511812 const connectionsEntry = this . connections . get ( targetNodeIdString ) ;
17521813 if ( connectionsEntry == null ) {
17531814 throw new nodesErrors . ErrorNodeConnectionManagerConnectionNotFound ( ) ;
17541815 }
1816+ const { p : abortP , rejectP : rejectAbortP } = utils . promise < never > ( ) ;
1817+ const abortHandler = ( ) => {
1818+ rejectAbortP ( ctx . signal . reason ) ;
1819+ } ;
1820+ ctx . signal . addEventListener ( 'abort' , abortHandler , { once : true } ) ;
17551821 try {
1756- return await connectionsEntry . authenticatedP ;
1822+ return await Promise . race ( [ connectionsEntry . authenticatedP , abortP ] ) ;
17571823 } catch ( e ) {
17581824 // Capture the stacktrace here since knowing where we're waiting for authentication is more useful
17591825 Error . captureStackTrace ( e ) ;
17601826 throw e ;
1827+ } finally {
1828+ ctx . signal . removeEventListener ( 'abort' , abortHandler ) ;
17611829 }
17621830 }
17631831
0 commit comments