werift 0.24.0 → 0.24.2

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/lib/common/src/binary.js +2 -3
  2. package/lib/common/src/binary.js.map +1 -1
  3. package/lib/dtls/src/context/transport.d.ts +2 -2
  4. package/lib/dtls/src/context/transport.js +2 -2
  5. package/lib/dtls/src/context/transport.js.map +1 -1
  6. package/lib/dtls/src/socket.d.ts +3 -2
  7. package/lib/dtls/src/socket.js +2 -2
  8. package/lib/dtls/src/socket.js.map +1 -1
  9. package/lib/ice/src/ice.d.ts +20 -0
  10. package/lib/ice/src/ice.js +263 -66
  11. package/lib/ice/src/ice.js.map +1 -1
  12. package/lib/ice/src/iceBase.d.ts +22 -1
  13. package/lib/ice/src/iceBase.js +30 -1
  14. package/lib/ice/src/iceBase.js.map +1 -1
  15. package/lib/ice/src/internal/selectAddresses.d.ts +9 -0
  16. package/lib/ice/src/internal/selectAddresses.js +40 -0
  17. package/lib/ice/src/internal/selectAddresses.js.map +1 -0
  18. package/lib/ice/src/stun/protocol.d.ts +2 -2
  19. package/lib/ice/src/stun/protocol.js +17 -3
  20. package/lib/ice/src/stun/protocol.js.map +1 -1
  21. package/lib/ice/src/stun/tcpProtocol.d.ts +2 -2
  22. package/lib/ice/src/stun/tcpProtocol.js +13 -3
  23. package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
  24. package/lib/ice/src/stun/transaction.d.ts +41 -4
  25. package/lib/ice/src/stun/transaction.js +193 -24
  26. package/lib/ice/src/stun/transaction.js.map +1 -1
  27. package/lib/ice/src/turn/protocol.d.ts +3 -3
  28. package/lib/ice/src/turn/protocol.js +31 -6
  29. package/lib/ice/src/turn/protocol.js.map +1 -1
  30. package/lib/ice/src/types/model.d.ts +27 -1
  31. package/lib/ice/src/types/model.js.map +1 -1
  32. package/lib/ice/src/utils.js +2 -31
  33. package/lib/ice/src/utils.js.map +1 -1
  34. package/lib/ice-server/src/stun/attributes.js +9 -47
  35. package/lib/ice-server/src/stun/attributes.js.map +1 -1
  36. package/lib/ice-server/src/stun/ip.d.ts +12 -0
  37. package/lib/ice-server/src/stun/ip.js +88 -0
  38. package/lib/ice-server/src/stun/ip.js.map +1 -0
  39. package/lib/ice-server/src/stun/message.js +8 -0
  40. package/lib/ice-server/src/stun/message.js.map +1 -1
  41. package/lib/index.mjs +652 -234
  42. package/lib/nonstandard/index.mjs +121 -54
  43. package/lib/rtp/src/codec/av1.js +11 -5
  44. package/lib/rtp/src/codec/av1.js.map +1 -1
  45. package/lib/rtp/src/codec/leb128.d.ts +5 -0
  46. package/lib/rtp/src/codec/leb128.js +24 -0
  47. package/lib/rtp/src/codec/leb128.js.map +1 -0
  48. package/lib/rtp/src/rtp/rtx.js +4 -6
  49. package/lib/rtp/src/rtp/rtx.js.map +1 -1
  50. package/lib/rtp/src/srtp/context/context.d.ts +2 -0
  51. package/lib/rtp/src/srtp/context/context.js +12 -12
  52. package/lib/rtp/src/srtp/context/context.js.map +1 -1
  53. package/lib/sctp/src/param.js +31 -15
  54. package/lib/sctp/src/param.js.map +1 -1
  55. package/lib/sctp/src/sctp.js +10 -9
  56. package/lib/sctp/src/sctp.js.map +1 -1
  57. package/lib/webrtc/src/media/rtpSender.js +2 -3
  58. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  59. package/lib/webrtc/src/peerConnection.d.ts +2 -2
  60. package/lib/webrtc/src/sdp.js +1 -35
  61. package/lib/webrtc/src/sdp.js.map +1 -1
  62. package/lib/webrtc/src/secureTransportManager.d.ts +1 -1
  63. package/lib/webrtc/src/secureTransportManager.js +12 -0
  64. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  65. package/lib/webrtc/src/transport/dtls.d.ts +1 -1
  66. package/lib/webrtc/src/transport/sctp.js +17 -16
  67. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  68. package/package.json +1 -7
@@ -1,12 +1,51 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Transaction = void 0;
4
+ exports.resolveRequestAddress = resolveRequestAddress;
5
+ exports.normalizeTransactionOptions = normalizeTransactionOptions;
6
+ exports.addressEquals = addressEquals;
7
+ exports.buildTransactionOptions = buildTransactionOptions;
8
+ const node_dns_1 = require("node:dns");
9
+ const node_net_1 = require("node:net");
4
10
  const common_1 = require("../imports/common");
5
11
  const exceptions_1 = require("../exceptions");
6
12
  const const_1 = require("./const");
7
13
  const log = (0, common_1.debug)("werift-ice:packages/ice/src/stun/transaction.ts");
14
+ /**
15
+ * Resolve a request target to a concrete IP before creating a Transaction so
16
+ * response source-address checks match the UDP peer address (hostname ≠ IP).
17
+ */
18
+ async function resolveRequestAddress(addr, family = 0) {
19
+ if ((0, node_net_1.isIP)(addr[0])) {
20
+ return addr;
21
+ }
22
+ const looked = await node_dns_1.promises.lookup(addr[0], { family });
23
+ return [looked.address, addr[1]];
24
+ }
25
+ /**
26
+ * Normalize legacy positional args and the options-object form into one shape.
27
+ * Existing callers pass `(retransmissions?, onRequestSent?)`.
28
+ */
29
+ function normalizeTransactionOptions(retransmissionsOrOptions, onRequestSent) {
30
+ if (retransmissionsOrOptions !== null &&
31
+ typeof retransmissionsOrOptions === "object") {
32
+ return retransmissionsOrOptions;
33
+ }
34
+ // After the object branch, only number | undefined remains (legacy positional API).
35
+ const retransmissions = typeof retransmissionsOrOptions === "number"
36
+ ? retransmissionsOrOptions
37
+ : undefined;
38
+ return {
39
+ retransmissions,
40
+ onRequestSent,
41
+ };
42
+ }
43
+ /** Compare ICE transport addresses (host, port). */
44
+ function addressEquals(a, b) {
45
+ return a[0] === b[0] && a[1] === b[1];
46
+ }
8
47
  class Transaction {
9
- constructor(request, addr, protocol, retransmissions, onRequestSent) {
48
+ constructor(request, addr, protocol, retransmissionsOrOptions, onRequestSent) {
10
49
  Object.defineProperty(this, "request", {
11
50
  enumerable: true,
12
51
  configurable: true,
@@ -25,62 +64,122 @@ class Transaction {
25
64
  writable: true,
26
65
  value: protocol
27
66
  });
28
- Object.defineProperty(this, "retransmissions", {
67
+ Object.defineProperty(this, "timeoutDelay", {
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true,
71
+ value: void 0
72
+ });
73
+ Object.defineProperty(this, "ended", {
74
+ enumerable: true,
75
+ configurable: true,
76
+ writable: true,
77
+ value: false
78
+ });
79
+ Object.defineProperty(this, "tries", {
80
+ enumerable: true,
81
+ configurable: true,
82
+ writable: true,
83
+ value: 0
84
+ });
85
+ Object.defineProperty(this, "triesMax", {
86
+ enumerable: true,
87
+ configurable: true,
88
+ writable: true,
89
+ value: void 0
90
+ });
91
+ Object.defineProperty(this, "onResponse", {
29
92
  enumerable: true,
30
93
  configurable: true,
31
94
  writable: true,
32
- value: retransmissions
95
+ value: new common_1.Event()
33
96
  });
34
97
  Object.defineProperty(this, "onRequestSent", {
35
98
  enumerable: true,
36
99
  configurable: true,
37
100
  writable: true,
38
- value: onRequestSent
101
+ value: void 0
102
+ });
103
+ Object.defineProperty(this, "signal", {
104
+ enumerable: true,
105
+ configurable: true,
106
+ writable: true,
107
+ value: void 0
39
108
  });
40
- Object.defineProperty(this, "timeoutDelay", {
109
+ /** Remote address this transaction was sent to; responses must match. */
110
+ Object.defineProperty(this, "expectedAddr", {
41
111
  enumerable: true,
42
112
  configurable: true,
43
113
  writable: true,
44
- value: const_1.RETRY_RTO
114
+ value: void 0
45
115
  });
46
- Object.defineProperty(this, "ended", {
116
+ /**
117
+ * When set, protocol layers re-parse the wire response with this key so
118
+ * MESSAGE-INTEGRITY failures are rejected before responseReceived.
119
+ */
120
+ Object.defineProperty(this, "integrityKey", {
47
121
  enumerable: true,
48
122
  configurable: true,
49
123
  writable: true,
50
- value: false
124
+ value: void 0
51
125
  });
52
- Object.defineProperty(this, "tries", {
126
+ Object.defineProperty(this, "waitTimer", {
53
127
  enumerable: true,
54
128
  configurable: true,
55
129
  writable: true,
56
- value: 0
130
+ value: void 0
57
131
  });
58
- Object.defineProperty(this, "triesMax", {
132
+ Object.defineProperty(this, "waitResolve", {
59
133
  enumerable: true,
60
134
  configurable: true,
61
135
  writable: true,
62
136
  value: void 0
63
137
  });
64
- Object.defineProperty(this, "onResponse", {
138
+ Object.defineProperty(this, "onAbort", {
65
139
  enumerable: true,
66
140
  configurable: true,
67
141
  writable: true,
68
- value: new common_1.Event()
142
+ value: void 0
69
143
  });
144
+ /**
145
+ * Accept a matching authenticated non-error response from the expected
146
+ * remote address. Wrong address, missing MESSAGE-INTEGRITY (when required),
147
+ * or non-success class is rejected without completing the transaction
148
+ * (wrong address / unauthenticated responses are ignored so we keep waiting).
149
+ */
70
150
  Object.defineProperty(this, "responseReceived", {
71
151
  enumerable: true,
72
152
  configurable: true,
73
153
  writable: true,
74
154
  value: (message, addr) => {
75
- if (this.onResponse.length > 0) {
76
- if (message.messageClass === const_1.classes.RESPONSE) {
77
- this.onResponse.execute(message, addr);
78
- this.onResponse.complete();
79
- }
80
- else {
81
- this.onResponse.error(new exceptions_1.TransactionFailed(message, addr));
155
+ if (this.ended || this.onResponse.length === 0) {
156
+ return;
157
+ }
158
+ // RFC 7675 / ICE: only responses from the request's transport address.
159
+ if (!addressEquals(this.expectedAddr, addr)) {
160
+ log("ignore STUN response from unexpected address", addr, "expected", this.expectedAddr);
161
+ return;
162
+ }
163
+ // RFC 7675 authenticated consent: integrityKey requires MESSAGE-INTEGRITY.
164
+ // Wire HMAC is verified by protocol layers via parseMessage(data, key);
165
+ // this presence check is defense-in-depth if responseReceived is called
166
+ // with a constructed Message that skipped the wire re-parse path.
167
+ if (this.integrityKey) {
168
+ const hasIntegrity = message.attributesKeys.includes("MESSAGE-INTEGRITY") ||
169
+ message.attributesKeys.includes("MESSAGE-INTEGRITY-SHA256");
170
+ if (!hasIntegrity) {
171
+ log("ignore unauthenticated STUN response (MESSAGE-INTEGRITY required)");
172
+ return;
82
173
  }
83
174
  }
175
+ if (message.messageClass === const_1.classes.RESPONSE) {
176
+ this.onResponse.execute(message, addr);
177
+ this.onResponse.complete();
178
+ }
179
+ else {
180
+ // ERROR class or other non-success
181
+ this.onResponse.error(new exceptions_1.TransactionFailed(message, addr));
182
+ }
84
183
  }
85
184
  });
86
185
  Object.defineProperty(this, "run", {
@@ -89,6 +188,10 @@ class Transaction {
89
188
  writable: true,
90
189
  value: async () => {
91
190
  try {
191
+ if (this.signal?.aborted) {
192
+ throw new exceptions_1.TransactionTimeout();
193
+ }
194
+ this.attachAbortListener();
92
195
  this.retry().catch((e) => {
93
196
  log("retry failed", e);
94
197
  });
@@ -113,24 +216,90 @@ class Transaction {
113
216
  this.protocol.sendStun(this.request, this.addr).catch((e) => {
114
217
  log("send stun failed", e);
115
218
  });
116
- await new Promise((r) => setTimeout(r, this.timeoutDelay));
219
+ await this.wait(this.timeoutDelay);
117
220
  if (this.ended) {
118
221
  break;
119
222
  }
120
223
  this.timeoutDelay *= 2;
121
224
  this.tries++;
122
225
  }
123
- if (this.tries >= this.triesMax) {
226
+ if (this.tries >= this.triesMax && !this.ended) {
124
227
  log(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);
125
- this.onResponse.error(new exceptions_1.TransactionTimeout());
228
+ this.failWithTimeout();
126
229
  }
127
230
  }
128
231
  });
129
- this.triesMax = 1 + (this.retransmissions ?? const_1.RETRY_MAX);
232
+ const options = normalizeTransactionOptions(retransmissionsOrOptions, onRequestSent);
233
+ // triesMax = initial send + retransmissions
234
+ this.triesMax = 1 + (options.retransmissions ?? const_1.RETRY_MAX);
235
+ // responseTimeout is independent of retransmission count (RFC 7675 / 8445)
236
+ this.timeoutDelay = options.responseTimeout ?? const_1.RETRY_RTO;
237
+ this.onRequestSent = options.onRequestSent;
238
+ this.signal = options.signal;
239
+ this.expectedAddr = addr;
240
+ this.integrityKey = options.integrityKey;
241
+ }
242
+ attachAbortListener() {
243
+ if (!this.signal) {
244
+ return;
245
+ }
246
+ this.onAbort = () => {
247
+ this.failWithTimeout();
248
+ };
249
+ this.signal.addEventListener("abort", this.onAbort, { once: true });
250
+ }
251
+ failWithTimeout() {
252
+ if (this.ended) {
253
+ return;
254
+ }
255
+ this.ended = true;
256
+ this.clearWait();
257
+ if (this.onResponse.length > 0) {
258
+ this.onResponse.error(new exceptions_1.TransactionTimeout());
259
+ }
260
+ }
261
+ clearWait() {
262
+ if (this.waitTimer !== undefined) {
263
+ clearTimeout(this.waitTimer);
264
+ this.waitTimer = undefined;
265
+ }
266
+ const resolve = this.waitResolve;
267
+ this.waitResolve = undefined;
268
+ resolve?.();
269
+ }
270
+ wait(ms) {
271
+ return new Promise((resolve) => {
272
+ if (this.ended || this.signal?.aborted) {
273
+ resolve();
274
+ return;
275
+ }
276
+ this.waitResolve = resolve;
277
+ this.waitTimer = setTimeout(() => {
278
+ this.waitTimer = undefined;
279
+ this.waitResolve = undefined;
280
+ resolve();
281
+ }, ms);
282
+ });
130
283
  }
131
284
  cancel() {
132
285
  this.ended = true;
286
+ this.clearWait();
287
+ if (this.signal && this.onAbort) {
288
+ this.signal.removeEventListener("abort", this.onAbort);
289
+ this.onAbort = undefined;
290
+ }
133
291
  }
134
292
  }
135
293
  exports.Transaction = Transaction;
294
+ /**
295
+ * Build Transaction options for Protocol.request, folding integrityKey into
296
+ * options so response path can re-verify MESSAGE-INTEGRITY.
297
+ */
298
+ function buildTransactionOptions(integrityKey, retransmissionsOrOptions, onRequestSent) {
299
+ const options = normalizeTransactionOptions(retransmissionsOrOptions, onRequestSent);
300
+ if (integrityKey && !options.integrityKey) {
301
+ options.integrityKey = integrityKey;
302
+ }
303
+ return options;
304
+ }
136
305
  //# sourceMappingURL=transaction.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../../ice/src/stun/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Address, Event, debug } from \"../imports/common\";\n\nimport { TransactionFailed, TransactionTimeout } from \"../exceptions\";\nimport type { Protocol } from \"../types/model\";\nimport { RETRY_MAX, RETRY_RTO, classes } from \"./const\";\nimport type { Message } from \"./message\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/transaction.ts\");\n\nexport class Transaction {\n private timeoutDelay = RETRY_RTO;\n ended = false;\n private tries = 0;\n private readonly triesMax: number;\n private readonly onResponse = new Event<[Message, Address]>();\n\n constructor(\n private request: Message,\n private addr: Address,\n private protocol: Protocol,\n private retransmissions?: number,\n private onRequestSent?: (attempt: number) => void,\n ) {\n this.triesMax = 1 + (this.retransmissions ?? RETRY_MAX);\n }\n\n responseReceived = (message: Message, addr: Address) => {\n if (this.onResponse.length > 0) {\n if (message.messageClass === classes.RESPONSE) {\n this.onResponse.execute(message, addr);\n this.onResponse.complete();\n } else {\n this.onResponse.error(new TransactionFailed(message, addr));\n }\n }\n };\n\n run = async () => {\n try {\n this.retry().catch((e) => {\n log(\"retry failed\", e);\n });\n const res = await this.onResponse.asPromise();\n return res;\n } catch (error) {\n throw error;\n } finally {\n this.cancel();\n }\n };\n\n private retry = async () => {\n while (this.tries < this.triesMax && !this.ended) {\n this.onRequestSent?.(this.tries);\n this.protocol.sendStun(this.request, this.addr).catch((e) => {\n log(\"send stun failed\", e);\n });\n await new Promise((r) => setTimeout(r, this.timeoutDelay));\n if (this.ended) {\n break;\n }\n this.timeoutDelay *= 2;\n this.tries++;\n }\n if (this.tries >= this.triesMax) {\n log(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);\n this.onResponse.error(new TransactionTimeout());\n }\n };\n\n cancel() {\n this.ended = true;\n }\n}\n"]}
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../../ice/src/stun/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as dns } from \"node:dns\";\nimport { isIP } from \"node:net\";\n\nimport { type Address, Event, debug } from \"../imports/common\";\n\nimport { TransactionFailed, TransactionTimeout } from \"../exceptions\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { RETRY_MAX, RETRY_RTO, classes } from \"./const\";\nimport type { Message } from \"./message\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/transaction.ts\");\n\n/**\n * Resolve a request target to a concrete IP before creating a Transaction so\n * response source-address checks match the UDP peer address (hostname ≠ IP).\n */\nexport async function resolveRequestAddress(\n addr: Address,\n family: 0 | 4 | 6 = 0,\n): Promise<Address> {\n if (isIP(addr[0])) {\n return addr;\n }\n const looked = await dns.lookup(addr[0], { family });\n return [looked.address, addr[1]];\n}\n\n/**\n * Normalize legacy positional args and the options-object form into one shape.\n * Existing callers pass `(retransmissions?, onRequestSent?)`.\n */\nexport function normalizeTransactionOptions(\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n): TransactionRequestOptions {\n if (\n retransmissionsOrOptions !== null &&\n typeof retransmissionsOrOptions === \"object\"\n ) {\n return retransmissionsOrOptions;\n }\n // After the object branch, only number | undefined remains (legacy positional API).\n const retransmissions =\n typeof retransmissionsOrOptions === \"number\"\n ? retransmissionsOrOptions\n : undefined;\n return {\n retransmissions,\n onRequestSent,\n };\n}\n\n/** Compare ICE transport addresses (host, port). */\nexport function addressEquals(a: Address, b: Address): boolean {\n return a[0] === b[0] && a[1] === b[1];\n}\n\nexport class Transaction {\n private timeoutDelay: number;\n ended = false;\n private tries = 0;\n private readonly triesMax: number;\n private readonly onResponse = new Event<[Message, Address]>();\n private readonly onRequestSent?: (attempt: number) => void;\n private readonly signal?: AbortSignal;\n /** Remote address this transaction was sent to; responses must match. */\n readonly expectedAddr: Address;\n /**\n * When set, protocol layers re-parse the wire response with this key so\n * MESSAGE-INTEGRITY failures are rejected before responseReceived.\n */\n readonly integrityKey?: Buffer;\n private waitTimer?: ReturnType<typeof setTimeout>;\n private waitResolve?: () => void;\n private onAbort?: () => void;\n\n constructor(\n private request: Message,\n private addr: Address,\n private protocol: Protocol,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n const options = normalizeTransactionOptions(\n retransmissionsOrOptions,\n onRequestSent,\n );\n // triesMax = initial send + retransmissions\n this.triesMax = 1 + (options.retransmissions ?? RETRY_MAX);\n // responseTimeout is independent of retransmission count (RFC 7675 / 8445)\n this.timeoutDelay = options.responseTimeout ?? RETRY_RTO;\n this.onRequestSent = options.onRequestSent;\n this.signal = options.signal;\n this.expectedAddr = addr;\n this.integrityKey = options.integrityKey;\n }\n\n /**\n * Accept a matching authenticated non-error response from the expected\n * remote address. Wrong address, missing MESSAGE-INTEGRITY (when required),\n * or non-success class is rejected without completing the transaction\n * (wrong address / unauthenticated responses are ignored so we keep waiting).\n */\n responseReceived = (message: Message, addr: Address) => {\n if (this.ended || this.onResponse.length === 0) {\n return;\n }\n\n // RFC 7675 / ICE: only responses from the request's transport address.\n if (!addressEquals(this.expectedAddr, addr)) {\n log(\n \"ignore STUN response from unexpected address\",\n addr,\n \"expected\",\n this.expectedAddr,\n );\n return;\n }\n\n // RFC 7675 authenticated consent: integrityKey requires MESSAGE-INTEGRITY.\n // Wire HMAC is verified by protocol layers via parseMessage(data, key);\n // this presence check is defense-in-depth if responseReceived is called\n // with a constructed Message that skipped the wire re-parse path.\n if (this.integrityKey) {\n const hasIntegrity =\n message.attributesKeys.includes(\"MESSAGE-INTEGRITY\") ||\n message.attributesKeys.includes(\"MESSAGE-INTEGRITY-SHA256\");\n if (!hasIntegrity) {\n log(\n \"ignore unauthenticated STUN response (MESSAGE-INTEGRITY required)\",\n );\n return;\n }\n }\n\n if (message.messageClass === classes.RESPONSE) {\n this.onResponse.execute(message, addr);\n this.onResponse.complete();\n } else {\n // ERROR class or other non-success\n this.onResponse.error(new TransactionFailed(message, addr));\n }\n };\n\n run = async () => {\n try {\n if (this.signal?.aborted) {\n throw new TransactionTimeout();\n }\n this.attachAbortListener();\n this.retry().catch((e) => {\n log(\"retry failed\", e);\n });\n const res = await this.onResponse.asPromise();\n return res;\n } catch (error) {\n throw error;\n } finally {\n this.cancel();\n }\n };\n\n private attachAbortListener() {\n if (!this.signal) {\n return;\n }\n this.onAbort = () => {\n this.failWithTimeout();\n };\n this.signal.addEventListener(\"abort\", this.onAbort, { once: true });\n }\n\n private failWithTimeout() {\n if (this.ended) {\n return;\n }\n this.ended = true;\n this.clearWait();\n if (this.onResponse.length > 0) {\n this.onResponse.error(new TransactionTimeout());\n }\n }\n\n private clearWait() {\n if (this.waitTimer !== undefined) {\n clearTimeout(this.waitTimer);\n this.waitTimer = undefined;\n }\n const resolve = this.waitResolve;\n this.waitResolve = undefined;\n resolve?.();\n }\n\n private wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n if (this.ended || this.signal?.aborted) {\n resolve();\n return;\n }\n this.waitResolve = resolve;\n this.waitTimer = setTimeout(() => {\n this.waitTimer = undefined;\n this.waitResolve = undefined;\n resolve();\n }, ms);\n });\n }\n\n private retry = async () => {\n while (this.tries < this.triesMax && !this.ended) {\n this.onRequestSent?.(this.tries);\n this.protocol.sendStun(this.request, this.addr).catch((e) => {\n log(\"send stun failed\", e);\n });\n await this.wait(this.timeoutDelay);\n if (this.ended) {\n break;\n }\n this.timeoutDelay *= 2;\n this.tries++;\n }\n if (this.tries >= this.triesMax && !this.ended) {\n log(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);\n this.failWithTimeout();\n }\n };\n\n cancel() {\n this.ended = true;\n this.clearWait();\n if (this.signal && this.onAbort) {\n this.signal.removeEventListener(\"abort\", this.onAbort);\n this.onAbort = undefined;\n }\n }\n}\n\n/**\n * Build Transaction options for Protocol.request, folding integrityKey into\n * options so response path can re-verify MESSAGE-INTEGRITY.\n */\nexport function buildTransactionOptions(\n integrityKey: Buffer | undefined,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n): TransactionRequestOptions {\n const options = normalizeTransactionOptions(\n retransmissionsOrOptions,\n onRequestSent,\n );\n if (integrityKey && !options.integrityKey) {\n options.integrityKey = integrityKey;\n }\n return options;\n}\n"]}
@@ -2,7 +2,7 @@ import type { Candidate } from "../candidate";
2
2
  import { type Address, Event, type InterfaceAddresses, type TlsConnectionOptions, type Transport } from "../imports/common";
3
3
  import { Message } from "../stun/message";
4
4
  import { Transaction } from "../stun/transaction";
5
- import type { Protocol } from "../types/model";
5
+ import type { Protocol, TransactionRequestOptions } from "../types/model";
6
6
  export declare class StunOverTurnProtocol implements Protocol {
7
7
  turn: TurnProtocol;
8
8
  static type: string;
@@ -13,7 +13,7 @@ export declare class StunOverTurnProtocol implements Protocol {
13
13
  onDataReceived: Event<[Buffer]>;
14
14
  constructor(turn: TurnProtocol);
15
15
  private handleStunMessage;
16
- request(request: Message, addr: Address, integrityKey?: Buffer, _retransmissions?: number, onRequestSent?: (attempt: number) => void): Promise<[Message, readonly [string, number]]>;
16
+ request(request: Message, addr: Address, integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): Promise<[Message, readonly [string, number]]>;
17
17
  connectionMade(): Promise<void>;
18
18
  sendData(data: Buffer, addr: Address): Promise<void>;
19
19
  sendStun(message: Message, addr: Address): Promise<void>;
@@ -65,7 +65,7 @@ export declare class TurnProtocol implements Protocol {
65
65
  private send;
66
66
  private createPermission;
67
67
  private refresh;
68
- request(request: Message, addr: Address, _integrityKey?: Buffer, _retransmissions?: number, onRequestSent?: (attempt: number) => void): Promise<[Message, Address]>;
68
+ request(request: Message, addr: Address, _integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): Promise<[Message, Address]>;
69
69
  requestWithRetry(request: Message, addr: Address): Promise<[Message, Address]>;
70
70
  sendData(data: Buffer, addr: Address): Promise<void>;
71
71
  getPermission(addr: Address): Promise<void>;
@@ -73,7 +73,14 @@ class StunOverTurnProtocol {
73
73
  message.messageClass === const_1.classes.ERROR) {
74
74
  const transaction = this.turn.transactions[message.transactionIdHex];
75
75
  if (transaction) {
76
- transaction.responseReceived(message, addr);
76
+ const verified = transaction.integrityKey
77
+ ? (0, message_1.parseMessage)(data, transaction.integrityKey)
78
+ : message;
79
+ if (!verified) {
80
+ log("STUN over TURN response failed MESSAGE-INTEGRITY check");
81
+ return;
82
+ }
83
+ transaction.responseReceived(verified, addr);
77
84
  }
78
85
  }
79
86
  else if (message.messageClass === const_1.classes.REQUEST) {
@@ -91,7 +98,7 @@ class StunOverTurnProtocol {
91
98
  })
92
99
  .disposer(this.disposer);
93
100
  }
94
- async request(request, addr, integrityKey, _retransmissions, onRequestSent) {
101
+ async request(request, addr, integrityKey, retransmissionsOrOptions, onRequestSent) {
95
102
  if (this.turn.transactions[request.transactionIdHex]) {
96
103
  throw new Error("exist");
97
104
  }
@@ -99,7 +106,13 @@ class StunOverTurnProtocol {
99
106
  request.addMessageIntegrity(integrityKey);
100
107
  request.addFingerprint();
101
108
  }
102
- const transaction = new transaction_1.Transaction(request, addr, this, undefined, onRequestSent);
109
+ // Peer-facing STUN over TURN must honor retransmissions/responseTimeout
110
+ // (consent uses retransmissions: 0). Do not confuse with TURN server
111
+ // allocation/refresh policy on TurnProtocol.
112
+ // Peer addresses are already IPs from candidates; resolve for safety.
113
+ const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr);
114
+ const options = (0, transaction_1.buildTransactionOptions)(integrityKey, retransmissionsOrOptions, onRequestSent);
115
+ const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
103
116
  this.turn.transactions[request.transactionIdHex] = transaction;
104
117
  try {
105
118
  return await transaction.run();
@@ -362,7 +375,14 @@ class TurnProtocol {
362
375
  message.messageClass === const_1.classes.ERROR) {
363
376
  const transaction = this.transactions[message.transactionIdHex];
364
377
  if (transaction) {
365
- transaction.responseReceived(message, addr);
378
+ const verified = transaction.integrityKey
379
+ ? (0, message_1.parseMessage)(data, transaction.integrityKey)
380
+ : message;
381
+ if (!verified) {
382
+ log("TURN STUN response failed MESSAGE-INTEGRITY check");
383
+ return;
384
+ }
385
+ transaction.responseReceived(verified, addr);
366
386
  }
367
387
  }
368
388
  else if (message.messageClass === const_1.classes.REQUEST) {
@@ -417,7 +437,7 @@ class TurnProtocol {
417
437
  throw e;
418
438
  });
419
439
  }
420
- async request(request, addr, _integrityKey, _retransmissions, onRequestSent) {
440
+ async request(request, addr, _integrityKey, retransmissionsOrOptions, onRequestSent) {
421
441
  if (this.transactions[request.transactionIdHex]) {
422
442
  throw new Error("exist");
423
443
  }
@@ -429,7 +449,12 @@ class TurnProtocol {
429
449
  .addMessageIntegrity(this.integrityKey)
430
450
  .addFingerprint();
431
451
  }
432
- const transaction = new transaction_1.Transaction(request, addr, this, undefined, onRequestSent);
452
+ // TURN server allocation/refresh uses default STUN retry policy unless
453
+ // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.
454
+ // Prefer the TURN session integrity key for response verification.
455
+ const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr);
456
+ const options = (0, transaction_1.buildTransactionOptions)(this.integrityKey, retransmissionsOrOptions, onRequestSent);
457
+ const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
433
458
  this.transactions[request.transactionIdHex] = transaction;
434
459
  try {
435
460
  return await transaction.run();
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout } from \"timers/promises\";\n\nimport { makeTurnIntegrityKey } from \"../../../ice-server/src/turn/auth\";\nimport type { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { type Cancelable, cancelable, randomTransactionId } from \"../helper\";\nimport {\n type Address,\n Event,\n EventDisposer,\n type InterfaceAddresses,\n TcpTransport,\n type TlsConnectionOptions,\n TlsTransport,\n type Transport,\n UdpTransport,\n bufferReader,\n debug,\n int,\n} from \"../imports/common\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, paddingLength, parseMessage } from \"../stun/message\";\nimport { Transaction } from \"../stun/transaction\";\nimport {\n decodeChannelData,\n encodeChannelData,\n isChannelData,\n padTurnFrame,\n splitTurnTcpFrames,\n} from \"./frame\";\n\nimport type { Protocol } from \"../types/model\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst DEFAULT_CHANNEL_REFRESH_TIME = 500;\nconst DEFAULT_ALLOCATION_LIFETIME = 600;\nconst UDP_TRANSPORT = 0x11000000;\n\nfunction isStreamTransport(transport: Transport) {\n return transport.type === \"tcp\" || transport.type === \"tls\";\n}\n\nexport class StunOverTurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = StunOverTurnProtocol.type;\n localCandidate!: Candidate;\n private disposer = new EventDisposer();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n\n constructor(public turn: TurnProtocol) {\n turn.onData\n .subscribe((data, addr) => {\n this.handleStunMessage(data, addr);\n })\n .disposer(this.disposer);\n }\n\n private handleStunMessage = (data: Buffer, addr: Address) => {\n try {\n const message = parseMessage(data);\n if (!message) {\n this.onDataReceived.execute(data);\n return;\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n if (transaction) {\n transaction.responseReceived(message, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"datagramReceived error\", error);\n }\n };\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n _retransmissions?: number,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.turn.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const transaction = new Transaction(\n request,\n addr,\n this,\n undefined,\n onRequestSent,\n );\n this.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n async close() {\n this.disposer.dispose();\n return this.turn.close();\n }\n}\n\nexport class TurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = TurnProtocol.type;\n readonly onData = new Event<[Buffer, Address]>();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n localCandidate!: Candidate;\n transactions: { [hexId: string]: Transaction } = {};\n private refreshHandle?: Cancelable<void>;\n private channelNumber = 0x4000;\n private channelByAddr: {\n [addr: string]: { number: number; address: Address };\n } = {};\n private addrByChannel: { [channel: number]: Address } = {};\n /**sec */\n private channelRefreshTime: number;\n private channelBinding?: Promise<void>;\n private channelRefreshAt = 0;\n private tcpBuffer: Buffer = Buffer.alloc(0);\n private permissionByAddr: { [addr: string]: boolean } = {};\n private creatingPermission: Promise<void> = Promise.resolve();\n\n constructor(\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport,\n public options: {\n /**sec */\n channelRefreshTime?: number;\n } = {},\n ) {\n this.channelRefreshTime =\n this.options.channelRefreshTime ?? DEFAULT_CHANNEL_REFRESH_TIME;\n }\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.dataReceived(data, addr);\n };\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.requestWithRetry(request, this.server).catch(\n (e) => {\n log(\"connect error\", e);\n throw e;\n },\n );\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n const exp = response.getAttributeValue(\"LIFETIME\");\n log(\"connect\", this.relayedAddress, this.mappedAddress, { exp });\n\n this.refresh(exp);\n }\n\n private handleChannelData(data: Buffer) {\n const decoded = decodeChannelData(data);\n const addr = decoded && this.addrByChannel[decoded.channelNumber];\n\n if (addr && decoded) {\n this.onData.execute(decoded.data, addr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n throw new Error(\"not stun message\");\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) {\n transaction.responseReceived(message, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onData.execute(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n const peerAddress =\n message.getAttributeValue(\"XOR-PEER-ADDRESS\") ?? addr;\n this.onData.execute(buf, peerAddress);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private dataReceived(data: Buffer, addr: Address) {\n const datagramReceived = (data: Buffer, addr: Address) => {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n };\n\n if (isStreamTransport(this.transport)) {\n this.tcpBuffer = Buffer.concat([this.tcpBuffer, data]);\n const { frames, rest } = splitTurnTcpFrames(this.tcpBuffer);\n this.tcpBuffer = rest;\n for (const frame of frames) {\n datagramReceived(frame, addr);\n }\n } else {\n datagramReceived(data, addr);\n }\n }\n\n private async send(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(\n isStreamTransport(this.transport) ? padTurnFrame(data) : data,\n addr,\n );\n }\n\n private async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n await this.request(request, this.server).catch((e) => {\n request;\n throw e;\n });\n }\n\n private refresh = (exp: number) => {\n this.refreshHandle = cancelable<void>(async (_, __, onCancel) => {\n let run = true;\n onCancel.once(() => {\n run = false;\n });\n\n while (run) {\n // refresh before expire\n const delay = (5 / 6) * exp * 1000;\n log(\"refresh delay\", delay, { exp });\n await setTimeout(delay);\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", exp);\n\n try {\n const [message] = await this.requestWithRetry(request, this.server);\n exp = message.getAttributeValue(\"LIFETIME\");\n log(\"refresh\", { exp });\n } catch (error) {\n log(\"refresh error\", error);\n }\n }\n });\n };\n\n async request(\n request: Message,\n addr: Address,\n _integrityKey?: Buffer,\n _retransmissions?: number,\n onRequestSent?: (attempt: number) => void,\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n const transaction = new Transaction(\n request,\n addr,\n this,\n undefined,\n onRequestSent,\n );\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async requestWithRetry(\n request: Message,\n addr: Address,\n ): Promise<[Message, Address]> {\n let message: Message, address: Address;\n try {\n [message, address] = await this.request(request, addr);\n } catch (error) {\n if (error instanceof TransactionFailed == false) {\n log(\"requestWithRetry error\", error);\n throw error;\n }\n\n // resolve dns address\n this.server = error.addr;\n\n const [errorCode] = error.response.getAttributeValue(\"ERROR-CODE\");\n const nonce = error.response.getAttributeValue(\"NONCE\");\n const realm = error.response.getAttributeValue(\"REALM\");\n\n if (\n ((errorCode === 401 && realm) || (errorCode === 438 && this.realm)) &&\n nonce\n ) {\n log(\"retry with nonce\", errorCode);\n\n this.nonce = nonce;\n if (errorCode === 401) {\n this.realm = realm;\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password,\n );\n\n request.transactionId = randomTransactionId();\n [message, address] = await this.request(request, this.server);\n } else {\n throw error;\n }\n }\n return [message!, address!];\n }\n\n async sendData(data: Buffer, addr: Address) {\n const channel = await this.getChannel(addr).catch((e) => {\n return new Error(\"channelBind error\");\n });\n\n if (channel instanceof Error) {\n await this.getPermission(addr);\n const indicate = new Message(methods.SEND, classes.INDICATION)\n .setAttribute(\"DATA\", data)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n\n await this.sendStun(indicate, this.server);\n return;\n }\n\n await this.send(encodeChannelData(channel.number, data), this.server);\n }\n\n async getPermission(addr: Address) {\n await this.creatingPermission;\n\n const permitted = this.permissionByAddr[addr.join(\":\")];\n if (!permitted) {\n this.creatingPermission = this.createPermission(addr);\n this.permissionByAddr[addr.join(\":\")] = true;\n await this.creatingPermission.catch((e) => {\n log(\"createPermission error\", e);\n throw e;\n });\n }\n }\n\n async getChannel(addr: Address) {\n if (this.channelBinding) {\n await this.channelBinding;\n }\n\n let channel = this.channelByAddr[addr.join(\":\")];\n\n if (!channel) {\n this.channelByAddr[addr.join(\":\")] = {\n number: this.channelNumber++,\n address: addr,\n };\n channel = this.channelByAddr[addr.join(\":\")];\n this.addrByChannel[channel.number] = addr;\n\n this.channelBinding = this.channelBind(channel.number, addr);\n await this.channelBinding.catch((e) => {\n log(\"channelBind error\", e);\n throw e;\n });\n this.channelRefreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n this.channelBinding = undefined;\n log(\"channelBind\", channel);\n } else if (this.channelRefreshAt < int(Date.now() / 1000)) {\n this.channelBinding = this.channelBind(channel.number, addr);\n this.channelRefreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n await this.channelBinding.catch((e) => {\n log(\"channelBind error\", e);\n throw e;\n });\n this.channelBinding = undefined;\n log(\"channelBind refresh\", channel);\n }\n return channel;\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.requestWithRetry(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error(\"should be CHANNEL_BIND\");\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.send(message.bytes, addr);\n }\n\n async close() {\n this.refreshHandle?.resolve?.();\n await this.transport.close();\n }\n}\n\nexport interface TurnClientConfig {\n address: Address;\n username: string;\n password: string;\n}\nexport interface TurnClientOptions {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n}\n\nexport async function createTurnClient(\n { address, username, password }: TurnClientConfig,\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: TurnClientOptions = {},\n) {\n lifetime ??= DEFAULT_ALLOCATION_LIFETIME;\n transportType ??= ssl ? \"tls\" : \"udp\";\n\n const transport =\n transportType === \"udp\"\n ? await UdpTransport.init(\"udp4\", { portRange, interfaceAddresses })\n : transportType === \"tcp\"\n ? await TcpTransport.init(address)\n : await TlsTransport.init(address, tlsOptions);\n\n const turn = new TurnProtocol(\n address,\n username,\n password,\n lifetime,\n transport,\n );\n\n await turn.connectionMade();\n return turn;\n}\n\nexport async function createStunOverTurnClient(\n {\n address,\n username,\n password,\n }: {\n address: Address;\n username: string;\n password: string;\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n } = {},\n) {\n const turn = await createTurnClient(\n {\n address,\n username,\n password,\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n },\n );\n const turnTransport = new StunOverTurnProtocol(turn);\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string,\n) {\n return makeTurnIntegrityKey(username, realm, password);\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout } from \"timers/promises\";\n\nimport { makeTurnIntegrityKey } from \"../../../ice-server/src/turn/auth\";\nimport type { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { type Cancelable, cancelable, randomTransactionId } from \"../helper\";\nimport {\n type Address,\n Event,\n EventDisposer,\n type InterfaceAddresses,\n TcpTransport,\n type TlsConnectionOptions,\n TlsTransport,\n type Transport,\n UdpTransport,\n bufferReader,\n debug,\n int,\n} from \"../imports/common\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, paddingLength, parseMessage } from \"../stun/message\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"../stun/transaction\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport {\n decodeChannelData,\n encodeChannelData,\n isChannelData,\n padTurnFrame,\n splitTurnTcpFrames,\n} from \"./frame\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst DEFAULT_CHANNEL_REFRESH_TIME = 500;\nconst DEFAULT_ALLOCATION_LIFETIME = 600;\nconst UDP_TRANSPORT = 0x11000000;\n\nfunction isStreamTransport(transport: Transport) {\n return transport.type === \"tcp\" || transport.type === \"tls\";\n}\n\nexport class StunOverTurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = StunOverTurnProtocol.type;\n localCandidate!: Candidate;\n private disposer = new EventDisposer();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n\n constructor(public turn: TurnProtocol) {\n turn.onData\n .subscribe((data, addr) => {\n this.handleStunMessage(data, addr);\n })\n .disposer(this.disposer);\n }\n\n private handleStunMessage = (data: Buffer, addr: Address) => {\n try {\n const message = parseMessage(data);\n if (!message) {\n this.onDataReceived.execute(data);\n return;\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN over TURN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"datagramReceived error\", error);\n }\n };\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.turn.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Peer-facing STUN over TURN must honor retransmissions/responseTimeout\n // (consent uses retransmissions: 0). Do not confuse with TURN server\n // allocation/refresh policy on TurnProtocol.\n // Peer addresses are already IPs from candidates; resolve for safety.\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n async close() {\n this.disposer.dispose();\n return this.turn.close();\n }\n}\n\nexport class TurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = TurnProtocol.type;\n readonly onData = new Event<[Buffer, Address]>();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n localCandidate!: Candidate;\n transactions: { [hexId: string]: Transaction } = {};\n private refreshHandle?: Cancelable<void>;\n private channelNumber = 0x4000;\n private channelByAddr: {\n [addr: string]: { number: number; address: Address };\n } = {};\n private addrByChannel: { [channel: number]: Address } = {};\n /**sec */\n private channelRefreshTime: number;\n private channelBinding?: Promise<void>;\n private channelRefreshAt = 0;\n private tcpBuffer: Buffer = Buffer.alloc(0);\n private permissionByAddr: { [addr: string]: boolean } = {};\n private creatingPermission: Promise<void> = Promise.resolve();\n\n constructor(\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport,\n public options: {\n /**sec */\n channelRefreshTime?: number;\n } = {},\n ) {\n this.channelRefreshTime =\n this.options.channelRefreshTime ?? DEFAULT_CHANNEL_REFRESH_TIME;\n }\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.dataReceived(data, addr);\n };\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.requestWithRetry(request, this.server).catch(\n (e) => {\n log(\"connect error\", e);\n throw e;\n },\n );\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n const exp = response.getAttributeValue(\"LIFETIME\");\n log(\"connect\", this.relayedAddress, this.mappedAddress, { exp });\n\n this.refresh(exp);\n }\n\n private handleChannelData(data: Buffer) {\n const decoded = decodeChannelData(data);\n const addr = decoded && this.addrByChannel[decoded.channelNumber];\n\n if (addr && decoded) {\n this.onData.execute(decoded.data, addr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n throw new Error(\"not stun message\");\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"TURN STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onData.execute(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n const peerAddress =\n message.getAttributeValue(\"XOR-PEER-ADDRESS\") ?? addr;\n this.onData.execute(buf, peerAddress);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private dataReceived(data: Buffer, addr: Address) {\n const datagramReceived = (data: Buffer, addr: Address) => {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n };\n\n if (isStreamTransport(this.transport)) {\n this.tcpBuffer = Buffer.concat([this.tcpBuffer, data]);\n const { frames, rest } = splitTurnTcpFrames(this.tcpBuffer);\n this.tcpBuffer = rest;\n for (const frame of frames) {\n datagramReceived(frame, addr);\n }\n } else {\n datagramReceived(data, addr);\n }\n }\n\n private async send(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(\n isStreamTransport(this.transport) ? padTurnFrame(data) : data,\n addr,\n );\n }\n\n private async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n await this.request(request, this.server).catch((e) => {\n request;\n throw e;\n });\n }\n\n private refresh = (exp: number) => {\n this.refreshHandle = cancelable<void>(async (_, __, onCancel) => {\n let run = true;\n onCancel.once(() => {\n run = false;\n });\n\n while (run) {\n // refresh before expire\n const delay = (5 / 6) * exp * 1000;\n log(\"refresh delay\", delay, { exp });\n await setTimeout(delay);\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", exp);\n\n try {\n const [message] = await this.requestWithRetry(request, this.server);\n exp = message.getAttributeValue(\"LIFETIME\");\n log(\"refresh\", { exp });\n } catch (error) {\n log(\"refresh error\", error);\n }\n }\n });\n };\n\n async request(\n request: Message,\n addr: Address,\n _integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n // TURN server allocation/refresh uses default STUN retry policy unless\n // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.\n // Prefer the TURN session integrity key for response verification.\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n this.integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async requestWithRetry(\n request: Message,\n addr: Address,\n ): Promise<[Message, Address]> {\n let message: Message, address: Address;\n try {\n [message, address] = await this.request(request, addr);\n } catch (error) {\n if (error instanceof TransactionFailed == false) {\n log(\"requestWithRetry error\", error);\n throw error;\n }\n\n // resolve dns address\n this.server = error.addr;\n\n const [errorCode] = error.response.getAttributeValue(\"ERROR-CODE\");\n const nonce = error.response.getAttributeValue(\"NONCE\");\n const realm = error.response.getAttributeValue(\"REALM\");\n\n if (\n ((errorCode === 401 && realm) || (errorCode === 438 && this.realm)) &&\n nonce\n ) {\n log(\"retry with nonce\", errorCode);\n\n this.nonce = nonce;\n if (errorCode === 401) {\n this.realm = realm;\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password,\n );\n\n request.transactionId = randomTransactionId();\n [message, address] = await this.request(request, this.server);\n } else {\n throw error;\n }\n }\n return [message!, address!];\n }\n\n async sendData(data: Buffer, addr: Address) {\n const channel = await this.getChannel(addr).catch((e) => {\n return new Error(\"channelBind error\");\n });\n\n if (channel instanceof Error) {\n await this.getPermission(addr);\n const indicate = new Message(methods.SEND, classes.INDICATION)\n .setAttribute(\"DATA\", data)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n\n await this.sendStun(indicate, this.server);\n return;\n }\n\n await this.send(encodeChannelData(channel.number, data), this.server);\n }\n\n async getPermission(addr: Address) {\n await this.creatingPermission;\n\n const permitted = this.permissionByAddr[addr.join(\":\")];\n if (!permitted) {\n this.creatingPermission = this.createPermission(addr);\n this.permissionByAddr[addr.join(\":\")] = true;\n await this.creatingPermission.catch((e) => {\n log(\"createPermission error\", e);\n throw e;\n });\n }\n }\n\n async getChannel(addr: Address) {\n if (this.channelBinding) {\n await this.channelBinding;\n }\n\n let channel = this.channelByAddr[addr.join(\":\")];\n\n if (!channel) {\n this.channelByAddr[addr.join(\":\")] = {\n number: this.channelNumber++,\n address: addr,\n };\n channel = this.channelByAddr[addr.join(\":\")];\n this.addrByChannel[channel.number] = addr;\n\n this.channelBinding = this.channelBind(channel.number, addr);\n await this.channelBinding.catch((e) => {\n log(\"channelBind error\", e);\n throw e;\n });\n this.channelRefreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n this.channelBinding = undefined;\n log(\"channelBind\", channel);\n } else if (this.channelRefreshAt < int(Date.now() / 1000)) {\n this.channelBinding = this.channelBind(channel.number, addr);\n this.channelRefreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n await this.channelBinding.catch((e) => {\n log(\"channelBind error\", e);\n throw e;\n });\n this.channelBinding = undefined;\n log(\"channelBind refresh\", channel);\n }\n return channel;\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.requestWithRetry(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error(\"should be CHANNEL_BIND\");\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.send(message.bytes, addr);\n }\n\n async close() {\n this.refreshHandle?.resolve?.();\n await this.transport.close();\n }\n}\n\nexport interface TurnClientConfig {\n address: Address;\n username: string;\n password: string;\n}\nexport interface TurnClientOptions {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n}\n\nexport async function createTurnClient(\n { address, username, password }: TurnClientConfig,\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: TurnClientOptions = {},\n) {\n lifetime ??= DEFAULT_ALLOCATION_LIFETIME;\n transportType ??= ssl ? \"tls\" : \"udp\";\n\n const transport =\n transportType === \"udp\"\n ? await UdpTransport.init(\"udp4\", { portRange, interfaceAddresses })\n : transportType === \"tcp\"\n ? await TcpTransport.init(address)\n : await TlsTransport.init(address, tlsOptions);\n\n const turn = new TurnProtocol(\n address,\n username,\n password,\n lifetime,\n transport,\n );\n\n await turn.connectionMade();\n return turn;\n}\n\nexport async function createStunOverTurnClient(\n {\n address,\n username,\n password,\n }: {\n address: Address;\n username: string;\n password: string;\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n } = {},\n) {\n const turn = await createTurnClient(\n {\n address,\n username,\n password,\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n },\n );\n const turnTransport = new StunOverTurnProtocol(turn);\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string,\n) {\n return makeTurnIntegrityKey(username, realm, password);\n}\n"]}