Skip to content

Commit 3905fa8

Browse files
committed
chore: updated documentation
1 parent 468e8f1 commit 3905fa8

11 files changed

Lines changed: 450 additions & 204 deletions

src/nodes/NodeConnectionManager.ts

Lines changed: 249 additions & 107 deletions
Large diffs are not rendered by default.

src/nodes/NodeManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1628,7 +1628,7 @@ class NodeManager {
16281628
}
16291629

16301630
if (!success) {
1631-
throw new agentErrors.ErrorNodesClaimNetworkVerificationFailed();
1631+
throw new nodesErrors.ErrorNodeClaimNetworkVerificationFailed();
16321632
}
16331633

16341634
return {

src/nodes/agent/errors.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,4 @@ class ErrorAgentNodeIdMissing<T> extends ErrorAgent<T> {
88
exitCode = sysexits.UNAVAILABLE;
99
}
1010

11-
// NOTE: NEEDS REVIEW
12-
class ErrorNodesConnectionSignalRequestVerificationFailed<
13-
T,
14-
> extends ErrorAgent<T> {
15-
static description = 'Failed to verify request message signature';
16-
exitCode = sysexits.UNAVAILABLE;
17-
}
18-
19-
class ErrorNodesConnectionSignalRelayVerificationFailed<
20-
T,
21-
> extends ErrorAgent<T> {
22-
static description = 'Failed to verify relay message signature';
23-
exitCode = sysexits.UNAVAILABLE;
24-
}
25-
26-
class ErrorNodesClaimNetworkVerificationFailed<T> extends ErrorAgent<T> {
27-
static description = 'Failed to verify claim network message';
28-
exitCode = sysexits.UNAVAILABLE;
29-
}
30-
31-
class ErrorAgentAuthenticationFailed<T> extends ErrorAgent<T> {
32-
static description = 'Failed to authenticate a node connection';
33-
exitCode = sysexits.SOFTWARE;
34-
}
35-
36-
export {
37-
ErrorAgentNodeIdMissing,
38-
ErrorNodesConnectionSignalRequestVerificationFailed,
39-
ErrorNodesConnectionSignalRelayVerificationFailed,
40-
ErrorNodesClaimNetworkVerificationFailed,
41-
ErrorAgentAuthenticationFailed,
42-
};
11+
export { ErrorAgentNodeIdMissing };

src/nodes/agent/handlers/NodesAuthenticateConnection.ts

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import type { JSONValue } from '../../../types.js';
1010
import { DuplexHandler } from '@matrixai/rpc';
1111
import * as agentErrors from '../errors.js';
1212
import * as agentUtils from '../utils.js';
13-
import * as utils from '../../../utils/index.js';
1413

1514
class NodesAuthenticateConnection extends DuplexHandler<
1615
{
@@ -43,53 +42,13 @@ class NodesAuthenticateConnection extends DuplexHandler<
4342
throw new agentErrors.ErrorAgentNodeIdMissing();
4443
}
4544

46-
// Process incoming forward authentication
47-
const reverseMessageInPair = await utils.valueOrTimeout(input.next(), ctx);
48-
const reverseMessageIn:
49-
| SuccessMessage
50-
| NodesAuthenticateConnectionMessage = reverseMessageInPair.value;
51-
if (reverseMessageIn.type === 'success') {
52-
throw new agentErrors.ErrorAgentAuthenticationFailed(
53-
'Expected authentication message but got success message',
54-
);
55-
}
56-
const forwardMessageOut = await nodeConnectionManager.handleAuthentication(
45+
// This async generator handles the back-and-forth communication to
46+
// authenticate a connection.
47+
yield* nodeConnectionManager.handleAuthentication(
5748
requestingNodeId,
58-
reverseMessageIn,
49+
input,
5950
ctx,
6051
);
61-
yield {
62-
type: 'success',
63-
success: true,
64-
};
65-
66-
// Send forward authentication message from this node
67-
yield forwardMessageOut;
68-
const forwardMessageResultPair = await utils.valueOrTimeout(
69-
input.next(),
70-
ctx,
71-
);
72-
const forwardMessageResult:
73-
| SuccessMessage
74-
| NodesAuthenticateConnectionMessage = forwardMessageResultPair.value;
75-
if (forwardMessageResult.type !== 'success') {
76-
throw new agentErrors.ErrorAgentAuthenticationFailed(
77-
'Expected success message but got authentication message',
78-
);
79-
}
80-
81-
// Update internal state to finalize authentication
82-
nodeConnectionManager.finalizeAuthentication(
83-
requestingNodeId,
84-
forwardMessageResult.success,
85-
);
86-
87-
// Return final acknowledgement. Once this has been returned, all
88-
// connections are guaranteed to be authenticated from both sides.
89-
yield {
90-
type: 'success',
91-
success: true,
92-
};
9352
};
9453
}
9554

src/nodes/agent/handlers/NodesConnectionSignalFinal.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import * as keysUtils from '../../../keys/utils/index.js';
1515
import * as ids from '../../../ids/index.js';
1616
import * as agentErrors from '../errors.js';
1717
import * as agentUtils from '../utils.js';
18+
import * as nodesErrors from '../../errors.js';
1819

1920
class NodesConnectionSignalFinal extends UnaryHandler<
2021
{
@@ -68,7 +69,7 @@ class NodesConnectionSignalFinal extends UnaryHandler<
6869
requestSignature,
6970
)
7071
) {
71-
throw new agentErrors.ErrorNodesConnectionSignalRequestVerificationFailed();
72+
throw new nodesErrors.ErrorNodeConnectionSignalRequestVerificationFailed();
7273
}
7374
// Checking relay message relaySignature.
7475
// relayData is just `<sourceNodeId><targetNodeId><Address><requestSignature>` concatenated.
@@ -83,7 +84,7 @@ class NodesConnectionSignalFinal extends UnaryHandler<
8384
if (
8485
!keysUtils.verifyWithPublicKey(relayPublicKey, relayData, relaySignature)
8586
) {
86-
throw new agentErrors.ErrorNodesConnectionSignalRelayVerificationFailed();
87+
throw new nodesErrors.ErrorNodeConnectionSignalRelayVerificationFailed();
8788
}
8889

8990
const host = input.address.host as Host;

src/nodes/agent/handlers/NodesConnectionSignalInitial.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { matchSync } from '../../../utils/index.js';
1414
import { never } from '../../../utils/index.js';
1515
import * as agentErrors from '../errors.js';
1616
import * as agentUtils from '../utils.js';
17+
import * as nodesErrors from '../../errors.js';
1718
import * as keysUtils from '../../../keys/utils/index.js';
1819
import * as ids from '../../../ids/index.js';
1920

@@ -55,7 +56,7 @@ class NodesConnectionSignalInitial extends UnaryHandler<
5556
const data = Buffer.concat([requestingNodeId, targetNodeId]);
5657
const sourcePublicKey = keysUtils.publicKeyFromNodeId(requestingNodeId);
5758
if (!keysUtils.verifyWithPublicKey(sourcePublicKey, data, signature)) {
58-
throw new agentErrors.ErrorNodesConnectionSignalRelayVerificationFailed();
59+
throw new nodesErrors.ErrorNodeConnectionSignalRelayVerificationFailed();
5960
}
6061
if (meta == null) never('Missing metadata from stream');
6162
const remoteHost = meta.remoteHost;

src/nodes/errors.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,17 @@ class ErrorNodeManagerAuthenticationFailed<T> extends ErrorNodeManager<T> {
4848
exitCode = sysexits.NOPERM;
4949
}
5050

51-
class ErrorNodeManagerAuthenticationFailedForward<T> extends ErrorNodes<T> {
51+
class ErrorNodeManagerAuthenticationFailedForward<T> extends ErrorNodeManager<T> {
5252
static description = 'Failed to complete forward authentication';
5353
exitCode = sysexits.USAGE;
5454
}
5555

56-
class ErrorNodeManagerAuthenticationFailedReverse<T> extends ErrorNodes<T> {
56+
class ErrorNodeManagerAuthenticationFailedReverse<T> extends ErrorNodeManager<T> {
5757
static description = 'Failed to complete reverse authentication';
5858
exitCode = sysexits.USAGE;
5959
}
6060

61-
class ErrorNodeManagerAuthenticatonTimedOut<T> extends ErrorNodes<T> {
61+
class ErrorNodeManagerAuthenticationTimedOut<T> extends ErrorNodeManager<T> {
6262
static description = 'Failed to complete authentication before timing out';
6363
exitCode = sysexits.USAGE;
6464
}
@@ -154,7 +154,7 @@ class ErrorNodeConnectionTransportGenericError<
154154
exitCode = sysexits.USAGE;
155155
}
156156

157-
class ErrorConnectionNodesEmpty<T> extends ErrorNodeConnection<T> {
157+
class ErrorNodeConnectionEmpty<T> extends ErrorNodeConnection<T> {
158158
static description = 'Nodes list to verify against was empty';
159159
exitCode = sysexits.USAGE;
160160
}
@@ -256,6 +256,30 @@ class ErrorNodeAuthenticationFailed<T> extends ErrorNodes<T> {
256256
exitCode = sysexits.NOPERM;
257257
}
258258

259+
class ErrorNodeAuthenticationInvalidProtocol<T> extends ErrorNodes<T> {
260+
static description = 'Invalid protocol used for node authentication';
261+
exitCode = sysexits.USAGE;
262+
}
263+
264+
class ErrorNodeConnectionSignalRequestVerificationFailed<
265+
T,
266+
> extends ErrorNodeConnection<T> {
267+
static description = 'Failed to verify request message signature';
268+
exitCode = sysexits.UNAVAILABLE;
269+
}
270+
271+
class ErrorNodeConnectionSignalRelayVerificationFailed<
272+
T,
273+
> extends ErrorNodeConnection<T> {
274+
static description = 'Failed to verify relay message signature';
275+
exitCode = sysexits.UNAVAILABLE;
276+
}
277+
278+
class ErrorNodeClaimNetworkVerificationFailed<T> extends ErrorNodes<T> {
279+
static description = 'Failed to verify claim network message';
280+
exitCode = sysexits.UNAVAILABLE;
281+
}
282+
259283
export {
260284
ErrorNodes,
261285
ErrorNodeManager,
@@ -269,7 +293,7 @@ export {
269293
ErrorNodeManagerAuthenticationFailed,
270294
ErrorNodeManagerAuthenticationFailedForward,
271295
ErrorNodeManagerAuthenticationFailedReverse,
272-
ErrorNodeManagerAuthenticatonTimedOut,
296+
ErrorNodeManagerAuthenticationTimedOut,
273297
ErrorNodeGraph,
274298
ErrorNodeGraphRunning,
275299
ErrorNodeGraphNotRunning,
@@ -288,7 +312,7 @@ export {
288312
ErrorNodeConnectionInternalError,
289313
ErrorNodeConnectionTransportUnknownError,
290314
ErrorNodeConnectionTransportGenericError,
291-
ErrorConnectionNodesEmpty,
315+
ErrorNodeConnectionEmpty,
292316
ErrorNodeConnectionManager,
293317
ErrorNodeConnectionManagerNotRunning,
294318
ErrorNodeConnectionManagerStopping,
@@ -304,4 +328,8 @@ export {
304328
ErrorNodePermissionDenied,
305329
ErrorNodeLookupNotFound,
306330
ErrorNodeAuthenticationFailed,
331+
ErrorNodeAuthenticationInvalidProtocol,
332+
ErrorNodeClaimNetworkVerificationFailed,
333+
ErrorNodeConnectionSignalRelayVerificationFailed,
334+
ErrorNodeConnectionSignalRequestVerificationFailed,
307335
};

src/nodes/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ async function verifyServerCertificateChain(
566566
};
567567
}
568568
if (nodeIds.length === 0) {
569-
throw new nodesErrors.ErrorConnectionNodesEmpty();
569+
throw new nodesErrors.ErrorNodeConnectionEmpty();
570570
}
571571
const certChain: Array<Readonly<X509Certificate>> = [];
572572
for (const certPEM of certPEMChain) {

src/utils/utils.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,19 @@ async function importFS(fs?: FileSystem): Promise<FileSystem> {
547547
return fsImported;
548548
}
549549

550-
async function valueOrTimeout<T>(
550+
/**
551+
* Races a promise against a context. If the context is aborted, then the promise
552+
* rejects with the reason. Otherwise, the original value is returned upon
553+
* resolving.
554+
* @param prom The promise to resolve
555+
* @param ctx The ctx with which to race the promise against
556+
* @returns A promise which resolves to the prom value or errors if ctx aborts
557+
*/
558+
async function resultOrAbort<T>(
551559
prom: Promise<T>,
552560
ctx: ContextTimed,
553561
): Promise<T> {
562+
// Create an abort promise which rejects when ctx is aborted
554563
const { p: abortP, rejectP: rejectAbortP } = promise<never>();
555564
const abortHandler = () => {
556565
rejectAbortP(ctx.signal.reason);
@@ -560,6 +569,10 @@ async function valueOrTimeout<T>(
560569
} else {
561570
ctx.signal.addEventListener('abort', abortHandler, { once: true });
562571
}
572+
573+
// Race the original promise and abortP. If the original promise resolves
574+
// first, then it is returned. If the context aborts first, then the
575+
// promise is rejected.
563576
try {
564577
return await Promise.race([prom, abortP]);
565578
} catch (e) {
@@ -611,5 +624,5 @@ export {
611624
yieldMicro,
612625
setMaxListeners,
613626
importFS,
614-
valueOrTimeout,
627+
resultOrAbort,
615628
};

tests/nodes/NodeConnection.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ describe(`${NodeConnection.name}`, () => {
211211
nodesUtils.encodeNodeId(nodeConnection.nodeId),
212212
);
213213
});
214-
test('Should fail due to server rejecting client certificate (no certs)', async () => {
214+
test('should fail due to server rejecting client certificate (no certs)', async () => {
215215
const nodeConnection = await NodeConnection.createNodeConnection({
216216
handleStream: () => {},
217217
targetNodeIds: [serverNodeId],
@@ -237,7 +237,7 @@ describe(`${NodeConnection.name}`, () => {
237237
quicErrors.ErrorQUICConnectionPeerTLS,
238238
);
239239
});
240-
test('Should fail due to client rejecting server certificate (missing NodeId)', async () => {
240+
test('should fail due to client rejecting server certificate (missing NodeId)', async () => {
241241
const nodeConnectionProm = NodeConnection.createNodeConnection({
242242
targetNodeIds: [clientNodeId],
243243
targetHost: localHost as Host,
@@ -249,7 +249,7 @@ describe(`${NodeConnection.name}`, () => {
249249
}).then(extractNodeConnection);
250250
await expect(nodeConnectionProm).rejects.toThrow();
251251
});
252-
test('Should fail and destroy due to connection failure', async () => {
252+
test('should fail and destroy due to connection failure', async () => {
253253
const nodeConnection = await NodeConnection.createNodeConnection(
254254
{
255255
targetNodeIds: [serverNodeId],
@@ -271,7 +271,7 @@ describe(`${NodeConnection.name}`, () => {
271271
await serverSocket.stop({ force: true });
272272
await destroyP;
273273
});
274-
test('Should fail and destroy due to connection ending local', async () => {
274+
test('should fail and destroy due to connection ending local', async () => {
275275
const nodeConnection = await NodeConnection.createNodeConnection(
276276
{
277277
targetNodeIds: [serverNodeId],
@@ -297,7 +297,7 @@ describe(`${NodeConnection.name}`, () => {
297297
});
298298
await destroyP;
299299
});
300-
test('Should fail and destroy due to connection ending remote', async () => {
300+
test('should fail and destroy due to connection ending remote', async () => {
301301
const nodeConnection = await NodeConnection.createNodeConnection(
302302
{
303303
targetNodeIds: [serverNodeId],

0 commit comments

Comments
 (0)