@@ -7,9 +7,9 @@ import type Sigchain from '../sigchain/Sigchain';
77import type TaskManager from '../tasks/TaskManager' ;
88import type GestaltGraph from '../gestalts/GestaltGraph' ;
99import type {
10+ Task ,
1011 TaskHandler ,
1112 TaskHandlerId ,
12- Task ,
1313 TaskInfo ,
1414} from '../tasks/types' ;
1515import type { SignedTokenEncoded } from '../tokens/types' ;
@@ -23,32 +23,33 @@ import type {
2323import type { ClaimLinkNode } from '../claims/payloads' ;
2424import type NodeConnection from '../nodes/NodeConnection' ;
2525import type {
26+ AgentClaimMessage ,
2627 AgentRPCRequestParams ,
2728 AgentRPCResponseResult ,
28- AgentClaimMessage ,
2929 NodesAuthenticateConnectionMessage ,
3030} from './agent/types' ;
3131import type {
32- NodeId ,
32+ AuthenticateNetworkForwardCallback ,
33+ AuthenticateNetworkReverseCallback ,
3334 NodeAddress ,
3435 NodeBucket ,
3536 NodeBucketIndex ,
3637 NodeContactAddressData ,
38+ NodeId ,
3739 NodeIdEncoded ,
38- AuthenticateNetworkForwardCallback ,
39- AuthenticateNetworkReverseCallback ,
4040 NodeIdString ,
4141} from './types' ;
4242import type NodeConnectionManager from './NodeConnectionManager' ;
4343import type NodeGraph from './NodeGraph' ;
4444import type { ServicePOJO } from '@matrixai/mdns' ;
45+ import { withF } from '@matrixai/resources' ;
46+ import { events as mdnsEvents , MDNS , utils as mdnsUtils } from '@matrixai/mdns' ;
4547import Logger from '@matrixai/logger' ;
46- import { StartStop , ready } from '@matrixai/async-init/dist/StartStop' ;
47- import { Semaphore , Lock } from '@matrixai/async-locks' ;
48+ import { ready , StartStop } from '@matrixai/async-init/dist/StartStop' ;
49+ import { Lock , Semaphore } from '@matrixai/async-locks' ;
4850import { IdInternal } from '@matrixai/id' ;
49- import { timedCancellable , context } from '@matrixai/contexts/dist/decorators' ;
50- import { withF } from '@matrixai/resources' ;
51- import { MDNS , events as mdnsEvents , utils as mdnsUtils } from '@matrixai/mdns' ;
51+ import { context , timedCancellable } from '@matrixai/contexts/dist/decorators' ;
52+ import { Timer } from '@matrixai/timer' ;
5253import * as nodesUtils from './utils' ;
5354import * as nodesEvents from './events' ;
5455import * as nodesErrors from './errors' ;
@@ -77,12 +78,13 @@ enum AuthenticatingState {
7778}
7879type AuthenticationEntry = {
7980 authenticatedForward : AuthenticatingState ;
80- reasonForward ?: any ;
81+ reasonForward ?: Error ;
8182 authenticatedReverse : AuthenticatingState ;
82- reasonReverse ?: any ;
83+ reasonReverse ?: Error ;
8384 authenticatedP : Promise < void > ;
8485 authenticatedResolveP : ( value : void ) => void ;
85- authenticatedRejectP : ( reason ?: any ) => void ;
86+ authenticatedRejectP : ( reason ?: Error ) => void ;
87+ timeout ?: Timer ;
8688} ;
8789
8890const activeForwardAuthenticateCancellationReason = Symbol (
@@ -1182,10 +1184,14 @@ class NodeManager {
11821184 } ) ;
11831185 connectionsEntry . authenticatedForward = AuthenticatingState . SUCCESS ;
11841186 } catch ( e ) {
1187+ const err = new nodesErrors . ErrorNodeManagerForwardAuthenticationFailed (
1188+ undefined ,
1189+ { cause : e } ,
1190+ ) ;
11851191 connectionsEntry . authenticatedForward = AuthenticatingState . FAIL ;
1186- connectionsEntry . reasonForward = e ;
1192+ connectionsEntry . reasonForward = err ;
11871193 await this . authenticateFail ( nodeId ) ;
1188- throw e ;
1194+ return ;
11891195 }
11901196 this . logger . warn (
11911197 `Node ${ nodesUtils . encodeNodeId ( nodeId ) } has been forward authenticated` ,
@@ -1270,9 +1276,6 @@ class NodeManager {
12701276 }
12711277 }
12721278
1273- // TODO: There's a race condition with this and awaiting authentication. There are cases where authentication can complete before we can even start awaiting authenctication. We need to handle this better.
1274- // It's better handled by starting the wait for authentication and then initiating it but the ordering of this sucks.
1275- // best thing for now is to allow awaiting the authentication before even triggering the connections.
12761279 /**
12771280 * Will initiate a forward authentication call and coalesce
12781281 */
@@ -1286,18 +1289,61 @@ class NodeManager {
12861289 resolveP : authenticatedResolveP ,
12871290 rejectP : authenticatedRejectP ,
12881291 } = utils . promise < void > ( ) ;
1289- // Prevent unhandled rejections
1290- authenticatedP . then (
1291- ( ) => { } ,
1292- ( ) => { } ,
1293- ) ;
1292+ const timeoutDelay = 1000 ;
1293+ const timeout = new Timer ( { delay : timeoutDelay } ) ;
1294+ // Prevent cancellation leak when cleaning up
1295+ void timeout . catch ( ( ) => { } ) ;
12941296 authenticationEntry = {
12951297 authenticatedForward : AuthenticatingState . PENDING ,
12961298 authenticatedReverse : AuthenticatingState . PENDING ,
12971299 authenticatedP,
12981300 authenticatedResolveP,
12991301 authenticatedRejectP,
1302+ timeout,
13001303 } ;
1304+ void timeout . then (
1305+ async ( ) => {
1306+ this . logger . warn ( `TIMED OUT!` ) ;
1307+ const error = new nodesErrors . ErrorNodeManagerAuthenticatonTimedOut (
1308+ `Authentication timed out after ${ timeoutDelay } ms` ,
1309+ ) ;
1310+ if (
1311+ authenticationEntry ! . authenticatedForward ===
1312+ AuthenticatingState . PENDING
1313+ ) {
1314+ authenticationEntry ! . authenticatedForward =
1315+ AuthenticatingState . FAIL ;
1316+ authenticationEntry ! . reasonForward = error ;
1317+ }
1318+ if (
1319+ authenticationEntry ! . authenticatedReverse ===
1320+ AuthenticatingState . PENDING
1321+ ) {
1322+ authenticationEntry ! . authenticatedReverse =
1323+ AuthenticatingState . FAIL ;
1324+ authenticationEntry ! . reasonReverse = error ;
1325+ }
1326+ if (
1327+ authenticationEntry ! . authenticatedForward ===
1328+ AuthenticatingState . FAIL ||
1329+ authenticationEntry ! . authenticatedReverse ===
1330+ AuthenticatingState . FAIL
1331+ ) {
1332+ await this . authenticateFail ( nodeId ) ;
1333+ }
1334+ delete authenticationEntry ! . timeout ;
1335+ } ,
1336+ ( ) => { } ,
1337+ ) ;
1338+ const authenticationWithCleanupP = authenticatedP . finally ( ( ) => {
1339+ timeout . cancel ( Error ( 'reason' ) ) ;
1340+ } ) ;
1341+ // Prevent unhandled rejections
1342+ authenticationWithCleanupP . then (
1343+ ( ) => { } ,
1344+ ( ) => { } ,
1345+ ) ;
1346+ authenticationEntry . authenticatedP = authenticationWithCleanupP ;
13011347 this . authenticationMap . set ( nodeIdString , authenticationEntry ) ;
13021348 }
13031349 const existingAuthenticate =
@@ -1349,10 +1395,14 @@ class NodeManager {
13491395 throw new nodesErrors . ErrorNodeConnectionManagerConnectionNotFound ( ) ;
13501396 }
13511397 try {
1398+ this . logger . warn ( 'waiting' ) ;
13521399 return await connectionsEntry . authenticatedP ;
13531400 } catch ( e ) {
1401+ this . logger . warn ( 'failed waiting' ) ;
13541402 Error . captureStackTrace ( e ) ;
13551403 throw e ;
1404+ } finally {
1405+ this . logger . warn ( 'done' ) ;
13561406 }
13571407 }
13581408
@@ -1370,10 +1420,13 @@ class NodeManager {
13701420 this . logger . warn ( 'skipped' ) ;
13711421 return ;
13721422 }
1373- const rejectAuthentication = connectionsEntry . authenticatedRejectP ;
1423+ const authenticatedRejectP = connectionsEntry . authenticatedRejectP ;
13741424 // Trigger shutdown of the connections
13751425 await this . nodeConnectionManager . destroyConnection ( nodeId , true ) ;
1376- let reason ;
1426+ let reason : Error ;
1427+ this . logger . warn (
1428+ `boi ${ connectionsEntry . reasonForward } |${ connectionsEntry . reasonReverse } ` ,
1429+ ) ;
13771430 if (
13781431 connectionsEntry . reasonForward != null &&
13791432 connectionsEntry . reasonReverse != null
@@ -1393,7 +1446,8 @@ class NodeManager {
13931446 utils . never ( 'No reason was provided' ) ;
13941447 }
13951448 this . logger . warn ( `Authentication failed with: ${ reason . toString ( ) } ` ) ;
1396- rejectAuthentication (
1449+ // Removing authentication entry
1450+ authenticatedRejectP (
13971451 new nodesErrors . ErrorNodeManagerAuthenticationFailed ( undefined , {
13981452 cause : reason ,
13991453 } ) ,
0 commit comments