Skip to content

Commit 15ea1fc

Browse files
committed
wip: EOD
1 parent 0c84744 commit 15ea1fc

21 files changed

Lines changed: 995 additions & 2272 deletions

src/PolykeyAgent.ts

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,12 @@ import * as workersUtils from './workers/utils';
4444
import TaskManager from './tasks/TaskManager';
4545
import { serverManifest as clientServerManifest } from './client/handlers';
4646
import { serverManifest as agentServerManifest } from './agent/handlers';
47+
import { webcrypto } from "crypto";
48+
import * as quicEvents from "@matrixai/quic/dist/events";
4749

4850
// TODO: clean this up
4951
type NetworkConfig = {
50-
forwardHost?: Host;
51-
forwardPort?: Port;
52-
proxyHost?: Host;
53-
proxyPort?: Port;
54-
// GRPCServer for agent service
52+
// RPCServer for agent service
5553
agentHost?: Host;
5654
agentPort?: Port;
5755
// RPCServer for client service
@@ -167,7 +165,7 @@ class PolykeyAgent {
167165
initialClosestNodes?: number;
168166
};
169167
networkConfig?: NetworkConfig;
170-
quicServerConfig: QUICServerConfig;
168+
quicServerConfig?: QUICServerConfig;
171169
seedNodes?: SeedNodes;
172170
workers?: number;
173171
status?: Status;
@@ -191,7 +189,7 @@ class PolykeyAgent {
191189
webSocketServerClient?: WebSocketServer;
192190
rpcServerAgent?: RPCServer;
193191
quicSocket?: QUICSocket;
194-
quicServerAgent: QUICServer;
192+
quicServerAgent?: QUICServer;
195193
fs?: FileSystem;
196194
logger?: Logger;
197195
fresh?: boolean;
@@ -362,24 +360,43 @@ class PolykeyAgent {
362360
keyRing,
363361
logger: logger.getChild(NodeGraph.name),
364362
}));
365-
// TODO:
363+
// TODO: This needs to be changed and moved to a utils file
366364
const quicOpts: QUICCrypto = {
367-
randomBytes(_data: ArrayBuffer): Promise<void> {
368-
return Promise.resolve(undefined);
365+
randomBytes: async (data: ArrayBuffer) => {
366+
const randomBytes = keysUtils.getRandomBytes(data.byteLength);
367+
const dataBuf = Buffer.from(data);
368+
// FIXME: is there a better way?
369+
dataBuf.write(randomBytes.toString('binary'), 'binary');
369370
},
370-
sign(_key: ArrayBuffer, _data: ArrayBuffer): Promise<ArrayBuffer> {
371-
return Promise.resolve(new ArrayBuffer(0));
371+
async sign(key: ArrayBuffer, data: ArrayBuffer) {
372+
const cryptoKey = await webcrypto.subtle.importKey(
373+
'raw',
374+
key,
375+
{
376+
name: 'HMAC',
377+
hash: 'SHA-256',
378+
},
379+
true,
380+
['sign', 'verify'],
381+
);
382+
return webcrypto.subtle.sign('HMAC', cryptoKey, data);
372383
},
373-
verify(
374-
_key: ArrayBuffer,
375-
_data: ArrayBuffer,
376-
_sig: ArrayBuffer,
377-
): Promise<boolean> {
378-
return Promise.resolve(false);
384+
async verify(key: ArrayBuffer, data: ArrayBuffer, sig: ArrayBuffer) {
385+
const cryptoKey = await webcrypto.subtle.importKey(
386+
'raw',
387+
key,
388+
{
389+
name: 'HMAC',
390+
hash: 'SHA-256',
391+
},
392+
true,
393+
['sign', 'verify'],
394+
);
395+
return webcrypto.subtle.verify('HMAC', cryptoKey, sig, data);
379396
},
380397
};
381398
const quicCrypto = {
382-
key: new ArrayBuffer(0),
399+
key: keysUtils.generateKey(),
383400
ops: quicOpts,
384401
};
385402
const resolveHostname = (host) => {
@@ -545,14 +562,15 @@ class PolykeyAgent {
545562
privKeyPem: tlsConfig.keyPrivatePem,
546563
certChainPem: tlsConfig.certChainPem,
547564
},
548-
verifyPeer: true,
565+
verifyPeer: false, // FIXME: false until custom verification logic
549566
...quicServerConfig,
567+
logKeys: 'tmp/key.log',
550568
},
551569
crypto: quicCrypto,
552570
logger: logger.getChild(QUICServer.name + 'Agent'),
553-
keepaliveIntervalTime: 0,
554-
maxReadableStreamBytes: 0,
555-
maxWritableStreamBytes: 0,
571+
// keepaliveIntervalTime: 0, TODO
572+
// maxReadableStreamBytes: 0,
573+
// maxWritableStreamBytes: 0,
556574
socket: quicSocket,
557575
resolveHostname,
558576
reasonToCode: utils.reasonToCode,
@@ -871,7 +889,38 @@ class PolykeyAgent {
871889
port: _networkConfig.agentPort,
872890
ipv6Only: false, // TODO: hardcode this?
873891
});
874-
// TODO: set up stream event handling here
892+
// Setting up stream handling
893+
const handleStream = async (event: quicEvents.QUICConnectionStreamEvent) => {
894+
// Streams are handled via the RPCServer.
895+
const stream = event.detail;
896+
this.logger.info('!!!!Handling new stream!!!!!');
897+
this.rpcServerAgent.handleStream(stream);
898+
};
899+
900+
const handleConnection = async (
901+
event: quicEvents.QUICServerConnectionEvent,
902+
) => {
903+
// Needs to setup stream handler
904+
const conn = event.detail;
905+
this.logger.info('!!!!Handling new Connection!!!!!');
906+
conn.addEventListener('stream', handleStream);
907+
conn.addEventListener(
908+
'destroy',
909+
() => {
910+
conn.removeEventListener('stream', handleStream);
911+
},
912+
{ once: true },
913+
);
914+
};
915+
this.quicServerAgent.addEventListener('connection', handleConnection);
916+
this.quicServerAgent.addEventListener(
917+
'stop',
918+
() => {
919+
this.quicServerAgent.removeEventListener('connection', handleConnection);
920+
},
921+
{ once: true },
922+
);
923+
// Finished setting up handling
875924
await this.quicServerAgent.start({
876925
host: _networkConfig.agentHost,
877926
port: _networkConfig.agentPort,

src/agent/handlers/clientManifest.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ const nodesClosestLocalNodesGet = new ServerCaller<
3535
AgentRPCResponseResult<NodeAddressMessage>
3636
>();
3737

38-
// TODO: still to be completed
3938
const nodesCrossSignClaim = new DuplexCaller<
40-
AgentRPCRequestParams<EchoMessage>,
41-
AgentRPCResponseResult<EchoMessage>
39+
AgentRPCRequestParams<AgentClaimMessage>,
40+
AgentRPCResponseResult<AgentClaimMessage>
4241
>();
4342

4443
// TODO: still to be completed

src/agent/handlers/nodesCrossSignClaim.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { EchoMessage } from './types';
1+
import type { AgentClaimMessage } from "./types";
22
import type { AgentRPCRequestParams, AgentRPCResponseResult } from '../types';
3-
import type KeyRing from '../../keys/KeyRing';
43
import type { NodeId } from '../../ids';
54
import type ACL from '../../acl/ACL';
65
import type NodeManager from '../../nodes/NodeManager';
@@ -11,19 +10,18 @@ import { DuplexHandler } from '../../rpc/handlers';
1110
// TODO: come back to this!
1211
class NodesCrossSignClaimHandler extends DuplexHandler<
1312
{
14-
keyRing: KeyRing;
1513
acl: ACL;
1614
nodeManager: NodeManager;
1715
},
18-
AgentRPCRequestParams<EchoMessage>,
19-
AgentRPCResponseResult<EchoMessage>
16+
AgentRPCRequestParams<AgentClaimMessage>,
17+
AgentRPCResponseResult<AgentClaimMessage>
2018
> {
2119
public async *handle(
22-
input: AsyncIterable<AgentRPCRequestParams<EchoMessage>>,
20+
input: AsyncIterableIterator<AgentRPCRequestParams<AgentClaimMessage>>,
2321
_,
2422
meta,
25-
): AsyncGenerator<AgentRPCResponseResult<EchoMessage>> {
26-
const { acl } = this.container;
23+
): AsyncGenerator<AgentRPCResponseResult<AgentClaimMessage>> {
24+
const { acl, nodeManager} = this.container;
2725
// TODO: get remote info from metadata. dependent on js-quic meta types
2826
const requestingNodeId: NodeId | undefined = nodesUtils.decodeNodeId(
2927
meta?.remoteNodeId,
@@ -35,7 +33,7 @@ class NodesCrossSignClaimHandler extends DuplexHandler<
3533
throw new nodesErrors.ErrorNodePermissionDenied();
3634
}
3735
// Handle claiming the node
38-
await nodeManager.handleClaimNode(requestingNodeId, genClaims);
36+
yield* nodeManager.handleClaimNode(requestingNodeId, input);
3937
}
4038
}
4139

src/agent/handlers/nodesHolePunchMessageSend.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,7 @@ class NodesHolePunchMessageSendHandler extends UnaryHandler<
9494
logger.debug(
9595
`Relaying signaling message from ${srcNodeId}@${proxyAddress.host}:${proxyAddress.port} to ${targetNodeId} with information ${proxyAddress}`,
9696
);
97-
// TODO: fix
98-
call.request.setProxyAddress(proxyAddress);
99-
await nodeConnectionManager.relaySignalingMessage(call.request, {
97+
await nodeConnectionManager.relaySignalingMessage(input, {
10098
host: connectionInfo!.remoteHost,
10199
port: connectionInfo!.remotePort,
102100
});

src/agent/handlers/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export type ClaimIdMessage = {
1111
claimIdEncoded: ClaimIdEncoded;
1212
};
1313

14-
export type AgentClaimMessage = ClaimIdMessage & {
14+
export type AgentClaimMessage = Partial<ClaimIdMessage> & {
1515
signedTokenEncoded: SignedTokenEncoded;
1616
};
1717

src/client/handlers/agentStatus.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type PolykeyAgent from '../../PolykeyAgent';
44
import * as nodesUtils from '../../nodes/utils';
55
import * as keysUtils from '../../keys/utils';
66
import { UnaryHandler } from '../../rpc/handlers';
7+
import { Host, Port } from "@/network/types";
78

89
class AgentStatusHandler extends UnaryHandler<
910
{
@@ -20,12 +21,8 @@ class AgentStatusHandler extends UnaryHandler<
2021
nodeIdEncoded: nodesUtils.encodeNodeId(pkAgent.keyRing.getNodeId()),
2122
clientHost: pkAgent.webSocketServerClient.getHost(),
2223
clientPort: pkAgent.webSocketServerClient.getPort(),
23-
proxyHost: pkAgent.proxy.getProxyHost(),
24-
proxyPort: pkAgent.proxy.getProxyPort(),
25-
agentHost: pkAgent.grpcServerAgent.getHost(),
26-
agentPort: pkAgent.grpcServerAgent.getPort(),
27-
forwardHost: pkAgent.proxy.getForwardHost(),
28-
forwardPort: pkAgent.proxy.getForwardPort(),
24+
agentHost: pkAgent.quicSocket.host as unknown as Host,
25+
agentPort: pkAgent.quicSocket.port as unknown as Port,
2926
publicKeyJwk: keysUtils.publicKeyToJWK(pkAgent.keyRing.keyPair.publicKey),
3027
certChainPEM: await pkAgent.certManager.getCertPEMsChainPEM(),
3128
};

src/client/handlers/types.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@ export type StatusResultMessage = {
1919
PublicKeyMessage & {
2020
clientHost: Host;
2121
clientPort: Port;
22-
proxyHost: Host;
23-
proxyPort: Port;
2422
agentHost: Host;
2523
agentPort: Port;
26-
forwardHost: Host;
27-
forwardPort: Port;
2824
certChainPEM: CertificatePEMChain;
2925
};
3026

src/nodes/NodeConnectionManager.ts

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {
1414
import type NodeManager from './NodeManager';
1515
import type { PromiseCancellable } from '@matrixai/async-cancellable';
1616
import type { MultiLockRequest } from '@matrixai/async-locks/dist/types';
17-
import type * as nodesPB from '../proto/js/polykey/v1/nodes/nodes_pb';
1817
import type { QUICClientConfig } from './types';
1918
import { withF } from '@matrixai/resources';
2019
import Logger from '@matrixai/logger';
@@ -30,6 +29,7 @@ import * as validationUtils from '../validation/utils';
3029
import * as networkUtils from '../network/utils';
3130
import { never } from '../utils';
3231
import { clientManifest as agentClientManifest } from '../agent/handlers/clientManifest';
32+
import { HolePunchRelayMessage } from "../agent/handlers/types";
3333

3434
// TODO: check all locking and add cancellation for it.
3535

@@ -775,39 +775,39 @@ class NodeConnectionManager {
775775
): Promise<Array<[NodeId, NodeData]>> {
776776
try {
777777
// Send through client
778-
const response = await this.withConnF(
778+
return await this.withConnF(
779779
nodeId,
780780
async (connection) => {
781781
const client = connection.getClient();
782-
return await client.methods.nodesClosestLocalNodesGet(
782+
const closestNodes = await client.methods.nodesClosestLocalNodesGet(
783783
{ nodeIdEncoded: nodesUtils.encodeNodeId(targetNodeId) },
784784
ctx,
785785
);
786+
const localNodeId = this.keyRing.getNodeId();
787+
const nodes: Array<[NodeId, NodeData]> = [];
788+
for await (const result of closestNodes) {
789+
const nodeId = nodesUtils.decodeNodeId(result.nodeIdEncoded);
790+
// If the nodeId is not valid we don't add it to the list of nodes
791+
// Our own nodeId is considered not valid here
792+
if (nodeId != null && !localNodeId.equals(nodeId)) {
793+
nodes.push([
794+
nodeId,
795+
{
796+
address: {
797+
host: result.host as Host | Hostname,
798+
port: result.port as Port,
799+
},
800+
// Not really needed
801+
// But if it's needed then we need to add the information to the proto definition
802+
lastUpdated: 0,
803+
},
804+
]);
805+
}
806+
}
807+
return nodes;
786808
},
787809
ctx,
788810
);
789-
const localNodeId = this.keyRing.getNodeId();
790-
const nodes: Array<[NodeId, NodeData]> = [];
791-
for await (const result of response) {
792-
const nodeId = nodesUtils.decodeNodeId(result.nodeIdEncoded);
793-
// If the nodeId is not valid we don't add it to the list of nodes
794-
// Our own nodeId is considered not valid here
795-
if (nodeId != null && !localNodeId.equals(nodeId)) {
796-
nodes.push([
797-
nodeId,
798-
{
799-
address: {
800-
host: result.host as Host | Hostname,
801-
port: result.port as Port,
802-
},
803-
// Not really needed
804-
// But if it's needed then we need to add the information to the proto definition
805-
lastUpdated: 0,
806-
},
807-
]);
808-
}
809-
}
810-
return nodes;
811811
} catch (e) {
812812
if (nodesUtils.isConnectionError(e)) {
813813
return [];
@@ -893,7 +893,7 @@ class NodeConnectionManager {
893893
* @param ctx
894894
*/
895895
public relaySignalingMessage(
896-
message: nodesPB.Relay,
896+
message: HolePunchRelayMessage,
897897
sourceAddress: NodeAddress,
898898
ctx?: Partial<ContextTimed>,
899899
): PromiseCancellable<void>;
@@ -904,18 +904,18 @@ class NodeConnectionManager {
904904
nodeConnectionManager.connConnectTime,
905905
)
906906
public async relaySignalingMessage(
907-
message: nodesPB.Relay,
907+
message: HolePunchRelayMessage,
908908
sourceAddress: NodeAddress,
909909
@context ctx: ContextTimed,
910910
): Promise<void> {
911911
// First check if we already have an existing ID -> address record
912912
// If we're relaying then we trust our own node graph records over
913913
// what was provided in the message
914-
const sourceNode = validationUtils.parseNodeId(message.getSrcId());
914+
const sourceNode = validationUtils.parseNodeId(message.srcIdEncoded);
915915
await this.sendSignalingMessage(
916-
validationUtils.parseNodeId(message.getTargetId()),
916+
validationUtils.parseNodeId(message.dstIdEncoded),
917917
sourceNode,
918-
validationUtils.parseNodeId(message.getTargetId()),
918+
validationUtils.parseNodeId(message.dstIdEncoded),
919919
sourceAddress,
920920
ctx,
921921
);

0 commit comments

Comments
 (0)