mockrtc 0.1.0 → 0.3.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/.github/workflows/ci.yml +2 -2
- package/README.md +2 -2
- package/dist/client/mockrtc-admin-request-builder.d.ts +27 -0
- package/dist/client/mockrtc-admin-request-builder.js +201 -0
- package/dist/client/mockrtc-admin-request-builder.js.map +1 -0
- package/dist/client/mockrtc-client.d.ts +12 -4
- package/dist/client/mockrtc-client.js +38 -22
- 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-builder.d.ts +16 -9
- package/dist/handling/handler-builder.js +11 -1
- package/dist/handling/handler-builder.js.map +1 -1
- package/dist/handling/handler-step-definitions.d.ts +43 -25
- package/dist/handling/handler-step-definitions.js +61 -19
- package/dist/handling/handler-step-definitions.js.map +1 -1
- package/dist/handling/handler-steps.d.ts +4 -1
- package/dist/handling/handler-steps.js +27 -17
- package/dist/handling/handler-steps.js.map +1 -1
- package/dist/main-browser.d.ts +3 -0
- package/dist/main-browser.js +6 -1
- package/dist/main-browser.js.map +1 -1
- package/dist/main.d.ts +8 -5
- package/dist/main.js +6 -1
- package/dist/main.js.map +1 -1
- package/dist/matching/matcher-definitions.d.ts +51 -0
- package/dist/matching/matcher-definitions.js +94 -0
- package/dist/matching/matcher-definitions.js.map +1 -0
- package/dist/matching/matchers.d.ts +27 -0
- package/dist/matching/matchers.js +87 -0
- package/dist/matching/matchers.js.map +1 -0
- package/dist/mockrtc-base.d.ts +16 -0
- package/dist/mockrtc-base.js +19 -0
- package/dist/mockrtc-base.js.map +1 -0
- package/dist/mockrtc-peer.d.ts +44 -6
- package/dist/mockrtc.d.ts +200 -1
- package/dist/mockrtc.js +1 -0
- package/dist/mockrtc.js.map +1 -1
- package/dist/rule-builder.d.ts +86 -0
- package/dist/rule-builder.js +113 -0
- package/dist/rule-builder.js.map +1 -0
- package/dist/server/mockrtc-admin-plugin.d.ts +2 -2
- package/dist/server/mockrtc-admin-plugin.js +165 -3
- 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 +119 -6
- package/dist/server/mockrtc-server-peer.js.map +1 -1
- package/dist/server/mockrtc-server.d.ts +20 -5
- package/dist/server/mockrtc-server.js +87 -14
- package/dist/server/mockrtc-server.js.map +1 -1
- package/dist/webrtc/datachannel-stream.d.ts +4 -0
- package/dist/webrtc/datachannel-stream.js +27 -1
- package/dist/webrtc/datachannel-stream.js.map +1 -1
- package/dist/webrtc/mediatrack-stream.d.ts +6 -0
- package/dist/webrtc/mediatrack-stream.js +28 -2
- 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 +28 -5
- package/dist/webrtc/rtc-connection.js +62 -23
- package/dist/webrtc/rtc-connection.js.map +1 -1
- package/dist/webrtc-hooks.js +10 -2
- package/dist/webrtc-hooks.js.map +1 -1
- package/package.json +12 -6
- package/src/client/mockrtc-admin-request-builder.ts +232 -0
- package/src/client/mockrtc-client.ts +50 -28
- package/src/client/mockrtc-remote-peer.ts +9 -8
- package/src/handling/handler-builder.ts +22 -10
- package/src/handling/handler-step-definitions.ts +87 -27
- package/src/handling/handler-steps.ts +34 -20
- package/src/main-browser.ts +5 -0
- package/src/main.ts +23 -5
- package/src/matching/matcher-definitions.ts +109 -0
- package/src/matching/matchers.ts +118 -0
- package/src/mockrtc-base.ts +49 -0
- package/src/mockrtc-peer.ts +48 -6
- package/src/mockrtc.ts +235 -1
- package/src/rule-builder.ts +142 -0
- package/src/server/mockrtc-admin-plugin.ts +200 -9
- package/src/server/mockrtc-server-peer.ts +194 -7
- package/src/server/mockrtc-server.ts +136 -19
- package/src/webrtc/datachannel-stream.ts +31 -1
- package/src/webrtc/mediatrack-stream.ts +31 -4
- package/src/webrtc/mockrtc-connection.ts +22 -7
- package/src/webrtc/rtc-connection.ts +111 -29
- package/src/webrtc-hooks.ts +13 -4
- package/test/integration/events.spec.ts +538 -0
- package/test/integration/matching.spec.ts +257 -0
- package/test/integration/proxy.spec.ts +68 -1
- package/test/integration/send-steps.spec.ts +25 -0
- package/test/test-setup.ts +19 -0
|
@@ -14,40 +14,113 @@ 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");
|
|
18
|
+
const mockrtc_base_1 = require("../mockrtc-base");
|
|
17
19
|
const mockrtc_server_peer_1 = require("./mockrtc-server-peer");
|
|
18
|
-
const
|
|
20
|
+
const matchers_1 = require("../matching/matchers");
|
|
19
21
|
const handler_steps_1 = require("../handling/handler-steps");
|
|
20
|
-
|
|
22
|
+
const MATCHING_PEER_ID = 'matching-peer';
|
|
23
|
+
class MockRTCServer extends mockrtc_base_1.MockRTCBase {
|
|
21
24
|
constructor(options = {}) {
|
|
25
|
+
super();
|
|
22
26
|
this.options = options;
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
return Object.assign(Object.create(handler_steps_1.StepLookup[definition.type].prototype), definition);
|
|
26
|
-
});
|
|
27
|
-
const peer = new mockrtc_server_peer_1.MockRTCServerPeer(handlerSteps, this.options);
|
|
28
|
-
this._activePeers[peer.peerId] = peer;
|
|
29
|
-
return peer;
|
|
30
|
-
});
|
|
27
|
+
this.debug = false;
|
|
28
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
31
29
|
this._activePeers = {};
|
|
30
|
+
this.rules = [];
|
|
31
|
+
this.debug = !!options.debug;
|
|
32
32
|
}
|
|
33
33
|
start() {
|
|
34
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
if (this.debug)
|
|
36
|
+
console.log("Starting MockRTC mock session");
|
|
37
|
+
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);
|
|
38
|
+
});
|
|
35
39
|
}
|
|
36
40
|
stop() {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
if (this.debug)
|
|
43
|
+
console.log("Stopping MockRTC mock session");
|
|
44
|
+
yield this.reset();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
reset() {
|
|
37
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
49
|
yield Promise.all(this.activePeers.map(peer => peer.close()));
|
|
39
50
|
this._activePeers = {};
|
|
51
|
+
this.matchingPeer = undefined;
|
|
52
|
+
this.rules = [];
|
|
53
|
+
this.eventEmitter.removeAllListeners();
|
|
40
54
|
});
|
|
41
55
|
}
|
|
42
|
-
buildPeer() {
|
|
43
|
-
return new handler_builder_1.MockRTCHandlerBuilder(this.buildPeerFromData);
|
|
44
|
-
}
|
|
45
56
|
get activePeers() {
|
|
46
57
|
return Object.values(this._activePeers);
|
|
47
58
|
}
|
|
48
59
|
getPeer(id) {
|
|
49
60
|
return this._activePeers[id];
|
|
50
61
|
}
|
|
62
|
+
on(event, callback) {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
this.eventEmitter.on(event, callback);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
getMatchingPeer() {
|
|
68
|
+
if (!this.matchingPeer) {
|
|
69
|
+
throw new Error('Cannot get matching peer as the mock session is not started');
|
|
70
|
+
}
|
|
71
|
+
return this.matchingPeer;
|
|
72
|
+
}
|
|
73
|
+
setRulesFromDefinitions(rules) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
75
|
+
this.rules = [];
|
|
76
|
+
yield Promise.all(rules.map(({ matchers, steps }) => this.addRuleFromDefinition(matchers, steps)));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
addRuleFromDefinition(matcherDefinitions, handlerStepDefinitions) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
const matchers = matcherDefinitions.map((definition) => {
|
|
82
|
+
return Object.assign(Object.create(matchers_1.MatcherLookup[definition.type].prototype), definition);
|
|
83
|
+
});
|
|
84
|
+
const handlerSteps = handlerStepDefinitions.map((definition) => {
|
|
85
|
+
return Object.assign(Object.create(handler_steps_1.StepLookup[definition.type].prototype), definition);
|
|
86
|
+
});
|
|
87
|
+
this.rules.push({ matchers, handlerSteps });
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
matchConnection(connection) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
if (this.debug)
|
|
93
|
+
console.log('Matching incoming RTC connection...');
|
|
94
|
+
yield connection.waitUntilConnected();
|
|
95
|
+
for (const rule of this.rules) {
|
|
96
|
+
const matches = rule.matchers.every(matcher => matcher.matches(connection));
|
|
97
|
+
if (matches) {
|
|
98
|
+
if (this.debug)
|
|
99
|
+
console.log(`Matched incoming RTC connection, running steps: ${rule.handlerSteps.map(s => s.type).join(', ')}`);
|
|
100
|
+
return rule.handlerSteps;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (this.debug)
|
|
104
|
+
console.log('RTC connection did not match any rules');
|
|
105
|
+
// Unmatched connections are proxied dynamically. In practice, that means they're accepted
|
|
106
|
+
// and ignored initially, unless an external peer also connects and is attached:
|
|
107
|
+
return [new handler_steps_1.DynamicProxyStep()];
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
// Peer definition API:
|
|
111
|
+
buildPeerFromDefinition(handlerStepDefinitions) {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
const handlerSteps = handlerStepDefinitions.map((definition) => {
|
|
114
|
+
return Object.assign(Object.create(handler_steps_1.StepLookup[definition.type].prototype), definition);
|
|
115
|
+
});
|
|
116
|
+
const peer = new mockrtc_server_peer_1.MockRTCServerPeer(() => handlerSteps, // Always runs a fixed set of steps
|
|
117
|
+
this.options, this.eventEmitter);
|
|
118
|
+
this._activePeers[peer.peerId] = peer;
|
|
119
|
+
if (this.debug)
|
|
120
|
+
console.log(`Built MockRTC peer ${peer.peerId} with steps: ${handlerStepDefinitions.map(d => d.type).join(', ')}`);
|
|
121
|
+
return peer;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
51
124
|
}
|
|
52
125
|
exports.MockRTCServer = MockRTCServer;
|
|
53
126
|
//# 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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"}
|
|
@@ -16,10 +16,14 @@ export declare class DataChannelStream extends stream.Duplex {
|
|
|
16
16
|
writableHighWaterMark?: number | undefined;
|
|
17
17
|
allowHalfOpen?: boolean;
|
|
18
18
|
});
|
|
19
|
+
private _isOpen;
|
|
20
|
+
get isOpen(): boolean;
|
|
19
21
|
private _readActive;
|
|
20
22
|
_read(): void;
|
|
21
23
|
_write(chunk: string | Buffer | unknown, encoding: string, callback: (error: Error | null) => void): void;
|
|
22
24
|
_final(callback: (error: Error | null) => void): void;
|
|
23
25
|
_destroy(maybeErr: Error | null, callback: (error: Error | null) => void): void;
|
|
26
|
+
get id(): number;
|
|
24
27
|
get label(): string;
|
|
28
|
+
get protocol(): string;
|
|
25
29
|
}
|
|
@@ -19,8 +19,14 @@ class DataChannelStream extends stream.Duplex {
|
|
|
19
19
|
super(Object.assign(Object.assign({ allowHalfOpen: false }, streamOptions), { objectMode: true // Preserve the string/buffer distinction (WebRTC treats them differently)
|
|
20
20
|
}));
|
|
21
21
|
this.rawChannel = rawChannel;
|
|
22
|
+
this._isOpen = false;
|
|
22
23
|
this._readActive = true;
|
|
23
24
|
rawChannel.onMessage((msg) => {
|
|
25
|
+
// Independently of the stream and it's normal events, we also fire our own
|
|
26
|
+
// read/wrote-data events, used for MockRTC event subscriptions. These aren't
|
|
27
|
+
// buffered, and this ensures that those events do not consume data that will
|
|
28
|
+
// separately be processed by handler steps.
|
|
29
|
+
this.emit('read-data', msg);
|
|
24
30
|
if (!this._readActive)
|
|
25
31
|
return; // If the buffer is full, drop messages.
|
|
26
32
|
// If the push is rejected, we pause reading until the next call to _read().
|
|
@@ -37,8 +43,21 @@ class DataChannelStream extends stream.Duplex {
|
|
|
37
43
|
// Buffer all writes until the DataChannel opens
|
|
38
44
|
if (!rawChannel.isOpen()) {
|
|
39
45
|
this.cork();
|
|
40
|
-
rawChannel.onOpen(() =>
|
|
46
|
+
rawChannel.onOpen(() => {
|
|
47
|
+
this.uncork();
|
|
48
|
+
this._isOpen = true;
|
|
49
|
+
this.emit('channel-open');
|
|
50
|
+
});
|
|
41
51
|
}
|
|
52
|
+
else {
|
|
53
|
+
setImmediate(() => {
|
|
54
|
+
this._isOpen = true;
|
|
55
|
+
this.emit('channel-open');
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
get isOpen() {
|
|
60
|
+
return this._isOpen;
|
|
42
61
|
}
|
|
43
62
|
_read() {
|
|
44
63
|
// Stop dropping messages, if the buffer filling up meant we were doing so before.
|
|
@@ -57,6 +76,7 @@ class DataChannelStream extends stream.Duplex {
|
|
|
57
76
|
const typeName = chunk.constructor.name || typeof chunk;
|
|
58
77
|
throw new Error(`Cannot write ${typeName} to DataChannel stream`);
|
|
59
78
|
}
|
|
79
|
+
this.emit('wrote-data', chunk);
|
|
60
80
|
}
|
|
61
81
|
catch (err) {
|
|
62
82
|
return callback(err);
|
|
@@ -78,9 +98,15 @@ class DataChannelStream extends stream.Duplex {
|
|
|
78
98
|
this.rawChannel.close();
|
|
79
99
|
callback(maybeErr);
|
|
80
100
|
}
|
|
101
|
+
get id() {
|
|
102
|
+
return this.rawChannel.getId();
|
|
103
|
+
}
|
|
81
104
|
get label() {
|
|
82
105
|
return this.rawChannel.getLabel();
|
|
83
106
|
}
|
|
107
|
+
get protocol() {
|
|
108
|
+
return this.rawChannel.getProtocol();
|
|
109
|
+
}
|
|
84
110
|
}
|
|
85
111
|
exports.DataChannelStream = DataChannelStream;
|
|
86
112
|
//# 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,12 @@ export declare class MediaTrackStream extends stream.Duplex {
|
|
|
13
13
|
writableHighWaterMark?: number | undefined;
|
|
14
14
|
allowHalfOpen?: boolean;
|
|
15
15
|
});
|
|
16
|
+
private _isOpen;
|
|
17
|
+
get isOpen(): boolean;
|
|
18
|
+
private _totalBytesSent;
|
|
19
|
+
get totalBytesSent(): number;
|
|
20
|
+
private _totalBytesReceived;
|
|
21
|
+
get totalBytesReceived(): number;
|
|
16
22
|
private close;
|
|
17
23
|
private _readActive;
|
|
18
24
|
_read(): void;
|
|
@@ -17,8 +17,12 @@ 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._isOpen = false;
|
|
21
|
+
this._totalBytesSent = 0;
|
|
22
|
+
this._totalBytesReceived = 0;
|
|
20
23
|
this._readActive = true;
|
|
21
24
|
rawTrack.onMessage((msg) => {
|
|
25
|
+
this._totalBytesReceived += msg.byteLength;
|
|
22
26
|
if (!this._readActive)
|
|
23
27
|
return; // If the buffer is full, drop messages.
|
|
24
28
|
// If the push is rejected, we pause reading until the next call to _read().
|
|
@@ -32,8 +36,27 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
32
36
|
// Buffer all writes until the DataChannel opens
|
|
33
37
|
if (!rawTrack.isOpen()) {
|
|
34
38
|
this.cork();
|
|
35
|
-
rawTrack.onOpen(() =>
|
|
39
|
+
rawTrack.onOpen(() => {
|
|
40
|
+
this.uncork();
|
|
41
|
+
this._isOpen = true;
|
|
42
|
+
this.emit('track-open');
|
|
43
|
+
});
|
|
36
44
|
}
|
|
45
|
+
else {
|
|
46
|
+
setImmediate(() => {
|
|
47
|
+
this._isOpen = true;
|
|
48
|
+
this.emit('track-open');
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
get isOpen() {
|
|
53
|
+
return this._isOpen;
|
|
54
|
+
}
|
|
55
|
+
get totalBytesSent() {
|
|
56
|
+
return this._totalBytesSent;
|
|
57
|
+
}
|
|
58
|
+
get totalBytesReceived() {
|
|
59
|
+
return this._totalBytesReceived;
|
|
37
60
|
}
|
|
38
61
|
close() {
|
|
39
62
|
this.push(null);
|
|
@@ -53,6 +76,7 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
53
76
|
}
|
|
54
77
|
try {
|
|
55
78
|
sentOk = this.rawTrack.sendMessageBinary(chunk);
|
|
79
|
+
this._totalBytesSent += chunk.byteLength;
|
|
56
80
|
}
|
|
57
81
|
catch (err) {
|
|
58
82
|
return callback(err);
|
|
@@ -73,7 +97,9 @@ class MediaTrackStream extends stream.Duplex {
|
|
|
73
97
|
return;
|
|
74
98
|
}
|
|
75
99
|
try {
|
|
76
|
-
|
|
100
|
+
const combinedChunks = Buffer.concat(chunks.map(c => c.chunk));
|
|
101
|
+
sentOk = this.rawTrack.sendMessageBinary(combinedChunks);
|
|
102
|
+
this._totalBytesSent += combinedChunks.byteLength;
|
|
77
103
|
}
|
|
78
104
|
catch (err) {
|
|
79
105
|
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-created', (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,9 +1,14 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
+
import * as SDP from 'sdp-transform';
|
|
3
4
|
import * as NodeDataChannel from 'node-datachannel';
|
|
4
|
-
import {
|
|
5
|
+
import type { MockRTCSessionDescription } from '../mockrtc';
|
|
6
|
+
import { ConnectionMetadata, MockRTCSession } from '../mockrtc-peer';
|
|
5
7
|
import { DataChannelStream } from './datachannel-stream';
|
|
6
8
|
import { MediaTrackStream } from './mediatrack-stream';
|
|
9
|
+
export declare type ParsedSDP = {
|
|
10
|
+
parsedSdp: SDP.SessionDescription;
|
|
11
|
+
};
|
|
7
12
|
/**
|
|
8
13
|
* An RTC connection is a single connection. This base class defines the raw connection management and
|
|
9
14
|
* tracking logic for a generic connection. The MockRTCConnection subclass extends this and adds
|
|
@@ -13,6 +18,9 @@ export declare class RTCConnection extends EventEmitter {
|
|
|
13
18
|
readonly id: string;
|
|
14
19
|
private rawConn;
|
|
15
20
|
private remoteDescription;
|
|
21
|
+
private localDescription;
|
|
22
|
+
private _connectionMetadata;
|
|
23
|
+
get metadata(): ConnectionMetadata;
|
|
16
24
|
private readonly trackedChannels;
|
|
17
25
|
get channels(): ReadonlyArray<DataChannelStream>;
|
|
18
26
|
get localChannels(): ReadonlyArray<DataChannelStream>;
|
|
@@ -35,12 +43,27 @@ export declare class RTCConnection extends EventEmitter {
|
|
|
35
43
|
* full result. Because this waits for gathering, it will not resolve if no DataChannel, other
|
|
36
44
|
* tracks or remote description have been provided beforehand.
|
|
37
45
|
*/
|
|
38
|
-
|
|
39
|
-
getRemoteDescription(): RTCSessionDescriptionInit | undefined;
|
|
46
|
+
buildLocalDescription(): Promise<MockRTCSessionDescription>;
|
|
47
|
+
getRemoteDescription(): (RTCSessionDescriptionInit & ParsedSDP) | undefined;
|
|
48
|
+
getLocalDescription(): (MockRTCSessionDescription & ParsedSDP) | undefined;
|
|
49
|
+
getSelectedCandidates(): {
|
|
50
|
+
local: {
|
|
51
|
+
type: RTCIceCandidateType;
|
|
52
|
+
protocol: string;
|
|
53
|
+
address: string;
|
|
54
|
+
port: number;
|
|
55
|
+
};
|
|
56
|
+
remote: {
|
|
57
|
+
type: RTCIceCandidateType;
|
|
58
|
+
protocol: string;
|
|
59
|
+
address: string;
|
|
60
|
+
port: number;
|
|
61
|
+
};
|
|
62
|
+
} | undefined;
|
|
40
63
|
getMirroredLocalOffer(sdpToMirror: string, options?: {
|
|
41
64
|
addDataStream?: boolean;
|
|
42
|
-
}): Promise<
|
|
43
|
-
getMirroredLocalAnswer(sdpToMirror: string): Promise<
|
|
65
|
+
}): Promise<MockRTCSessionDescription>;
|
|
66
|
+
getMirroredLocalAnswer(sdpToMirror: string): Promise<MockRTCSessionDescription>;
|
|
44
67
|
waitUntilConnected(): Promise<void>;
|
|
45
68
|
readonly sessionApi: MockRTCSession;
|
|
46
69
|
close(): Promise<void>;
|