mockrtc 0.1.0 → 0.2.0
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/README.md +2 -2
- package/dist/client/mockrtc-admin-request-builder.d.ts +21 -0
- package/dist/client/mockrtc-admin-request-builder.js +171 -0
- package/dist/client/mockrtc-admin-request-builder.js.map +1 -0
- package/dist/client/mockrtc-client.d.ts +5 -1
- package/dist/client/mockrtc-client.js +20 -16
- package/dist/client/mockrtc-client.js.map +1 -1
- package/dist/client/mockrtc-remote-peer.d.ts +3 -2
- package/dist/client/mockrtc-remote-peer.js.map +1 -1
- package/dist/handling/handler-step-definitions.d.ts +3 -2
- package/dist/handling/handler-step-definitions.js.map +1 -1
- package/dist/handling/handler-steps.js +1 -1
- package/dist/handling/handler-steps.js.map +1 -1
- package/dist/main-browser.d.ts +2 -0
- package/dist/main-browser.js +5 -1
- package/dist/main-browser.js.map +1 -1
- package/dist/main.d.ts +5 -4
- package/dist/main.js +5 -1
- package/dist/main.js.map +1 -1
- package/dist/mockrtc-peer.d.ts +37 -6
- package/dist/mockrtc.d.ts +138 -1
- package/dist/mockrtc.js +1 -0
- package/dist/mockrtc.js.map +1 -1
- package/dist/server/mockrtc-admin-plugin.d.ts +2 -2
- package/dist/server/mockrtc-admin-plugin.js +147 -2
- package/dist/server/mockrtc-admin-plugin.js.map +1 -1
- package/dist/server/mockrtc-server-peer.d.ts +8 -2
- package/dist/server/mockrtc-server-peer.js +106 -5
- package/dist/server/mockrtc-server-peer.js.map +1 -1
- package/dist/server/mockrtc-server.d.ts +11 -3
- package/dist/server/mockrtc-server.js +44 -6
- package/dist/server/mockrtc-server.js.map +1 -1
- package/dist/webrtc/datachannel-stream.d.ts +2 -0
- package/dist/webrtc/datachannel-stream.js +12 -0
- package/dist/webrtc/datachannel-stream.js.map +1 -1
- package/dist/webrtc/mediatrack-stream.d.ts +4 -0
- package/dist/webrtc/mediatrack-stream.js +13 -1
- package/dist/webrtc/mediatrack-stream.js.map +1 -1
- package/dist/webrtc/mockrtc-connection.d.ts +1 -1
- package/dist/webrtc/mockrtc-connection.js +77 -60
- package/dist/webrtc/mockrtc-connection.js.map +1 -1
- package/dist/webrtc/rtc-connection.d.ts +23 -4
- package/dist/webrtc/rtc-connection.js +45 -6
- package/dist/webrtc/rtc-connection.js.map +1 -1
- package/dist/webrtc-hooks.js +4 -2
- package/dist/webrtc-hooks.js.map +1 -1
- package/package.json +12 -6
- package/src/client/mockrtc-admin-request-builder.ts +184 -0
- package/src/client/mockrtc-client.ts +26 -22
- package/src/client/mockrtc-remote-peer.ts +9 -8
- package/src/handling/handler-step-definitions.ts +6 -4
- package/src/handling/handler-steps.ts +6 -5
- package/src/main-browser.ts +4 -0
- package/src/main.ts +18 -4
- package/src/mockrtc-peer.ts +41 -6
- package/src/mockrtc.ts +163 -1
- package/src/server/mockrtc-admin-plugin.ts +159 -6
- package/src/server/mockrtc-server-peer.ts +183 -6
- package/src/server/mockrtc-server.ts +75 -14
- package/src/webrtc/datachannel-stream.ts +16 -0
- package/src/webrtc/mediatrack-stream.ts +16 -3
- package/src/webrtc/mockrtc-connection.ts +21 -6
- package/src/webrtc/rtc-connection.ts +79 -14
- package/src/webrtc-hooks.ts +7 -4
- package/test/integration/events.spec.ts +536 -0
- package/test/integration/matching.spec.ts +68 -0
- package/test/integration/proxy.spec.ts +66 -1
- package/test/test-setup.ts +19 -0
|
@@ -14,40 +14,78 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.MockRTCServer = void 0;
|
|
17
|
+
const events_1 = require("events");
|
|
17
18
|
const mockrtc_server_peer_1 = require("./mockrtc-server-peer");
|
|
18
19
|
const handler_builder_1 = require("../handling/handler-builder");
|
|
19
20
|
const handler_steps_1 = require("../handling/handler-steps");
|
|
21
|
+
const MATCHING_PEER_ID = 'matching-peer';
|
|
20
22
|
class MockRTCServer {
|
|
21
23
|
constructor(options = {}) {
|
|
22
24
|
this.options = options;
|
|
25
|
+
this.debug = false;
|
|
26
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
27
|
+
this._activePeers = {};
|
|
23
28
|
this.buildPeerFromData = (handlerStepDefinitions) => __awaiter(this, void 0, void 0, function* () {
|
|
24
29
|
const handlerSteps = handlerStepDefinitions.map((definition) => {
|
|
25
30
|
return Object.assign(Object.create(handler_steps_1.StepLookup[definition.type].prototype), definition);
|
|
26
31
|
});
|
|
27
|
-
const peer = new mockrtc_server_peer_1.MockRTCServerPeer(handlerSteps,
|
|
32
|
+
const peer = new mockrtc_server_peer_1.MockRTCServerPeer(() => handlerSteps, // Always runs a fixed set of steps
|
|
33
|
+
this.options, this.eventEmitter);
|
|
28
34
|
this._activePeers[peer.peerId] = peer;
|
|
35
|
+
if (this.debug)
|
|
36
|
+
console.log(`Built MockRTC peer ${peer.peerId} with steps: ${handlerStepDefinitions.map(d => d.type).join(', ')}`);
|
|
29
37
|
return peer;
|
|
30
38
|
});
|
|
31
|
-
this.
|
|
39
|
+
this.debug = !!options.debug;
|
|
32
40
|
}
|
|
33
41
|
start() {
|
|
34
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
if (this.debug)
|
|
44
|
+
console.log("Starting MockRTC mock session");
|
|
45
|
+
this.matchingPeer = this._activePeers[MATCHING_PEER_ID] = new mockrtc_server_peer_1.MockRTCServerPeer(this.matchConnection.bind(this), Object.assign(Object.assign({}, this.options), { peerId: MATCHING_PEER_ID }), this.eventEmitter);
|
|
46
|
+
});
|
|
35
47
|
}
|
|
36
48
|
stop() {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
if (this.debug)
|
|
51
|
+
console.log("Stopping MockRTC mock session");
|
|
52
|
+
yield this.reset();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
reset() {
|
|
37
56
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
57
|
yield Promise.all(this.activePeers.map(peer => peer.close()));
|
|
39
58
|
this._activePeers = {};
|
|
59
|
+
this.matchingPeer = undefined;
|
|
60
|
+
this.eventEmitter.removeAllListeners();
|
|
40
61
|
});
|
|
41
62
|
}
|
|
42
|
-
buildPeer() {
|
|
43
|
-
return new handler_builder_1.MockRTCHandlerBuilder(this.buildPeerFromData);
|
|
44
|
-
}
|
|
45
63
|
get activePeers() {
|
|
46
64
|
return Object.values(this._activePeers);
|
|
47
65
|
}
|
|
48
66
|
getPeer(id) {
|
|
49
67
|
return this._activePeers[id];
|
|
50
68
|
}
|
|
69
|
+
on(event, callback) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
this.eventEmitter.on(event, callback);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
getMatchingPeer() {
|
|
75
|
+
if (!this.matchingPeer) {
|
|
76
|
+
throw new Error('Cannot get matching peer as the mock session is not started');
|
|
77
|
+
}
|
|
78
|
+
return this.matchingPeer;
|
|
79
|
+
}
|
|
80
|
+
matchConnection(connection) {
|
|
81
|
+
return [
|
|
82
|
+
new handler_steps_1.DynamicProxyStep()
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
// Peer definition API:
|
|
86
|
+
buildPeer() {
|
|
87
|
+
return new handler_builder_1.MockRTCHandlerBuilder(this.buildPeerFromData);
|
|
88
|
+
}
|
|
51
89
|
}
|
|
52
90
|
exports.MockRTCServer = MockRTCServer;
|
|
53
91
|
//# sourceMappingURL=mockrtc-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockrtc-server.js","sourceRoot":"","sources":["../../src/server/mockrtc-server.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"mockrtc-server.js","sourceRoot":"","sources":["../../src/server/mockrtc-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,5 +21,7 @@ export declare class DataChannelStream extends stream.Duplex {
|
|
|
21
21
|
_write(chunk: string | Buffer | unknown, encoding: string, callback: (error: Error | null) => void): void;
|
|
22
22
|
_final(callback: (error: Error | null) => void): void;
|
|
23
23
|
_destroy(maybeErr: Error | null, callback: (error: Error | null) => void): void;
|
|
24
|
+
get id(): number;
|
|
24
25
|
get label(): string;
|
|
26
|
+
get protocol(): string;
|
|
25
27
|
}
|
|
@@ -21,6 +21,11 @@ class DataChannelStream extends stream.Duplex {
|
|
|
21
21
|
this.rawChannel = rawChannel;
|
|
22
22
|
this._readActive = true;
|
|
23
23
|
rawChannel.onMessage((msg) => {
|
|
24
|
+
// Independently of the stream and it's normal events, we also fire our own
|
|
25
|
+
// read/wrote-data events, used for MockRTC event subscriptions. These aren't
|
|
26
|
+
// buffered, and this ensures that those events do not consume data that will
|
|
27
|
+
// separately be processed by handler steps.
|
|
28
|
+
this.emit('read-data', msg);
|
|
24
29
|
if (!this._readActive)
|
|
25
30
|
return; // If the buffer is full, drop messages.
|
|
26
31
|
// If the push is rejected, we pause reading until the next call to _read().
|
|
@@ -57,6 +62,7 @@ class DataChannelStream extends stream.Duplex {
|
|
|
57
62
|
const typeName = chunk.constructor.name || typeof chunk;
|
|
58
63
|
throw new Error(`Cannot write ${typeName} to DataChannel stream`);
|
|
59
64
|
}
|
|
65
|
+
this.emit('wrote-data', chunk);
|
|
60
66
|
}
|
|
61
67
|
catch (err) {
|
|
62
68
|
return callback(err);
|
|
@@ -78,9 +84,15 @@ class DataChannelStream extends stream.Duplex {
|
|
|
78
84
|
this.rawChannel.close();
|
|
79
85
|
callback(maybeErr);
|
|
80
86
|
}
|
|
87
|
+
get id() {
|
|
88
|
+
return this.rawChannel.getId();
|
|
89
|
+
}
|
|
81
90
|
get label() {
|
|
82
91
|
return this.rawChannel.getLabel();
|
|
83
92
|
}
|
|
93
|
+
get protocol() {
|
|
94
|
+
return this.rawChannel.getProtocol();
|
|
95
|
+
}
|
|
84
96
|
}
|
|
85
97
|
exports.DataChannelStream = DataChannelStream;
|
|
86
98
|
//# sourceMappingURL=datachannel-stream.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datachannel-stream.js","sourceRoot":"","sources":["../../src/webrtc/datachannel-stream.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAAiC;AAGjC;;;;;;;GAOG;AACH,MAAa,iBAAkB,SAAQ,MAAM,CAAC,MAAM;IAEhD,YACY,UAAuC,EAC/C,gBAKI,EAAE;QAEN,KAAK,+BACD,aAAa,EAAE,KAAK,IACjB,aAAa,KAChB,UAAU,EAAE,IAAI,CAAC,0EAA0E;YAC7F,CAAC;QAZK,eAAU,GAAV,UAAU,CAA6B;
|
|
1
|
+
{"version":3,"file":"datachannel-stream.js","sourceRoot":"","sources":["../../src/webrtc/datachannel-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,10 @@ export declare class MediaTrackStream extends stream.Duplex {
|
|
|
13
13
|
writableHighWaterMark?: number | undefined;
|
|
14
14
|
allowHalfOpen?: boolean;
|
|
15
15
|
});
|
|
16
|
+
private _totalBytesSent;
|
|
17
|
+
get totalBytesSent(): number;
|
|
18
|
+
private _totalBytesReceived;
|
|
19
|
+
get totalBytesReceived(): number;
|
|
16
20
|
private close;
|
|
17
21
|
private _readActive;
|
|
18
22
|
_read(): void;
|
|
@@ -17,8 +17,11 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
17
17
|
constructor(rawTrack, streamOptions = {}) {
|
|
18
18
|
super(Object.assign({ allowHalfOpen: false }, streamOptions));
|
|
19
19
|
this.rawTrack = rawTrack;
|
|
20
|
+
this._totalBytesSent = 0;
|
|
21
|
+
this._totalBytesReceived = 0;
|
|
20
22
|
this._readActive = true;
|
|
21
23
|
rawTrack.onMessage((msg) => {
|
|
24
|
+
this._totalBytesReceived += msg.byteLength;
|
|
22
25
|
if (!this._readActive)
|
|
23
26
|
return; // If the buffer is full, drop messages.
|
|
24
27
|
// If the push is rejected, we pause reading until the next call to _read().
|
|
@@ -35,6 +38,12 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
35
38
|
rawTrack.onOpen(() => this.uncork());
|
|
36
39
|
}
|
|
37
40
|
}
|
|
41
|
+
get totalBytesSent() {
|
|
42
|
+
return this._totalBytesSent;
|
|
43
|
+
}
|
|
44
|
+
get totalBytesReceived() {
|
|
45
|
+
return this._totalBytesReceived;
|
|
46
|
+
}
|
|
38
47
|
close() {
|
|
39
48
|
this.push(null);
|
|
40
49
|
this.destroy();
|
|
@@ -53,6 +62,7 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
53
62
|
}
|
|
54
63
|
try {
|
|
55
64
|
sentOk = this.rawTrack.sendMessageBinary(chunk);
|
|
65
|
+
this._totalBytesSent += chunk.byteLength;
|
|
56
66
|
}
|
|
57
67
|
catch (err) {
|
|
58
68
|
return callback(err);
|
|
@@ -73,7 +83,9 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
73
83
|
return;
|
|
74
84
|
}
|
|
75
85
|
try {
|
|
76
|
-
|
|
86
|
+
const combinedChunks = Buffer.concat(chunks.map(c => c.chunk));
|
|
87
|
+
sentOk = this.rawTrack.sendMessageBinary(combinedChunks);
|
|
88
|
+
this._totalBytesSent += combinedChunks.byteLength;
|
|
77
89
|
}
|
|
78
90
|
catch (err) {
|
|
79
91
|
return callback(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediatrack-stream.js","sourceRoot":"","sources":["../../src/webrtc/mediatrack-stream.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,iCAAiC;AACjC,oDAAoD;AAEpD,MAAM,EAAE,SAAS,EAAE,GAAG,eAAe,CAAC;AAEtC;;;;GAIG;AACH,MAAa,gBAAiB,SAAQ,MAAM,CAAC,MAAM;IAE/C,YACY,QAA+B,EACvC,gBAKI,EAAE;QAEN,KAAK,iBACD,aAAa,EAAE,KAAK,IACjB,aAAa,EAClB,CAAC;QAXK,aAAQ,GAAR,QAAQ,CAAuB;
|
|
1
|
+
{"version":3,"file":"mediatrack-stream.js","sourceRoot":"","sources":["../../src/webrtc/mediatrack-stream.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,5 +10,5 @@ export declare class MockRTCConnection extends RTCConnection {
|
|
|
10
10
|
isLocal: boolean;
|
|
11
11
|
}): DataChannelStream;
|
|
12
12
|
proxyTrafficToExternalConnection(): Promise<void>;
|
|
13
|
-
proxyTrafficTo(externalConnection: RTCConnection): void
|
|
13
|
+
proxyTrafficTo(externalConnection: RTCConnection): Promise<void>;
|
|
14
14
|
}
|
|
@@ -43,10 +43,15 @@ class MockRTCConnection extends rtc_connection_1.RTCConnection {
|
|
|
43
43
|
if (this.externalConnection) {
|
|
44
44
|
throw new Error('Cannot attach mock connection to multiple external connections');
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
|
|
46
|
+
const externalConnection = this.getExternalConnection(controlMessage.id);
|
|
47
|
+
// We don't attach until the external connection actually connects. Typically that's
|
|
48
|
+
// already happened at this point, but its not guaranteed, so best to check:
|
|
49
|
+
externalConnection.waitUntilConnected().then(() => {
|
|
50
|
+
this.externalConnection = externalConnection;
|
|
51
|
+
this.emit('external-connection-attached', this.externalConnection);
|
|
52
|
+
});
|
|
53
|
+
// We don't necessarily proxy traffic through to the external connection at this
|
|
54
|
+
// point, that depends on the specific handling that's used here.
|
|
50
55
|
}
|
|
51
56
|
else {
|
|
52
57
|
throw new Error(`Unrecognized control channel message: ${controlMessage.type}`);
|
|
@@ -77,69 +82,81 @@ class MockRTCConnection extends rtc_connection_1.RTCConnection {
|
|
|
77
82
|
if (!this.externalConnection) {
|
|
78
83
|
yield new Promise((resolve) => this.once('external-connection-attached', resolve));
|
|
79
84
|
}
|
|
80
|
-
this.proxyTrafficTo(this.externalConnection);
|
|
85
|
+
yield this.proxyTrafficTo(this.externalConnection);
|
|
81
86
|
});
|
|
82
87
|
}
|
|
83
88
|
proxyTrafficTo(externalConnection) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
* - A MockRTC external connection that will connect to the remote peer ('external')
|
|
89
|
-
* - The original remote peer that we're connecting to ('remote')
|
|
90
|
-
*
|
|
91
|
-
* Once the proxy is set up, the the connection structure works like so:
|
|
92
|
-
* INTERNAL <--> MOCK <--> EXTERNAL <--> REMOTE
|
|
93
|
-
*
|
|
94
|
-
* Here we connect the internal & external connections together, proxying all behaviours between the
|
|
95
|
-
* two so that from this point forwards every event on one is reflected on the other.
|
|
96
|
-
*
|
|
97
|
-
* Note that this isn't necessarily the initialization of either connection: the remote peer could
|
|
98
|
-
* have been connected for a while (sending data with no response), and the internal peer could have
|
|
99
|
-
* been fully interacting with steps before this point.
|
|
100
|
-
*/
|
|
101
|
-
// Mirror connection closure:
|
|
102
|
-
this.on('connection-closed', () => externalConnection.close());
|
|
103
|
-
externalConnection.on('connection-closed', () => this.close());
|
|
104
|
-
/// --- Data channels: --- ///
|
|
105
|
-
// Forward *all* existing internal channels to the external connection:
|
|
106
|
-
this.channels.forEach((channel) => {
|
|
107
|
-
const mirrorChannelStream = externalConnection.createDataChannel(channel.label);
|
|
108
|
-
channel.pipe(mirrorChannelStream).pipe(channel);
|
|
109
|
-
});
|
|
110
|
-
// Forward any existing external channels back to this peer connection. Note that we're mirroring
|
|
111
|
-
// *remote* channels only, so we skip the channels that we've just created above.
|
|
112
|
-
externalConnection.remoteChannels.forEach((channel) => {
|
|
113
|
-
const mirrorChannelStream = this.createDataChannel(channel.label);
|
|
114
|
-
channel.pipe(mirrorChannelStream).pipe(channel);
|
|
115
|
-
});
|
|
116
|
-
// If any new channels open in future, mirror them to the other peer:
|
|
117
|
-
[[this, externalConnection], [externalConnection, this]].forEach(([connA, connB]) => {
|
|
118
|
-
connA.on('remote-channel-open', (incomingChannel) => {
|
|
119
|
-
const mirrorChannelStream = connB.createDataChannel(incomingChannel.label);
|
|
120
|
-
incomingChannel.pipe(mirrorChannelStream).pipe(incomingChannel);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
/// --- Media tracks: --- ///
|
|
124
|
-
// Note that while data channels will *not* have been negotiated before this point, so
|
|
125
|
-
// we can always assume that mock data channels need mirroring, media tracks are negotiated
|
|
126
|
-
// in the SDP, not in-band, and so any media track could already exist on the other side.
|
|
127
|
-
// For each track on the internal connection, proxy it to the corresponding external track:
|
|
128
|
-
this.mediaTracks.forEach((track) => {
|
|
129
|
-
const externalStream = externalConnection.mediaTracks.find(({ mid }) => mid === track.mid);
|
|
130
|
-
if (externalStream) {
|
|
131
|
-
if (externalStream.type === track.type) {
|
|
132
|
-
track.pipe(externalStream).pipe(track);
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
throw new Error(`Mock & external streams with mid ${track.mid} have mismatched types (${track.type}/${externalStream.type})`);
|
|
89
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
+
if (this.externalConnection) {
|
|
91
|
+
if (externalConnection !== this.externalConnection) {
|
|
92
|
+
throw new Error('Cannot attach multiple external connections');
|
|
136
93
|
}
|
|
137
94
|
}
|
|
138
95
|
else {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
96
|
+
yield externalConnection.waitUntilConnected();
|
|
97
|
+
this.externalConnection = externalConnection;
|
|
98
|
+
this.emit('external-connection-attached', this.externalConnection);
|
|
142
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* When proxying traffic, you effectively have four peers, each with a connection endpoint:
|
|
102
|
+
* - The incoming RTCPeerConnection that we're mocking ('internal')
|
|
103
|
+
* - This MockRTC connection, with an associated MockRTCPeer that it will actually connect to ('mock')
|
|
104
|
+
* - A MockRTC external connection that will connect to the remote peer ('external')
|
|
105
|
+
* - The original remote peer that we're connecting to ('remote')
|
|
106
|
+
*
|
|
107
|
+
* Once the proxy is set up, the the connection structure works like so:
|
|
108
|
+
* INTERNAL <--> MOCK <--> EXTERNAL <--> REMOTE
|
|
109
|
+
*
|
|
110
|
+
* Here we connect the internal & external connections together, proxying all behaviours between the
|
|
111
|
+
* two so that from this point forwards every event on one is reflected on the other.
|
|
112
|
+
*
|
|
113
|
+
* Note that this isn't necessarily the initialization of either connection: the remote peer could
|
|
114
|
+
* have been connected for a while (sending data with no response), and the internal peer could have
|
|
115
|
+
* been fully interacting with steps before this point.
|
|
116
|
+
*/
|
|
117
|
+
// Mirror connection closure:
|
|
118
|
+
this.on('connection-closed', () => externalConnection.close());
|
|
119
|
+
externalConnection.on('connection-closed', () => this.close());
|
|
120
|
+
/// --- Data channels: --- ///
|
|
121
|
+
// Forward *all* existing internal channels to the external connection:
|
|
122
|
+
this.channels.forEach((channel) => {
|
|
123
|
+
const mirrorChannelStream = externalConnection.createDataChannel(channel.label);
|
|
124
|
+
channel.pipe(mirrorChannelStream).pipe(channel);
|
|
125
|
+
});
|
|
126
|
+
// Forward any existing external channels back to this peer connection. Note that we're mirroring
|
|
127
|
+
// *remote* channels only, so we skip the channels that we've just created above.
|
|
128
|
+
externalConnection.remoteChannels.forEach((channel) => {
|
|
129
|
+
const mirrorChannelStream = this.createDataChannel(channel.label);
|
|
130
|
+
channel.pipe(mirrorChannelStream).pipe(channel);
|
|
131
|
+
});
|
|
132
|
+
// If any new channels open in future, mirror them to the other peer:
|
|
133
|
+
[[this, externalConnection], [externalConnection, this]].forEach(([connA, connB]) => {
|
|
134
|
+
connA.on('remote-channel-open', (incomingChannel) => {
|
|
135
|
+
const mirrorChannelStream = connB.createDataChannel(incomingChannel.label);
|
|
136
|
+
incomingChannel.pipe(mirrorChannelStream).pipe(incomingChannel);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
/// --- Media tracks: --- ///
|
|
140
|
+
// Note that while data channels will *not* have been negotiated before this point, so
|
|
141
|
+
// we can always assume that mock data channels need mirroring, media tracks are negotiated
|
|
142
|
+
// in the SDP, not in-band, and so any media track could already exist on the other side.
|
|
143
|
+
// For each track on the internal connection, proxy it to the corresponding external track:
|
|
144
|
+
this.mediaTracks.forEach((track) => {
|
|
145
|
+
const externalStream = externalConnection.mediaTracks.find(({ mid }) => mid === track.mid);
|
|
146
|
+
if (externalStream) {
|
|
147
|
+
if (externalStream.type === track.type) {
|
|
148
|
+
track.pipe(externalStream).pipe(track);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
throw new Error(`Mock & external streams with mid ${track.mid} have mismatched types (${track.type}/${externalStream.type})`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
// A mismatch in media streams means the external & mock peer negotiation isn't in sync!
|
|
156
|
+
// For now we just reject this case - later we should try to prompt a renegotiation.
|
|
157
|
+
throw new Error(`Mock has ${track.type} ${track.mid} but external does not`);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
143
160
|
});
|
|
144
161
|
}
|
|
145
162
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockrtc-connection.js","sourceRoot":"","sources":["../../src/webrtc/mockrtc-connection.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;AAIH,uDAAmF;AAEnF,6DAAyD;AAEzD,qDAAiD;AAEjD,MAAa,iBAAkB,SAAQ,8BAAa;IAOhD,YACY,qBAAoD;QAE5D,KAAK,EAAE,CAAC;QAFA,0BAAqB,GAArB,qBAAqB,CAA+B;IAGhE,CAAC;IAES,eAAe,CAAC,OAAoC,EAAE,OAA6B;QACzF,IAAI,OAAO,CAAC,QAAQ,EAAE,KAAK,yCAAuB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;YACpE,mFAAmF;YACnF,IAAI,IAAI,CAAC,cAAc,EAAE;gBACrB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBAChF,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC;oBAC/B,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,KAAK,CAAC,OAAO;iBACvB,CAAC,CAAC,CAAC;gBACJ,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;gBACvC,MAAM,KAAK,CAAC;aACf;YAED,IAAI,CAAC,cAAc,GAAG,IAAI,sCAAiB,CAAC,OAAO,CAAC,CAAC;YAErD,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;;gBACnC,IAAI;oBACA,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;oBAEhE,IAAI,cAAc,CAAC,IAAI,KAAK,iBAAiB,EAAE;wBAC3C,IAAI,IAAI,CAAC,kBAAkB,EAAE;4BACzB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;yBACrF;
|
|
1
|
+
{"version":3,"file":"mockrtc-connection.js","sourceRoot":"","sources":["../../src/webrtc/mockrtc-connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
3
|
import * as NodeDataChannel from 'node-datachannel';
|
|
4
|
-
import {
|
|
4
|
+
import type { MockRTCSessionDescription } from '../mockrtc';
|
|
5
|
+
import { ConnectionMetadata, MockRTCSession } from '../mockrtc-peer';
|
|
5
6
|
import { DataChannelStream } from './datachannel-stream';
|
|
6
7
|
import { MediaTrackStream } from './mediatrack-stream';
|
|
7
8
|
/**
|
|
@@ -13,6 +14,9 @@ export declare class RTCConnection extends EventEmitter {
|
|
|
13
14
|
readonly id: string;
|
|
14
15
|
private rawConn;
|
|
15
16
|
private remoteDescription;
|
|
17
|
+
private localDescription;
|
|
18
|
+
private _connectionMetadata;
|
|
19
|
+
get metadata(): ConnectionMetadata;
|
|
16
20
|
private readonly trackedChannels;
|
|
17
21
|
get channels(): ReadonlyArray<DataChannelStream>;
|
|
18
22
|
get localChannels(): ReadonlyArray<DataChannelStream>;
|
|
@@ -35,12 +39,27 @@ export declare class RTCConnection extends EventEmitter {
|
|
|
35
39
|
* full result. Because this waits for gathering, it will not resolve if no DataChannel, other
|
|
36
40
|
* tracks or remote description have been provided beforehand.
|
|
37
41
|
*/
|
|
38
|
-
|
|
42
|
+
buildLocalDescription(): Promise<MockRTCSessionDescription>;
|
|
39
43
|
getRemoteDescription(): RTCSessionDescriptionInit | undefined;
|
|
44
|
+
getLocalDescription(): MockRTCSessionDescription | undefined;
|
|
45
|
+
getSelectedCandidates(): {
|
|
46
|
+
local: {
|
|
47
|
+
type: RTCIceCandidateType;
|
|
48
|
+
protocol: string;
|
|
49
|
+
address: string;
|
|
50
|
+
port: number;
|
|
51
|
+
};
|
|
52
|
+
remote: {
|
|
53
|
+
type: RTCIceCandidateType;
|
|
54
|
+
protocol: string;
|
|
55
|
+
address: string;
|
|
56
|
+
port: number;
|
|
57
|
+
};
|
|
58
|
+
} | undefined;
|
|
40
59
|
getMirroredLocalOffer(sdpToMirror: string, options?: {
|
|
41
60
|
addDataStream?: boolean;
|
|
42
|
-
}): Promise<
|
|
43
|
-
getMirroredLocalAnswer(sdpToMirror: string): Promise<
|
|
61
|
+
}): Promise<MockRTCSessionDescription>;
|
|
62
|
+
getMirroredLocalAnswer(sdpToMirror: string): Promise<MockRTCSessionDescription>;
|
|
44
63
|
waitUntilConnected(): Promise<void>;
|
|
45
64
|
readonly sessionApi: MockRTCSession;
|
|
46
65
|
close(): Promise<void>;
|
|
@@ -14,6 +14,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
16
|
exports.RTCConnection = void 0;
|
|
17
|
+
const _ = require("lodash");
|
|
17
18
|
const crypto_1 = require("crypto");
|
|
18
19
|
const events_1 = require("events");
|
|
19
20
|
const SDP = require("sdp-transform");
|
|
@@ -32,30 +33,37 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
32
33
|
// Set to null when the connection is closed, as otherwise calling any method (including checking
|
|
33
34
|
// the connection state) will segfault the process.
|
|
34
35
|
this.rawConn = new NodeDataChannel.PeerConnection("MockRTCConnection", { iceServers: [] });
|
|
36
|
+
this._connectionMetadata = {};
|
|
35
37
|
this.trackedChannels = [];
|
|
36
38
|
this.trackedMediaTracks = [];
|
|
37
39
|
this.sessionApi = {
|
|
38
40
|
sessionId: this.id,
|
|
39
41
|
createOffer: (options = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
if (options.connectionMetadata) {
|
|
43
|
+
this._connectionMetadata = Object.assign(Object.assign({}, this._connectionMetadata), options.connectionMetadata);
|
|
44
|
+
}
|
|
40
45
|
if (options.mirrorSDP) {
|
|
41
46
|
return this.getMirroredLocalOffer(options.mirrorSDP, {
|
|
42
47
|
addDataStream: !!options.addDataStream
|
|
43
48
|
});
|
|
44
49
|
}
|
|
45
50
|
else {
|
|
46
|
-
return this.
|
|
51
|
+
return this.buildLocalDescription();
|
|
47
52
|
}
|
|
48
53
|
}),
|
|
49
54
|
completeOffer: (answer) => __awaiter(this, void 0, void 0, function* () {
|
|
50
55
|
this.setRemoteDescription(answer);
|
|
51
56
|
}),
|
|
52
57
|
answerOffer: (offer, options = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
if (options.connectionMetadata) {
|
|
59
|
+
this._connectionMetadata = Object.assign(Object.assign({}, this._connectionMetadata), options.connectionMetadata);
|
|
60
|
+
}
|
|
53
61
|
this.setRemoteDescription(offer);
|
|
54
62
|
if (options.mirrorSDP) {
|
|
55
63
|
return this.getMirroredLocalAnswer(options.mirrorSDP);
|
|
56
64
|
}
|
|
57
65
|
else {
|
|
58
|
-
return this.
|
|
66
|
+
return this.buildLocalDescription();
|
|
59
67
|
}
|
|
60
68
|
})
|
|
61
69
|
};
|
|
@@ -75,10 +83,19 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
75
83
|
this.emit('connection-state-changed', state);
|
|
76
84
|
});
|
|
77
85
|
this.on('connection-state-changed', (state) => {
|
|
78
|
-
if (state === '
|
|
86
|
+
if (state === 'connected') {
|
|
87
|
+
this.emit('connection-connected');
|
|
88
|
+
}
|
|
89
|
+
else if (state === 'closed' || state === 'disconnected') {
|
|
79
90
|
this.emit('connection-closed');
|
|
91
|
+
this.remoteDescription = undefined;
|
|
92
|
+
this.localDescription = undefined;
|
|
93
|
+
}
|
|
80
94
|
});
|
|
81
95
|
}
|
|
96
|
+
get metadata() {
|
|
97
|
+
return this._connectionMetadata;
|
|
98
|
+
}
|
|
82
99
|
get channels() {
|
|
83
100
|
return this.trackedChannels
|
|
84
101
|
.map(channel => channel.stream);
|
|
@@ -169,7 +186,7 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
169
186
|
* full result. Because this waits for gathering, it will not resolve if no DataChannel, other
|
|
170
187
|
* tracks or remote description have been provided beforehand.
|
|
171
188
|
*/
|
|
172
|
-
|
|
189
|
+
buildLocalDescription() {
|
|
173
190
|
return __awaiter(this, void 0, void 0, function* () {
|
|
174
191
|
if (!this.rawConn)
|
|
175
192
|
throw new Error("Can't get local description after connection is closed");
|
|
@@ -194,6 +211,7 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
194
211
|
throw new Error("Connection was closed while building local description");
|
|
195
212
|
const sessionDescription = this.rawConn.localDescription();
|
|
196
213
|
setupChannel === null || setupChannel === void 0 ? void 0 : setupChannel.close(); // Close the temporary setup channel, if we created one
|
|
214
|
+
this.localDescription = sessionDescription;
|
|
197
215
|
return sessionDescription;
|
|
198
216
|
});
|
|
199
217
|
}
|
|
@@ -202,6 +220,23 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
202
220
|
throw new Error("Can't get remote description after connection is closed");
|
|
203
221
|
return this.remoteDescription;
|
|
204
222
|
}
|
|
223
|
+
getLocalDescription() {
|
|
224
|
+
if (!this.rawConn)
|
|
225
|
+
throw new Error("Can't get local description after connection is closed");
|
|
226
|
+
return this.localDescription;
|
|
227
|
+
}
|
|
228
|
+
getSelectedCandidates() {
|
|
229
|
+
if (!this.rawConn)
|
|
230
|
+
throw new Error("Can't get selected candidates after connection is closed");
|
|
231
|
+
const candidates = this.rawConn.getSelectedCandidatePair();
|
|
232
|
+
if (!candidates)
|
|
233
|
+
return undefined;
|
|
234
|
+
// Rename transportType -> protocol, to better match the browser WebRTC APIs
|
|
235
|
+
return {
|
|
236
|
+
local: Object.assign(Object.assign({}, _.omit(candidates.local, 'transportType')), { type: candidates.local.type, protocol: candidates.local.transportType.toLowerCase() }),
|
|
237
|
+
remote: Object.assign(Object.assign({}, _.omit(candidates.remote, 'transportType')), { type: candidates.remote.type, protocol: candidates.remote.transportType.toLowerCase() })
|
|
238
|
+
};
|
|
239
|
+
}
|
|
205
240
|
getMirroredLocalOffer(sdpToMirror, options = {}) {
|
|
206
241
|
return __awaiter(this, void 0, void 0, function* () {
|
|
207
242
|
if (!this.rawConn)
|
|
@@ -268,7 +303,8 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
268
303
|
const offerSDP = SDP.parse(localDesc.sdp);
|
|
269
304
|
mirrorMediaParams(offerToMirror, offerSDP);
|
|
270
305
|
localDesc.sdp = SDP.write(offerSDP);
|
|
271
|
-
|
|
306
|
+
this.localDescription = localDesc;
|
|
307
|
+
return this.localDescription;
|
|
272
308
|
});
|
|
273
309
|
}
|
|
274
310
|
getMirroredLocalAnswer(sdpToMirror) {
|
|
@@ -278,7 +314,8 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
278
314
|
const answerSDP = SDP.parse(localDesc.sdp);
|
|
279
315
|
mirrorMediaParams(answerToMirror, answerSDP);
|
|
280
316
|
localDesc.sdp = SDP.write(answerSDP);
|
|
281
|
-
|
|
317
|
+
this.localDescription = localDesc;
|
|
318
|
+
return this.localDescription;
|
|
282
319
|
});
|
|
283
320
|
}
|
|
284
321
|
waitUntilConnected() {
|
|
@@ -305,6 +342,8 @@ class RTCConnection extends events_1.EventEmitter {
|
|
|
305
342
|
return; // Already closed
|
|
306
343
|
const { rawConn } = this;
|
|
307
344
|
this.rawConn = null; // Drop the reference, so nothing tries to use it after close
|
|
345
|
+
this.remoteDescription = undefined;
|
|
346
|
+
this.localDescription = undefined;
|
|
308
347
|
if (rawConn.state() === 'closed')
|
|
309
348
|
return;
|
|
310
349
|
rawConn.close();
|