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.
Files changed (68) hide show
  1. package/README.md +2 -2
  2. package/dist/client/mockrtc-admin-request-builder.d.ts +21 -0
  3. package/dist/client/mockrtc-admin-request-builder.js +171 -0
  4. package/dist/client/mockrtc-admin-request-builder.js.map +1 -0
  5. package/dist/client/mockrtc-client.d.ts +5 -1
  6. package/dist/client/mockrtc-client.js +20 -16
  7. package/dist/client/mockrtc-client.js.map +1 -1
  8. package/dist/client/mockrtc-remote-peer.d.ts +3 -2
  9. package/dist/client/mockrtc-remote-peer.js.map +1 -1
  10. package/dist/handling/handler-step-definitions.d.ts +3 -2
  11. package/dist/handling/handler-step-definitions.js.map +1 -1
  12. package/dist/handling/handler-steps.js +1 -1
  13. package/dist/handling/handler-steps.js.map +1 -1
  14. package/dist/main-browser.d.ts +2 -0
  15. package/dist/main-browser.js +5 -1
  16. package/dist/main-browser.js.map +1 -1
  17. package/dist/main.d.ts +5 -4
  18. package/dist/main.js +5 -1
  19. package/dist/main.js.map +1 -1
  20. package/dist/mockrtc-peer.d.ts +37 -6
  21. package/dist/mockrtc.d.ts +138 -1
  22. package/dist/mockrtc.js +1 -0
  23. package/dist/mockrtc.js.map +1 -1
  24. package/dist/server/mockrtc-admin-plugin.d.ts +2 -2
  25. package/dist/server/mockrtc-admin-plugin.js +147 -2
  26. package/dist/server/mockrtc-admin-plugin.js.map +1 -1
  27. package/dist/server/mockrtc-server-peer.d.ts +8 -2
  28. package/dist/server/mockrtc-server-peer.js +106 -5
  29. package/dist/server/mockrtc-server-peer.js.map +1 -1
  30. package/dist/server/mockrtc-server.d.ts +11 -3
  31. package/dist/server/mockrtc-server.js +44 -6
  32. package/dist/server/mockrtc-server.js.map +1 -1
  33. package/dist/webrtc/datachannel-stream.d.ts +2 -0
  34. package/dist/webrtc/datachannel-stream.js +12 -0
  35. package/dist/webrtc/datachannel-stream.js.map +1 -1
  36. package/dist/webrtc/mediatrack-stream.d.ts +4 -0
  37. package/dist/webrtc/mediatrack-stream.js +13 -1
  38. package/dist/webrtc/mediatrack-stream.js.map +1 -1
  39. package/dist/webrtc/mockrtc-connection.d.ts +1 -1
  40. package/dist/webrtc/mockrtc-connection.js +77 -60
  41. package/dist/webrtc/mockrtc-connection.js.map +1 -1
  42. package/dist/webrtc/rtc-connection.d.ts +23 -4
  43. package/dist/webrtc/rtc-connection.js +45 -6
  44. package/dist/webrtc/rtc-connection.js.map +1 -1
  45. package/dist/webrtc-hooks.js +4 -2
  46. package/dist/webrtc-hooks.js.map +1 -1
  47. package/package.json +12 -6
  48. package/src/client/mockrtc-admin-request-builder.ts +184 -0
  49. package/src/client/mockrtc-client.ts +26 -22
  50. package/src/client/mockrtc-remote-peer.ts +9 -8
  51. package/src/handling/handler-step-definitions.ts +6 -4
  52. package/src/handling/handler-steps.ts +6 -5
  53. package/src/main-browser.ts +4 -0
  54. package/src/main.ts +18 -4
  55. package/src/mockrtc-peer.ts +41 -6
  56. package/src/mockrtc.ts +163 -1
  57. package/src/server/mockrtc-admin-plugin.ts +159 -6
  58. package/src/server/mockrtc-server-peer.ts +183 -6
  59. package/src/server/mockrtc-server.ts +75 -14
  60. package/src/webrtc/datachannel-stream.ts +16 -0
  61. package/src/webrtc/mediatrack-stream.ts +16 -3
  62. package/src/webrtc/mockrtc-connection.ts +21 -6
  63. package/src/webrtc/rtc-connection.ts +79 -14
  64. package/src/webrtc-hooks.ts +7 -4
  65. package/test/integration/events.spec.ts +536 -0
  66. package/test/integration/matching.spec.ts +68 -0
  67. package/test/integration/proxy.spec.ts +66 -1
  68. 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, this.options);
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._activePeers = {};
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;;;;;;;;;;;;AAGH,+DAA0D;AAC1D,iEAAoE;AAEpE,6DAAuD;AAEvD,MAAa,aAAa;IAEtB,YACY,UAA0B,EAAE;QAA5B,YAAO,GAAP,OAAO,CAAqB;QAiBxC,sBAAiB,GAAG,CAAO,sBAA+C,EAA8B,EAAE;YACtG,MAAM,YAAY,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;gBAC3D,OAAO,MAAM,CAAC,MAAM,CAChB,MAAM,CAAC,MAAM,CAAC,0BAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,EACpD,UAAU,CACb,CAAC;YACN,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,uCAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/D,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YACtC,OAAO,IAAI,CAAC;QAChB,CAAC,CAAA,CAAA;QAEO,iBAAY,GAAwC,EAAE,CAAC;IA5B5D,CAAC;IAEE,KAAK;8DAAmB,CAAC;KAAA;IACzB,IAAI;;YACN,MAAM,OAAO,CAAC,GAAG,CACb,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CACxB,IAAI,CAAC,KAAK,EAAE,CACf,CACJ,CAAC;YACF,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAC3B,CAAC;KAAA;IAED,SAAS;QACL,OAAO,IAAI,uCAAqB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC7D,CAAC;IAeD,IAAI,WAAW;QACX,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,EAAU;QACd,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;CAEJ;AAzCD,sCAyCC"}
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;QAsC3C,gBAAW,GAAG,IAAI,CAAC;QAxBvB,UAAU,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE;YACzB,IAAI,CAAC,IAAI,CAAC,WAAW;gBAAE,OAAO,CAAC,wCAAwC;YAEvE,4EAA4E;YAC5E,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,kEAAkE;QAClE,UAAU,CAAC,QAAQ,CAAC,GAAG,EAAE;YACrB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,gDAAgD;QAChD,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE;YACtB,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;SAC1C;IACL,CAAC;IAGD,KAAK;QACD,kFAAkF;QAClF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,KAAgC,EAAE,QAAgB,EAAE,QAAuC;QAC9F,IAAI,MAAe,CAAC;QAEpB,IAAI;YACA,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;gBACxB,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;aACrD;iBAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;gBAClC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;aAC/C;iBAAM;gBACH,MAAM,QAAQ,GAAI,KAAgB,CAAC,WAAW,CAAC,IAAI,IAAI,OAAO,KAAK,CAAC;gBACpE,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,wBAAwB,CAAC,CAAC;aACrE;SACJ;QAAC,OAAO,GAAQ,EAAE;YACf,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;SACxB;QAED,IAAI,MAAM,EAAE;YACR,QAAQ,CAAC,IAAI,CAAC,CAAC;SAClB;aAAM;YACH,QAAQ,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;SACzD;IACL,CAAC;IAED,MAAM,CAAC,QAAuC;QAC1C,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACxC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,QAAQ,CAAC,QAAsB,EAAE,QAAuC;QACpE,0DAA0D;QAC1D,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,KAAK;QACL,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACtC,CAAC;CAEJ;AArFD,8CAqFC"}
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
- sentOk = this.rawTrack.sendMessageBinary(Buffer.concat(chunks.map(c => c.chunk)));
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":"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"}
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
- this.externalConnection = this.getExternalConnection(controlMessage.id);
47
- this.emit('external-connection-attached');
48
- // We don't necessarily proxy traffic through to the external connection at this point,
49
- // that depends on the specific handling that's used here.
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
- * When proxying traffic, you effectively have four peers, each with a connection endpoint:
86
- * - The incoming RTCPeerConnection that we're mocking ('internal')
87
- * - This MockRTC connection, with an associated MockRTCPeer that it will actually connect to ('mock')
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
- // A mismatch in media streams means the external & mock peer negotiation isn't in sync!
140
- // For now we just reject this case - later we should try to prompt a renegotiation.
141
- throw new Error(`Mock has ${track.type} ${track.mid} but external does not`);
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":"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"}
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 { MockRTCSession } from '../mockrtc-peer';
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
- getLocalDescription(): Promise<RTCSessionDescriptionInit>;
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<RTCSessionDescriptionInit>;
43
- getMirroredLocalAnswer(sdpToMirror: string): Promise<RTCSessionDescriptionInit>;
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.getLocalDescription();
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.getLocalDescription();
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 === 'closed')
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
- getLocalDescription() {
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
- return localDesc;
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
- return localDesc;
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();