@dxos/messaging 0.6.8-main.3be982f → 0.6.8-staging.63bcb81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +466 -199
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +456 -197
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/types/src/messenger.blueprint-test.d.ts +4 -0
- package/dist/types/src/messenger.blueprint-test.d.ts.map +1 -0
- package/dist/types/src/messenger.d.ts +4 -10
- package/dist/types/src/messenger.d.ts.map +1 -1
- package/dist/types/src/signal-client/signal-client.d.ts +6 -10
- package/dist/types/src/signal-client/signal-client.d.ts.map +1 -1
- package/dist/types/src/signal-client/signal-local-state.d.ts +2 -10
- package/dist/types/src/signal-client/signal-local-state.d.ts.map +1 -1
- package/dist/types/src/signal-manager/edge-signal-manager.d.ts +18 -19
- package/dist/types/src/signal-manager/edge-signal-manager.d.ts.map +1 -1
- package/dist/types/src/signal-manager/index.d.ts +1 -0
- package/dist/types/src/signal-manager/index.d.ts.map +1 -1
- package/dist/types/src/signal-manager/memory-signal-manager.d.ts +14 -25
- package/dist/types/src/signal-manager/memory-signal-manager.d.ts.map +1 -1
- package/dist/types/src/signal-manager/signal-manager.d.ts +5 -6
- package/dist/types/src/signal-manager/signal-manager.d.ts.map +1 -1
- package/dist/types/src/signal-manager/websocket-signal-manager.d.ts +14 -29
- package/dist/types/src/signal-manager/websocket-signal-manager.d.ts.map +1 -1
- package/dist/types/src/signal-methods.d.ts +29 -14
- package/dist/types/src/signal-methods.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +5 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/test-builder.d.ts +19 -0
- package/dist/types/src/testing/test-builder.d.ts.map +1 -0
- package/dist/types/src/testing/test-messages.d.ts +6 -0
- package/dist/types/src/testing/test-messages.d.ts.map +1 -0
- package/dist/types/src/testing/test-peer.d.ts +23 -0
- package/dist/types/src/testing/test-peer.d.ts.map +1 -0
- package/dist/types/src/testing/utils.d.ts +10 -0
- package/dist/types/src/testing/utils.d.ts.map +1 -0
- package/package.json +15 -14
- package/src/messenger.blueprint-test.ts +346 -0
- package/src/messenger.test.ts +26 -362
- package/src/messenger.ts +20 -18
- package/src/signal-client/signal-client-monitor.ts +3 -3
- package/src/signal-client/signal-client.test.ts +56 -52
- package/src/signal-client/signal-client.ts +30 -16
- package/src/signal-client/signal-local-state.ts +28 -10
- package/src/signal-manager/edge-signal-manager.test.ts +31 -35
- package/src/signal-manager/edge-signal-manager.ts +88 -36
- package/src/signal-manager/index.ts +1 -0
- package/src/signal-manager/memory-signal-manager.ts +36 -50
- package/src/signal-manager/signal-manager.ts +5 -7
- package/src/signal-manager/websocket-signal-manager.test.ts +27 -31
- package/src/signal-manager/websocket-signal-manager.ts +34 -65
- package/src/signal-methods.ts +33 -11
- package/src/testing/index.ts +8 -0
- package/src/testing/test-builder.ts +54 -0
- package/src/testing/test-messages.ts +24 -0
- package/src/testing/test-peer.ts +66 -0
- package/src/testing/utils.ts +50 -0
- package/dist/types/src/testing.d.ts +0 -40
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/testing.ts +0 -120
|
@@ -2,85 +2,115 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { AnySchema } from '@bufbuild/protobuf/wkt';
|
|
6
|
+
|
|
5
7
|
import { Event } from '@dxos/async';
|
|
6
8
|
import { Resource } from '@dxos/context';
|
|
7
|
-
import {
|
|
9
|
+
import { type EdgeConnection, protocol } from '@dxos/edge-client';
|
|
8
10
|
import { invariant } from '@dxos/invariant';
|
|
9
11
|
import { PublicKey } from '@dxos/keys';
|
|
10
12
|
import { log } from '@dxos/log';
|
|
13
|
+
import { EdgeService } from '@dxos/protocols';
|
|
11
14
|
import {
|
|
12
15
|
SwarmRequestSchema,
|
|
13
16
|
SwarmRequest_Action as SwarmRequestAction,
|
|
14
17
|
SwarmResponseSchema,
|
|
15
18
|
type Message as EdgeMessage,
|
|
16
19
|
} from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
17
|
-
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
18
20
|
import { ComplexMap, ComplexSet } from '@dxos/util';
|
|
19
21
|
|
|
20
|
-
import { type
|
|
22
|
+
import { type SignalManager } from './signal-manager';
|
|
23
|
+
import { type PeerInfo, type Message, type SwarmEvent, PeerInfoHash } from '../signal-methods';
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
public swarmEvent = new Event<{ topic: PublicKey; swarmEvent: SwarmEvent }>();
|
|
25
|
+
export class EdgeSignalManager extends Resource implements SignalManager {
|
|
26
|
+
public swarmEvent = new Event<SwarmEvent>();
|
|
25
27
|
public onMessage = new Event<Message>();
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
|
-
* swarm key ->
|
|
30
|
+
* swarm key -> peerKeys in the swarm
|
|
29
31
|
*/
|
|
30
32
|
// TODO(mykola): This class should not contain swarm state. Temporary before network-manager API changes to accept list of peers.
|
|
31
|
-
private readonly _swarmPeers = new ComplexMap<PublicKey, ComplexSet<
|
|
32
|
-
private readonly
|
|
33
|
+
private readonly _swarmPeers = new ComplexMap<PublicKey, ComplexSet<PeerInfo>>(PublicKey.hash);
|
|
34
|
+
private readonly _edgeConnection: EdgeConnection;
|
|
33
35
|
|
|
34
|
-
constructor({
|
|
36
|
+
constructor({ edgeConnection }: { edgeConnection: EdgeConnection }) {
|
|
35
37
|
super();
|
|
36
|
-
this.
|
|
38
|
+
this._edgeConnection = edgeConnection;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
protected override async _open() {
|
|
40
|
-
this._ctx.onDispose(this.
|
|
42
|
+
this._ctx.onDispose(this._edgeConnection.addListener((message) => this._onMessage(message)));
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
/**
|
|
44
|
-
* Warning:
|
|
46
|
+
* Warning: PeerInfo is inferred from edgeConnection.
|
|
45
47
|
*/
|
|
46
|
-
async join({ topic }: { topic: PublicKey;
|
|
47
|
-
this.
|
|
48
|
-
|
|
48
|
+
async join({ topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
|
|
49
|
+
if (!this._matchSelfPeerInfo(peer)) {
|
|
50
|
+
// NOTE: Could only join swarm with the same peer info as the edge connection.
|
|
51
|
+
log.warn('ignoring peer info on join request', {
|
|
52
|
+
peer,
|
|
53
|
+
expected: {
|
|
54
|
+
peerKey: this._edgeConnection.deviceKey.toHex(),
|
|
55
|
+
identityKey: this._edgeConnection.identityKey.toHex(),
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this._swarmPeers.set(topic, new ComplexSet<PeerInfo>(PeerInfoHash));
|
|
61
|
+
await this._edgeConnection.send(
|
|
49
62
|
protocol.createMessage(SwarmRequestSchema, {
|
|
50
|
-
serviceId: SWARM_SERVICE_ID,
|
|
63
|
+
serviceId: EdgeService.SWARM_SERVICE_ID,
|
|
51
64
|
payload: { action: SwarmRequestAction.JOIN, swarmKeys: [topic.toHex()] },
|
|
52
65
|
}),
|
|
53
66
|
);
|
|
54
67
|
}
|
|
55
68
|
|
|
56
|
-
async leave({ topic }: { topic: PublicKey;
|
|
69
|
+
async leave({ topic, peer }: { topic: PublicKey; peer: PeerInfo }): Promise<void> {
|
|
57
70
|
this._swarmPeers.delete(topic);
|
|
58
|
-
await this.
|
|
71
|
+
await this._edgeConnection.send(
|
|
59
72
|
protocol.createMessage(SwarmRequestSchema, {
|
|
60
|
-
serviceId: SWARM_SERVICE_ID,
|
|
73
|
+
serviceId: EdgeService.SWARM_SERVICE_ID,
|
|
61
74
|
payload: { action: SwarmRequestAction.LEAVE, swarmKeys: [topic.toHex()] },
|
|
62
75
|
}),
|
|
63
76
|
);
|
|
64
77
|
}
|
|
65
78
|
|
|
66
79
|
async sendMessage(message: Message): Promise<void> {
|
|
67
|
-
|
|
80
|
+
if (!this._matchSelfPeerInfo(message.author)) {
|
|
81
|
+
// NOTE: Could only join swarm with the same peer info as the edge connection.
|
|
82
|
+
log.warn('ignoring author on send request', {
|
|
83
|
+
author: message.author,
|
|
84
|
+
expected: { peerKey: this._edgeConnection.deviceKey, identityKey: this._edgeConnection.identityKey },
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await this._edgeConnection.send(
|
|
89
|
+
protocol.createMessage(AnySchema, {
|
|
90
|
+
serviceId: EdgeService.SIGNAL_SERVICE_ID,
|
|
91
|
+
source: message.author,
|
|
92
|
+
target: [message.recipient],
|
|
93
|
+
payload: { typeUrl: message.payload.type_url, value: message.payload.value },
|
|
94
|
+
}),
|
|
95
|
+
);
|
|
68
96
|
}
|
|
69
97
|
|
|
70
|
-
async subscribeMessages(
|
|
71
|
-
|
|
98
|
+
async subscribeMessages(peerInfo: PeerInfo): Promise<void> {
|
|
99
|
+
// No-op.
|
|
72
100
|
}
|
|
73
101
|
|
|
74
|
-
async unsubscribeMessages(
|
|
75
|
-
|
|
102
|
+
async unsubscribeMessages(peerInfo: PeerInfo): Promise<void> {
|
|
103
|
+
// No-op.
|
|
76
104
|
}
|
|
77
105
|
|
|
78
106
|
private _onMessage(message: EdgeMessage) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
switch (type) {
|
|
82
|
-
case SwarmResponseSchema.typeName: {
|
|
107
|
+
switch (message.serviceId) {
|
|
108
|
+
case EdgeService.SWARM_SERVICE_ID: {
|
|
83
109
|
this._processSwarmResponse(message);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case EdgeService.SIGNAL_SERVICE_ID: {
|
|
113
|
+
this._processMessage(message);
|
|
84
114
|
}
|
|
85
115
|
}
|
|
86
116
|
}
|
|
@@ -95,10 +125,7 @@ export class EdgeSignal extends Resource implements SignalMethods {
|
|
|
95
125
|
}
|
|
96
126
|
const oldPeers = this._swarmPeers.get(topic)!;
|
|
97
127
|
const timestamp = new Date(Date.parse(message.timestamp));
|
|
98
|
-
const newPeers = new ComplexSet<
|
|
99
|
-
PublicKey.hash,
|
|
100
|
-
payload.peers.map(({ peerKey }) => PublicKey.from(peerKey)),
|
|
101
|
-
);
|
|
128
|
+
const newPeers = new ComplexSet<PeerInfo>(PeerInfoHash, payload.peers);
|
|
102
129
|
|
|
103
130
|
// Emit new available peers in the swarm.
|
|
104
131
|
for (const peer of newPeers) {
|
|
@@ -107,21 +134,46 @@ export class EdgeSignal extends Resource implements SignalMethods {
|
|
|
107
134
|
}
|
|
108
135
|
this.swarmEvent.emit({
|
|
109
136
|
topic,
|
|
110
|
-
|
|
137
|
+
peerAvailable: { peer, since: timestamp },
|
|
111
138
|
});
|
|
112
139
|
}
|
|
113
140
|
|
|
114
141
|
// Emit peer that left the swarm.
|
|
115
|
-
for (const peer of oldPeers
|
|
142
|
+
for (const peer of oldPeers) {
|
|
116
143
|
if (newPeers.has(peer)) {
|
|
117
144
|
continue;
|
|
118
145
|
}
|
|
119
146
|
this.swarmEvent.emit({
|
|
120
147
|
topic,
|
|
121
|
-
|
|
148
|
+
peerLeft: { peer },
|
|
122
149
|
});
|
|
123
150
|
}
|
|
124
151
|
|
|
125
152
|
this._swarmPeers.set(topic, newPeers);
|
|
126
153
|
}
|
|
154
|
+
|
|
155
|
+
private _processMessage(message: EdgeMessage) {
|
|
156
|
+
invariant(protocol.getPayloadType(message) === AnySchema.typeName, 'Wrong payload type');
|
|
157
|
+
const payload = protocol.getPayload(message, AnySchema);
|
|
158
|
+
invariant(message.source, 'source is missing');
|
|
159
|
+
invariant(message.target, 'target is missing');
|
|
160
|
+
invariant(message.target.length === 1, 'target should have exactly one item');
|
|
161
|
+
|
|
162
|
+
this.onMessage.emit({
|
|
163
|
+
author: message.source,
|
|
164
|
+
recipient: message.target[0],
|
|
165
|
+
payload: {
|
|
166
|
+
type_url: payload.typeUrl,
|
|
167
|
+
value: payload.value,
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private _matchSelfPeerInfo(peer: PeerInfo) {
|
|
173
|
+
return (
|
|
174
|
+
peer &&
|
|
175
|
+
(peer.peerKey === this._edgeConnection.deviceKey.toHex() ||
|
|
176
|
+
peer.identityKey === this._edgeConnection.identityKey.toHex())
|
|
177
|
+
);
|
|
178
|
+
}
|
|
127
179
|
}
|
|
@@ -9,27 +9,23 @@ import { invariant } from '@dxos/invariant';
|
|
|
9
9
|
import { PublicKey } from '@dxos/keys';
|
|
10
10
|
import { log } from '@dxos/log';
|
|
11
11
|
import { schema } from '@dxos/protocols';
|
|
12
|
-
import { type SwarmEvent } from '@dxos/protocols/proto/dxos/mesh/signal';
|
|
13
12
|
import { ComplexMap, ComplexSet } from '@dxos/util';
|
|
14
13
|
|
|
15
14
|
import { type SignalManager } from './signal-manager';
|
|
16
|
-
import { type SignalStatus } from '../signal-methods';
|
|
15
|
+
import { type SwarmEvent, type PeerInfo, type SignalStatus, type Message, PeerInfoHash } from '../signal-methods';
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* Common signaling context that connects multiple MemorySignalManager instances.
|
|
20
19
|
*/
|
|
21
20
|
export class MemorySignalManagerContext {
|
|
22
21
|
// Swarm messages.
|
|
23
|
-
readonly swarmEvent = new Event<
|
|
24
|
-
topic: PublicKey;
|
|
25
|
-
swarmEvent: SwarmEvent;
|
|
26
|
-
}>();
|
|
22
|
+
readonly swarmEvent = new Event<SwarmEvent>();
|
|
27
23
|
|
|
28
24
|
// Mapping from topic to set of peers.
|
|
29
|
-
readonly swarms = new ComplexMap<PublicKey, ComplexSet<
|
|
25
|
+
readonly swarms = new ComplexMap<PublicKey, ComplexSet<PeerInfo>>(PublicKey.hash);
|
|
30
26
|
|
|
31
27
|
// Map of connections for each peer for signaling.
|
|
32
|
-
readonly connections = new ComplexMap<
|
|
28
|
+
readonly connections = new ComplexMap<PeerInfo, MemorySignalManager>(PeerInfoHash);
|
|
33
29
|
}
|
|
34
30
|
|
|
35
31
|
/**
|
|
@@ -37,20 +33,13 @@ export class MemorySignalManagerContext {
|
|
|
37
33
|
*/
|
|
38
34
|
export class MemorySignalManager implements SignalManager {
|
|
39
35
|
readonly statusChanged = new Event<SignalStatus[]>();
|
|
40
|
-
readonly swarmEvent = new Event<
|
|
41
|
-
topic: PublicKey;
|
|
42
|
-
swarmEvent: SwarmEvent;
|
|
43
|
-
}>();
|
|
36
|
+
readonly swarmEvent = new Event<SwarmEvent>();
|
|
44
37
|
|
|
45
|
-
readonly onMessage = new Event<
|
|
46
|
-
author: PublicKey;
|
|
47
|
-
recipient: PublicKey;
|
|
48
|
-
payload: Any;
|
|
49
|
-
}>();
|
|
38
|
+
readonly onMessage = new Event<Message>();
|
|
50
39
|
|
|
51
40
|
/** Will be used to emit SwarmEvents on .open() and .close() */
|
|
52
|
-
private _joinedSwarms = new ComplexSet<{ topic: PublicKey;
|
|
53
|
-
({ topic,
|
|
41
|
+
private _joinedSwarms = new ComplexSet<{ topic: PublicKey; peer: PeerInfo }>(
|
|
42
|
+
({ topic, peer }) => topic.toHex() + peer.peerKey,
|
|
54
43
|
);
|
|
55
44
|
|
|
56
45
|
private _ctx!: Context;
|
|
@@ -79,8 +68,8 @@ export class MemorySignalManager implements SignalManager {
|
|
|
79
68
|
return;
|
|
80
69
|
}
|
|
81
70
|
// save copy of joined swarms.
|
|
82
|
-
const joinedSwarmsCopy = new ComplexSet<{ topic: PublicKey;
|
|
83
|
-
({ topic,
|
|
71
|
+
const joinedSwarmsCopy = new ComplexSet<{ topic: PublicKey; peer: PeerInfo }>(
|
|
72
|
+
({ topic, peer }) => topic.toHex() + peer.peerKey,
|
|
84
73
|
[...this._joinedSwarms.values()],
|
|
85
74
|
);
|
|
86
75
|
|
|
@@ -96,63 +85,60 @@ export class MemorySignalManager implements SignalManager {
|
|
|
96
85
|
return [];
|
|
97
86
|
}
|
|
98
87
|
|
|
99
|
-
async join({ topic,
|
|
88
|
+
async join({ topic, peer }: { topic: PublicKey; peer: PeerInfo }) {
|
|
100
89
|
invariant(!this._ctx.disposed, 'Closed');
|
|
101
90
|
|
|
102
|
-
this._joinedSwarms.add({ topic,
|
|
91
|
+
this._joinedSwarms.add({ topic, peer });
|
|
103
92
|
|
|
104
93
|
if (!this._context.swarms.has(topic)) {
|
|
105
|
-
this._context.swarms.set(topic, new ComplexSet(
|
|
94
|
+
this._context.swarms.set(topic, new ComplexSet(PeerInfoHash));
|
|
106
95
|
}
|
|
107
96
|
|
|
108
|
-
this._context.swarms.get(topic)!.add(
|
|
97
|
+
this._context.swarms.get(topic)!.add(peer);
|
|
109
98
|
this._context.swarmEvent.emit({
|
|
110
99
|
topic,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
since: new Date(),
|
|
115
|
-
},
|
|
100
|
+
peerAvailable: {
|
|
101
|
+
peer,
|
|
102
|
+
since: new Date(),
|
|
116
103
|
},
|
|
117
104
|
});
|
|
118
105
|
|
|
119
106
|
// Emitting swarm events for each peer.
|
|
120
|
-
for (const [topic,
|
|
121
|
-
Array.from(
|
|
107
|
+
for (const [topic, peers] of this._context.swarms) {
|
|
108
|
+
Array.from(peers).forEach((peer) => {
|
|
122
109
|
this.swarmEvent.emit({
|
|
123
110
|
topic,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
since: new Date(),
|
|
128
|
-
},
|
|
111
|
+
peerAvailable: {
|
|
112
|
+
peer,
|
|
113
|
+
since: new Date(),
|
|
129
114
|
},
|
|
130
115
|
});
|
|
131
116
|
});
|
|
132
117
|
}
|
|
133
118
|
}
|
|
134
119
|
|
|
135
|
-
async leave({ topic,
|
|
120
|
+
async leave({ topic, peer }: { topic: PublicKey; peer: PeerInfo }) {
|
|
136
121
|
invariant(!this._ctx.disposed, 'Closed');
|
|
137
122
|
|
|
138
|
-
this._joinedSwarms.delete({ topic,
|
|
123
|
+
this._joinedSwarms.delete({ topic, peer });
|
|
139
124
|
|
|
140
125
|
if (!this._context.swarms.has(topic)) {
|
|
141
|
-
this._context.swarms.set(topic, new ComplexSet(
|
|
126
|
+
this._context.swarms.set(topic, new ComplexSet(PeerInfoHash));
|
|
142
127
|
}
|
|
143
128
|
|
|
144
|
-
this._context.swarms.get(topic)!.delete(
|
|
129
|
+
this._context.swarms.get(topic)!.delete(peer);
|
|
145
130
|
|
|
146
131
|
const swarmEvent: SwarmEvent = {
|
|
132
|
+
topic,
|
|
147
133
|
peerLeft: {
|
|
148
|
-
peer
|
|
134
|
+
peer,
|
|
149
135
|
},
|
|
150
136
|
};
|
|
151
137
|
|
|
152
|
-
this._context.swarmEvent.emit(
|
|
138
|
+
this._context.swarmEvent.emit(swarmEvent);
|
|
153
139
|
}
|
|
154
140
|
|
|
155
|
-
async sendMessage({ author, recipient, payload }: { author:
|
|
141
|
+
async sendMessage({ author, recipient, payload }: { author: PeerInfo; recipient: PeerInfo; payload: Any }) {
|
|
156
142
|
log('send message', { author, recipient, ...dec(payload) });
|
|
157
143
|
|
|
158
144
|
invariant(recipient);
|
|
@@ -188,14 +174,14 @@ export class MemorySignalManager implements SignalManager {
|
|
|
188
174
|
});
|
|
189
175
|
}
|
|
190
176
|
|
|
191
|
-
async subscribeMessages(
|
|
192
|
-
log('subscribing', {
|
|
193
|
-
this._context.connections.set(
|
|
177
|
+
async subscribeMessages(peerInfo: PeerInfo) {
|
|
178
|
+
log('subscribing', { peerInfo });
|
|
179
|
+
this._context.connections.set(peerInfo, this);
|
|
194
180
|
}
|
|
195
181
|
|
|
196
|
-
async unsubscribeMessages(
|
|
197
|
-
log('unsubscribing', {
|
|
198
|
-
this._context.connections.delete(
|
|
182
|
+
async unsubscribeMessages(peerInfo: PeerInfo) {
|
|
183
|
+
log('unsubscribing', { peerInfo });
|
|
184
|
+
this._context.connections.delete(peerInfo);
|
|
199
185
|
}
|
|
200
186
|
|
|
201
187
|
freeze() {
|
|
@@ -3,16 +3,14 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Event } from '@dxos/async';
|
|
6
|
+
import { type Lifecycle } from '@dxos/context';
|
|
6
7
|
|
|
7
|
-
import { type
|
|
8
|
+
import { type SignalStatus, type SignalMethods } from '../signal-methods';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Manages a collection of signaling clients.
|
|
11
12
|
*/
|
|
12
|
-
export interface SignalManager extends SignalMethods {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
getStatus(): SignalStatus[];
|
|
16
|
-
|
|
17
|
-
statusChanged: Event<SignalStatus[]>;
|
|
13
|
+
export interface SignalManager extends SignalMethods, Required<Lifecycle> {
|
|
14
|
+
statusChanged?: Event<SignalStatus[]>;
|
|
15
|
+
getStatus?: () => SignalStatus[];
|
|
18
16
|
}
|
|
@@ -8,7 +8,7 @@ import { runTestSignalServer, type SignalServerRunner } from '@dxos/signal';
|
|
|
8
8
|
import { afterAll, beforeAll, describe, test, openAndClose } from '@dxos/test';
|
|
9
9
|
|
|
10
10
|
import { WebsocketSignalManager } from './websocket-signal-manager';
|
|
11
|
-
import { expectPeerAvailable, expectReceivedMessage } from '../testing';
|
|
11
|
+
import { createMessage, expectPeerAvailable, expectReceivedMessage } from '../testing';
|
|
12
12
|
|
|
13
13
|
describe('WebSocketSignalManager', () => {
|
|
14
14
|
let broker1: SignalServerRunner;
|
|
@@ -40,14 +40,14 @@ describe('WebSocketSignalManager', () => {
|
|
|
40
40
|
|
|
41
41
|
const [topic, peer1, peer2, peer3] = PublicKey.randomSequence();
|
|
42
42
|
|
|
43
|
-
const joined12 = expectPeerAvailable(client1, topic, peer2);
|
|
44
|
-
const joined13 = expectPeerAvailable(client1, topic, peer3);
|
|
45
|
-
const joined21 = expectPeerAvailable(client2, topic, peer1);
|
|
46
|
-
const joined31 = expectPeerAvailable(client3, topic, peer1);
|
|
43
|
+
const joined12 = expectPeerAvailable(client1, topic, { peerKey: peer2.toHex() });
|
|
44
|
+
const joined13 = expectPeerAvailable(client1, topic, { peerKey: peer3.toHex() });
|
|
45
|
+
const joined21 = expectPeerAvailable(client2, topic, { peerKey: peer1.toHex() });
|
|
46
|
+
const joined31 = expectPeerAvailable(client3, topic, { peerKey: peer1.toHex() });
|
|
47
47
|
|
|
48
|
-
await client1.join({ topic,
|
|
49
|
-
await client2.join({ topic,
|
|
50
|
-
await client3.join({ topic,
|
|
48
|
+
await client1.join({ topic, peer: { peerKey: peer1.toHex() } });
|
|
49
|
+
await client2.join({ topic, peer: { peerKey: peer2.toHex() } });
|
|
50
|
+
await client3.join({ topic, peer: { peerKey: peer3.toHex() } });
|
|
51
51
|
|
|
52
52
|
await Promise.all([joined12, joined13, joined21, joined31]);
|
|
53
53
|
})
|
|
@@ -62,22 +62,18 @@ describe('WebSocketSignalManager', () => {
|
|
|
62
62
|
|
|
63
63
|
const [topic, peer1, peer2] = PublicKey.randomSequence();
|
|
64
64
|
|
|
65
|
-
const joined12 = expectPeerAvailable(client1, topic, peer2);
|
|
66
|
-
const joined21 = expectPeerAvailable(client2, topic, peer1);
|
|
65
|
+
const joined12 = expectPeerAvailable(client1, topic, { peerKey: peer2.toHex() });
|
|
66
|
+
const joined21 = expectPeerAvailable(client2, topic, { peerKey: peer1.toHex() });
|
|
67
67
|
|
|
68
|
-
await client1.join({ topic,
|
|
69
|
-
await client2.join({ topic,
|
|
68
|
+
await client1.join({ topic, peer: { peerKey: peer1.toHex() } });
|
|
69
|
+
await client2.join({ topic, peer: { peerKey: peer2.toHex() } });
|
|
70
70
|
|
|
71
71
|
await asyncTimeout(Promise.all([joined12, joined21]), 1_000);
|
|
72
72
|
|
|
73
|
-
const message = {
|
|
74
|
-
author: peer1,
|
|
75
|
-
recipient: peer2,
|
|
76
|
-
payload: { type_url: 'google.protobuf.Any', value: Uint8Array.from([1, 2, 3]) },
|
|
77
|
-
};
|
|
73
|
+
const message = createMessage({ peerKey: peer1.toHex() }, { peerKey: peer2.toHex() });
|
|
78
74
|
|
|
79
|
-
const received = expectReceivedMessage(client2, message);
|
|
80
|
-
await client2.subscribeMessages(peer2);
|
|
75
|
+
const received = expectReceivedMessage(client2.onMessage, message);
|
|
76
|
+
await client2.subscribeMessages({ peerKey: peer2.toHex() });
|
|
81
77
|
await sleep(50);
|
|
82
78
|
await client1.sendMessage(message);
|
|
83
79
|
|
|
@@ -94,11 +90,11 @@ describe('WebSocketSignalManager', () => {
|
|
|
94
90
|
|
|
95
91
|
const [topic, peer1, peer2] = PublicKey.randomSequence();
|
|
96
92
|
|
|
97
|
-
const joined12 = expectPeerAvailable(client1, topic, peer2);
|
|
98
|
-
const joined21 = expectPeerAvailable(client2, topic, peer1);
|
|
93
|
+
const joined12 = expectPeerAvailable(client1, topic, { peerKey: peer2.toHex() });
|
|
94
|
+
const joined21 = expectPeerAvailable(client2, topic, { peerKey: peer1.toHex() });
|
|
99
95
|
|
|
100
|
-
await client1.join({ topic,
|
|
101
|
-
await client2.join({ topic,
|
|
96
|
+
await client1.join({ topic, peer: { peerKey: peer1.toHex() } });
|
|
97
|
+
await client2.join({ topic, peer: { peerKey: peer2.toHex() } });
|
|
102
98
|
|
|
103
99
|
await Promise.all([joined12, joined21]);
|
|
104
100
|
})
|
|
@@ -113,18 +109,18 @@ describe('WebSocketSignalManager', () => {
|
|
|
113
109
|
|
|
114
110
|
const [topic1, topic2, peer1, peer2] = PublicKey.randomSequence();
|
|
115
111
|
|
|
116
|
-
const joined112 = expectPeerAvailable(client1, topic1, peer2);
|
|
117
|
-
const joined121 = expectPeerAvailable(client2, topic1, peer1);
|
|
112
|
+
const joined112 = expectPeerAvailable(client1, topic1, { peerKey: peer2.toHex() });
|
|
113
|
+
const joined121 = expectPeerAvailable(client2, topic1, { peerKey: peer1.toHex() });
|
|
118
114
|
|
|
119
|
-
await client1.join({ topic: topic1,
|
|
120
|
-
await client2.join({ topic: topic1,
|
|
115
|
+
await client1.join({ topic: topic1, peer: { peerKey: peer1.toHex() } });
|
|
116
|
+
await client2.join({ topic: topic1, peer: { peerKey: peer2.toHex() } });
|
|
121
117
|
await Promise.all([joined112, joined121]);
|
|
122
118
|
|
|
123
|
-
const joined212 = expectPeerAvailable(client1, topic2, peer2);
|
|
124
|
-
const joined221 = expectPeerAvailable(client2, topic2, peer1);
|
|
119
|
+
const joined212 = expectPeerAvailable(client1, topic2, { peerKey: peer2.toHex() });
|
|
120
|
+
const joined221 = expectPeerAvailable(client2, topic2, { peerKey: peer1.toHex() });
|
|
125
121
|
|
|
126
|
-
await client1.join({ topic: topic2,
|
|
127
|
-
await client2.join({ topic: topic2,
|
|
122
|
+
await client1.join({ topic: topic2, peer: { peerKey: peer1.toHex() } });
|
|
123
|
+
await client2.join({ topic: topic2, peer: { peerKey: peer2.toHex() } });
|
|
128
124
|
await Promise.all([joined212, joined221]);
|
|
129
125
|
})
|
|
130
126
|
.timeout(1_000)
|