Skip to content

Commit 921624d

Browse files
authored
Merge pull request #584 from MatrixAI/feature-local-discovery
Local Polykey Node Discovery
2 parents 68b7649 + e698dfd commit 921624d

28 files changed

+824
-113
lines changed

package-lock.json

Lines changed: 51 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"@matrixai/events": "^3.2.3",
7575
"@matrixai/id": "^3.3.6",
7676
"@matrixai/logger": "^3.1.0",
77+
"@matrixai/mdns": "^1.2.0",
7778
"@matrixai/quic": "^1.0.0",
7879
"@matrixai/resources": "^1.1.5",
7980
"@matrixai/rpc": "^0.2.4",

src/PolykeyAgent.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import path from 'path';
77
import process from 'process';
88
import Logger from '@matrixai/logger';
99
import { DB } from '@matrixai/db';
10+
import { MDNS } from '@matrixai/mdns';
1011
import {
1112
CreateDestroyStartStop,
1213
ready,
@@ -83,6 +84,10 @@ type PolykeyAgentOptions = {
8384
rpcCallTimeoutTime: number;
8485
rpcParserBufferSize: number;
8586
};
87+
mdns: {
88+
groups: Array<string>;
89+
port: number;
90+
};
8691
};
8792

8893
interface PolykeyAgent extends CreateDestroyStartStop {}
@@ -167,6 +172,10 @@ class PolykeyAgent {
167172
connectionHolePunchIntervalTime:
168173
config.defaultsSystem.nodesConnectionHolePunchIntervalTime,
169174
},
175+
mdns: {
176+
groups: config.defaultsSystem.mdnsGroups,
177+
port: config.defaultsSystem.mdnsPort,
178+
},
170179
});
171180
// This can only happen if the caller didn't specify the node path and the
172181
// automatic detection failed
@@ -201,6 +210,7 @@ class PolykeyAgent {
201210
let gestaltGraph: GestaltGraph | undefined;
202211
let identitiesManager: IdentitiesManager | undefined;
203212
let nodeGraph: NodeGraph | undefined;
213+
let mdns: MDNS | undefined;
204214
let nodeConnectionManager: NodeConnectionManager | undefined;
205215
let nodeManager: NodeManager | undefined;
206216
let discovery: Discovery | undefined;
@@ -316,13 +326,23 @@ class PolykeyAgent {
316326
keyRing,
317327
logger: logger.getChild(NodeGraph.name),
318328
});
329+
mdns = new MDNS({
330+
logger: logger.getChild(MDNS.name),
331+
});
332+
await mdns.start({
333+
id: keyRing.getNodeId().toBuffer().readUint16BE(),
334+
hostname: nodesUtils.encodeNodeId(keyRing.getNodeId()),
335+
groups: optionsDefaulted.mdns.groups,
336+
port: optionsDefaulted.mdns.port,
337+
});
319338
// Remove your own node ID if provided as a seed node
320339
const nodeIdOwnEncoded = nodesUtils.encodeNodeId(keyRing.getNodeId());
321340
delete optionsDefaulted.seedNodes[nodeIdOwnEncoded];
322341
nodeConnectionManager = new NodeConnectionManager({
323342
keyRing,
324343
nodeGraph,
325344
tlsConfig,
345+
mdns,
326346
seedNodes: optionsDefaulted.seedNodes,
327347
connectionFindConcurrencyLimit:
328348
optionsDefaulted.nodes.connectionFindConcurrencyLimit,
@@ -426,6 +446,7 @@ class PolykeyAgent {
426446
await discovery?.stop();
427447
await identitiesManager?.stop();
428448
await gestaltGraph?.stop();
449+
await mdns?.stop();
429450
await acl?.stop();
430451
await sigchain?.stop();
431452
await certManager?.stop();
@@ -448,6 +469,7 @@ class PolykeyAgent {
448469
acl,
449470
gestaltGraph,
450471
nodeGraph,
472+
mdns,
451473
taskManager,
452474
nodeConnectionManager,
453475
nodeManager,
@@ -486,6 +508,7 @@ class PolykeyAgent {
486508
public readonly acl: ACL;
487509
public readonly gestaltGraph: GestaltGraph;
488510
public readonly nodeGraph: NodeGraph;
511+
public readonly mdns: MDNS;
489512
public readonly taskManager: TaskManager;
490513
public readonly nodeConnectionManager: NodeConnectionManager;
491514
public readonly nodeManager: NodeManager;
@@ -530,6 +553,7 @@ class PolykeyAgent {
530553
acl,
531554
gestaltGraph,
532555
nodeGraph,
556+
mdns,
533557
taskManager,
534558
nodeConnectionManager,
535559
nodeManager,
@@ -552,6 +576,7 @@ class PolykeyAgent {
552576
acl: ACL;
553577
gestaltGraph: GestaltGraph;
554578
nodeGraph: NodeGraph;
579+
mdns: MDNS;
555580
taskManager: TaskManager;
556581
nodeConnectionManager: NodeConnectionManager;
557582
nodeManager: NodeManager;
@@ -576,6 +601,7 @@ class PolykeyAgent {
576601
this.gestaltGraph = gestaltGraph;
577602
this.discovery = discovery;
578603
this.nodeGraph = nodeGraph;
604+
this.mdns = mdns;
579605
this.taskManager = taskManager;
580606
this.nodeConnectionManager = nodeConnectionManager;
581607
this.nodeManager = nodeManager;
@@ -624,6 +650,10 @@ class PolykeyAgent {
624650
| { recoveryCode: string }
625651
| { privateKey: Buffer }
626652
| { privateKeyPath: string };
653+
mdns: {
654+
groups: Array<string>;
655+
port: number;
656+
};
627657
}>;
628658
workers?: number;
629659
fresh?: boolean;
@@ -637,6 +667,10 @@ class PolykeyAgent {
637667
agentServicePort: config.defaultsUser.agentServicePort,
638668
workers: config.defaultsUser.workers,
639669
ipv6Only: config.defaultsUser.ipv6Only,
670+
mdns: {
671+
groups: config.defaultsSystem.mdnsGroups,
672+
port: config.defaultsSystem.mdnsPort,
673+
},
640674
});
641675
// Register event handlers
642676
this.certManager.addEventListener(
@@ -706,6 +740,12 @@ class PolykeyAgent {
706740
host: optionsDefaulted.clientServiceHost,
707741
port: optionsDefaulted.clientServicePort,
708742
});
743+
await this.mdns.start({
744+
id: this.keyRing.getNodeId().toBuffer().readUint16BE(),
745+
hostname: nodesUtils.encodeNodeId(this.keyRing.getNodeId()),
746+
groups: optionsDefaulted.mdns.groups,
747+
port: optionsDefaulted.mdns.port,
748+
});
709749
await this.nodeManager.start();
710750
await this.nodeConnectionManager.start({
711751
host: optionsDefaulted.agentServiceHost,
@@ -768,6 +808,7 @@ class PolykeyAgent {
768808
await this.vaultManager?.stop();
769809
await this.discovery?.stop();
770810
await this.nodeGraph?.stop();
811+
await this.mdns?.stop();
771812
await this.nodeConnectionManager?.stop();
772813
await this.nodeManager?.stop();
773814
await this.clientService.stop({ force: true });
@@ -810,6 +851,7 @@ class PolykeyAgent {
810851
await this.clientService.stop({ force: true });
811852
await this.identitiesManager.stop();
812853
await this.gestaltGraph.stop();
854+
await this.mdns.stop();
813855
await this.acl.stop();
814856
await this.sigchain.stop();
815857
await this.certManager.stop();

src/client/handlers/NodesAdd.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ class NodesAdd extends UnaryHandler<
5353
// Pinging to authenticate the node
5454
if (
5555
(input.ping ?? false) &&
56-
!(await nodeManager.pingNode(nodeId, { host, port }))
56+
!(await nodeManager.pingNode(nodeId, [
57+
{ host, port, scopes: ['external'] },
58+
]))
5759
) {
5860
throw new nodeErrors.ErrorNodePingFailed(
5961
'Failed to authenticate target node',

src/client/handlers/NodesFind.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type {
2-
AddressMessage,
32
ClientRPCRequestParams,
43
ClientRPCResponseResult,
54
NodeIdMessage,
5+
NodesFindMessage,
66
} from '../types';
77
import type { NodeId } from '../../ids';
88
import type NodeConnectionManager from '../../nodes/NodeConnectionManager';
@@ -17,11 +17,11 @@ class NodesFind extends UnaryHandler<
1717
nodeConnectionManager: NodeConnectionManager;
1818
},
1919
ClientRPCRequestParams<NodeIdMessage>,
20-
ClientRPCResponseResult<AddressMessage>
20+
ClientRPCResponseResult<NodesFindMessage>
2121
> {
2222
public handle = async (
2323
input: ClientRPCRequestParams<NodeIdMessage>,
24-
): Promise<ClientRPCResponseResult<AddressMessage>> => {
24+
): Promise<ClientRPCResponseResult<NodesFindMessage>> => {
2525
const { nodeConnectionManager } = this.container;
2626

2727
const {
@@ -39,13 +39,12 @@ class NodesFind extends UnaryHandler<
3939
nodeId: input.nodeIdEncoded,
4040
},
4141
);
42-
const address = await nodeConnectionManager.findNode(nodeId);
43-
if (address == null) throw new nodesErrors.ErrorNodeGraphNodeIdNotFound();
42+
const addresses = await nodeConnectionManager.findNodeAll(nodeId);
43+
if (addresses.length === 0) {
44+
throw new nodesErrors.ErrorNodeGraphNodeIdNotFound();
45+
}
4446

45-
return {
46-
host: address.host,
47-
port: address.port,
48-
};
47+
return { addresses };
4948
};
5049
}
5150

src/client/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ type AddressMessage = {
109109

110110
type NodeAddressMessage = NodeIdMessage & AddressMessage;
111111

112+
type NodesFindMessage = {
113+
addresses: Array<AddressMessage>;
114+
};
115+
112116
type NodesGetMessage = NodeAddressMessage & { bucketIndex: number };
113117

114118
type NodesAddMessage = NodeAddressMessage & {
@@ -327,6 +331,7 @@ export type {
327331
NodeIdMessage,
328332
AddressMessage,
329333
NodeAddressMessage,
334+
NodesFindMessage,
330335
NodeConnectionMessage,
331336
ActionsListMessage,
332337
SetIdentityActionMessage,

src/config.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ const testnet: Record<string, NodeAddress> = {
1313
v7v9ptvcdbdf8p4upok3prpmu3938ns8v4g45dib7sm5hqvvehv70: {
1414
host: 'testnet.polykey.com' as Host,
1515
port: 1314 as Port,
16+
scopes: ['external'],
1617
},
1718
v270ktdd3cs3mp1r3q3dkmick92bn927mii9or4sgroeogd1peqb0: {
1819
host: 'testnet.polykey.com' as Host,
1920
port: 1314 as Port,
21+
scopes: ['external'],
2022
},
2123
};
2224

@@ -246,6 +248,25 @@ const config = {
246248
* Interval for hole punching reverse node connections.
247249
*/
248250
nodesConnectionHolePunchIntervalTime: 1_000, // 1 second
251+
/**
252+
* Multicast group addresses that the MDNS stack will operate on.
253+
*
254+
* These values are well-known, and hence must not be changed by the user.
255+
*
256+
* The default values of these groups must start with either `224.0` (IPv4) or `ff02` (IPv6).
257+
* The default values of `224.0.0.250` and `ff02::fa17` have been selected due to
258+
* the resemblance of `fa17` to the latin word `fait`, and `250` being the decimal representation of that.
259+
*/
260+
mdnsGroups: ['224.0.0.250', 'ff02::fa17'],
261+
/**
262+
* The port that the MDNS stack will operate on.
263+
*
264+
* This is well-known, and hence must not be changed by the user.
265+
*
266+
* The default value has been selected as the decimal decimal representation of `fa17`,
267+
* which resembles the latin word `fait`.
268+
*/
269+
mdnsPort: 64023,
249270
},
250271
/**
251272
* Default user configuration.

0 commit comments

Comments
 (0)