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
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.selectAddressesFromInterfaces = selectAddressesFromInterfaces;
4
+ const common_1 = require("../imports/common");
5
+ /**
6
+ * Interface 辞書から host 候補アドレスを選別する(package-private)。
7
+ * 公開 barrel (`src/index.ts`) からは export しない。
8
+ * テストは本 helper への依存注入で行う。
9
+ */
10
+ function selectAddressesFromInterfaces(interfaces, family, options = {}, isLinkLocal) {
11
+ // https://chromium.googlesource.com/external/webrtc/+/master/rtc_base/network.cc#236
12
+ const costlyNetworks = ["ipsec", "tun", "utun", "tap"];
13
+ const banNetworks = ["vmnet", "veth"];
14
+ const { useLinkLocalAddress } = options;
15
+ const all = Object.keys(interfaces)
16
+ .map((nic) => {
17
+ for (const word of [...costlyNetworks, ...banNetworks]) {
18
+ if (nic.startsWith(word)) {
19
+ return {
20
+ nic,
21
+ addresses: [],
22
+ };
23
+ }
24
+ }
25
+ const addresses = (interfaces[nic] ?? []).filter((details) => (0, common_1.normalizeFamilyNodeV18)(details.family) === family &&
26
+ !details.internal &&
27
+ (useLinkLocalAddress ? true : !isLinkLocal(details)));
28
+ return {
29
+ nic,
30
+ addresses: addresses.map((address) => address.address),
31
+ };
32
+ })
33
+ .filter((address) => !!address);
34
+ // os.networkInterfaces doesn't actually return addresses in a good order.
35
+ // have seen instances where en0 (ethernet) is after en1 (wlan), etc.
36
+ // eth0 > eth1
37
+ all.sort((a, b) => a.nic.localeCompare(b.nic));
38
+ return Object.values(all).flatMap((entry) => entry.addresses);
39
+ }
40
+ //# sourceMappingURL=selectAddresses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectAddresses.js","sourceRoot":"","sources":["../../../../../ice/src/internal/selectAddresses.ts"],"names":[],"mappings":";;AAQA,sEAyCC;AAhDD,8CAA2D;AAE3D;;;;GAIG;AACH,SAAgB,6BAA6B,CAC3C,UAA8D,EAC9D,MAAc,EACd,UAEI,EAAE,EACN,WAAuD;IAEvD,qFAAqF;IACrF,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACtC,MAAM,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAC;IAExC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;SAChC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,cAAc,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC;YACvD,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,OAAO;oBACL,GAAG;oBACH,SAAS,EAAE,EAAc;iBAC1B,CAAC;YACJ,CAAC;QACH,CAAC;QACD,MAAM,SAAS,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAC9C,CAAC,OAAO,EAAE,EAAE,CACV,IAAA,+BAAsB,EAAC,OAAO,CAAC,MAAM,CAAC,KAAK,MAAM;YACjD,CAAC,OAAO,CAAC,QAAQ;YACjB,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CACvD,CAAC;QACF,OAAO;YACL,GAAG;YACH,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;SACvD,CAAC;IACJ,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAElC,0EAA0E;IAC1E,qEAAqE;IACrE,cAAc;IACd,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AAChE,CAAC","sourcesContent":["import type * as os from \"node:os\";\nimport { normalizeFamilyNodeV18 } from \"../imports/common\";\n\n/**\n * Interface 辞書から host 候補アドレスを選別する(package-private)。\n * 公開 barrel (`src/index.ts`) からは export しない。\n * テストは本 helper への依存注入で行う。\n */\nexport function selectAddressesFromInterfaces(\n interfaces: NodeJS.Dict<os.NetworkInterfaceInfo[] | undefined>,\n family: number,\n options: {\n useLinkLocalAddress?: boolean;\n } = {},\n isLinkLocal: (info: os.NetworkInterfaceInfo) => boolean,\n): string[] {\n // https://chromium.googlesource.com/external/webrtc/+/master/rtc_base/network.cc#236\n const costlyNetworks = [\"ipsec\", \"tun\", \"utun\", \"tap\"];\n const banNetworks = [\"vmnet\", \"veth\"];\n const { useLinkLocalAddress } = options;\n\n const all = Object.keys(interfaces)\n .map((nic) => {\n for (const word of [...costlyNetworks, ...banNetworks]) {\n if (nic.startsWith(word)) {\n return {\n nic,\n addresses: [] as string[],\n };\n }\n }\n const addresses = (interfaces[nic] ?? []).filter(\n (details) =>\n normalizeFamilyNodeV18(details.family) === family &&\n !details.internal &&\n (useLinkLocalAddress ? true : !isLinkLocal(details)),\n );\n return {\n nic,\n addresses: addresses.map((address) => address.address),\n };\n })\n .filter((address) => !!address);\n\n // os.networkInterfaces doesn't actually return addresses in a good order.\n // have seen instances where en0 (ethernet) is after en1 (wlan), etc.\n // eth0 > eth1\n all.sort((a, b) => a.nic.localeCompare(b.nic));\n return Object.values(all).flatMap((entry) => entry.addresses);\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { Event, UdpTransport } from "../imports/common";
2
2
  import type { Address, InterfaceAddresses } from "../../../common/src/network";
3
3
  import type { Candidate } from "../candidate";
4
- import type { Protocol } from "../types/model";
4
+ import type { Protocol, TransactionRequestOptions } from "../types/model";
5
5
  import { type Message } from "./message";
6
6
  import { Transaction } from "./transaction";
7
7
  export declare class StunProtocol implements Protocol {
@@ -23,6 +23,6 @@ export declare class StunProtocol implements Protocol {
23
23
  getExtraInfo(): Address;
24
24
  sendStun(message: Message, addr: Address): Promise<void>;
25
25
  sendData(data: Buffer, addr: Address): Promise<void>;
26
- request(request: Message, addr: Address, integrityKey?: Buffer, retransmissions?: number, onRequestSent?: (attempt: number) => void): Promise<[Message, readonly [string, number]]>;
26
+ request(request: Message, addr: Address, integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): Promise<[Message, readonly [string, number]]>;
27
27
  close(): Promise<void>;
28
28
  }
@@ -96,7 +96,15 @@ class StunProtocol {
96
96
  message.messageClass === const_1.classes.ERROR) &&
97
97
  this.transactionsKeys.includes(message.transactionIdHex)) {
98
98
  const transaction = this.transactions[message.transactionIdHex];
99
- transaction.responseReceived(message, addr);
99
+ // Re-parse with integrity key so unauthenticated responses are dropped.
100
+ const verified = transaction.integrityKey
101
+ ? (0, message_1.parseMessage)(data, transaction.integrityKey)
102
+ : message;
103
+ if (!verified) {
104
+ log("STUN response failed MESSAGE-INTEGRITY check");
105
+ return;
106
+ }
107
+ transaction.responseReceived(verified, addr);
100
108
  }
101
109
  else if (message.messageClass === const_1.classes.REQUEST) {
102
110
  this.onRequestReceived.execute(message, addr, data);
@@ -125,7 +133,7 @@ class StunProtocol {
125
133
  }
126
134
  await this.transport.send(data, addr);
127
135
  }
128
- async request(request, addr, integrityKey, retransmissions, onRequestSent) {
136
+ async request(request, addr, integrityKey, retransmissionsOrOptions, onRequestSent) {
129
137
  // """
130
138
  // Execute a STUN transaction and return the response.
131
139
  // """
@@ -135,7 +143,13 @@ class StunProtocol {
135
143
  request.addMessageIntegrity(integrityKey);
136
144
  request.addFingerprint();
137
145
  }
138
- const transaction = new transaction_1.Transaction(request, addr, this, retransmissions, onRequestSent);
146
+ // Match DNS family to the bound socket so STUN hostname targets resolve correctly.
147
+ const socketType = this.transport
148
+ .socketType;
149
+ const family = socketType === "udp6" ? 6 : 4;
150
+ const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr, family);
151
+ const options = (0, transaction_1.buildTransactionOptions)(integrityKey, retransmissionsOrOptions, onRequestSent);
152
+ const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
139
153
  this.transactions[request.transactionIdHex] = transaction;
140
154
  try {
141
155
  return await transaction.run();
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { Event, UdpTransport, debug } from \"../imports/common\";\n\nimport type { Address, InterfaceAddresses } from \"../../../common/src/network\";\nimport type { Candidate } from \"../candidate\";\n\nimport type { Protocol } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport { Transaction } from \"./transaction\";\n\nconst log = debug(\"werift-ice : packages/ice/src/stun/protocol.ts\");\n\nexport class StunProtocol implements Protocol {\n static readonly type = \"stun\";\n readonly type = StunProtocol.type;\n transport!: UdpTransport;\n transactions: { [key: string]: Transaction } = {};\n get transactionsKeys() {\n return Object.keys(this.transactions);\n }\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n\n constructor() {}\n\n connectionMade = async (\n useIpv4: boolean,\n portRange?: [number, number],\n interfaceAddresses?: InterfaceAddresses,\n ) => {\n if (useIpv4) {\n this.transport = await UdpTransport.init(\"udp4\", {\n portRange,\n interfaceAddresses,\n });\n } else {\n this.transport = await UdpTransport.init(\"udp6\", {\n portRange,\n interfaceAddresses,\n });\n }\n\n this.transport.onData = (data, addr) => {\n this.datagramReceived(data, addr);\n };\n };\n\n private datagramReceived(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n if (this.localCandidate) {\n this.onDataReceived.execute(data);\n }\n return;\n }\n // log(\"parseMessage\", addr, message.toJSON());\n if (\n (message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR) &&\n this.transactionsKeys.includes(message.transactionIdHex)\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n transaction.responseReceived(message, addr);\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 getExtraInfo(): Address {\n const { address: host, port } = this.transport.address;\n return [host, port];\n }\n\n async sendStun(message: Message, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n const data = message.bytes;\n await this.transport.send(data, addr).catch(() => {\n log(\"sendStun failed\", addr, message);\n });\n }\n\n async sendData(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(data, addr);\n }\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissions?: number,\n onRequestSent?: (attempt: number) => void,\n ) {\n // \"\"\"\n // Execute a STUN transaction and return the response.\n // \"\"\"\n if (this.transactionsKeys.includes(request.transactionIdHex))\n throw new Error(\"already request ed\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const transaction: Transaction = new Transaction(\n request,\n addr,\n this,\n retransmissions,\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 close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n await this.transport.close();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n }\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { Event, UdpTransport, debug } from \"../imports/common\";\n\nimport type { Address, InterfaceAddresses } from \"../../../common/src/network\";\nimport type { Candidate } from \"../candidate\";\n\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"./transaction\";\n\nconst log = debug(\"werift-ice : packages/ice/src/stun/protocol.ts\");\n\nexport class StunProtocol implements Protocol {\n static readonly type = \"stun\";\n readonly type = StunProtocol.type;\n transport!: UdpTransport;\n transactions: { [key: string]: Transaction } = {};\n get transactionsKeys() {\n return Object.keys(this.transactions);\n }\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n\n constructor() {}\n\n connectionMade = async (\n useIpv4: boolean,\n portRange?: [number, number],\n interfaceAddresses?: InterfaceAddresses,\n ) => {\n if (useIpv4) {\n this.transport = await UdpTransport.init(\"udp4\", {\n portRange,\n interfaceAddresses,\n });\n } else {\n this.transport = await UdpTransport.init(\"udp6\", {\n portRange,\n interfaceAddresses,\n });\n }\n\n this.transport.onData = (data, addr) => {\n this.datagramReceived(data, addr);\n };\n };\n\n private datagramReceived(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n if (this.localCandidate) {\n this.onDataReceived.execute(data);\n }\n return;\n }\n // log(\"parseMessage\", addr, message.toJSON());\n if (\n (message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR) &&\n this.transactionsKeys.includes(message.transactionIdHex)\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n // Re-parse with integrity key so unauthenticated responses are dropped.\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\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 getExtraInfo(): Address {\n const { address: host, port } = this.transport.address;\n return [host, port];\n }\n\n async sendStun(message: Message, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n const data = message.bytes;\n await this.transport.send(data, addr).catch(() => {\n log(\"sendStun failed\", addr, message);\n });\n }\n\n async sendData(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(data, addr);\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 // \"\"\"\n // Execute a STUN transaction and return the response.\n // \"\"\"\n if (this.transactionsKeys.includes(request.transactionIdHex))\n throw new Error(\"already request ed\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Match DNS family to the bound socket so STUN hostname targets resolve correctly.\n const socketType = (this.transport as unknown as { socketType?: string })\n .socketType;\n const family: 4 | 6 = socketType === \"udp6\" ? 6 : 4;\n const resolvedAddr = await resolveRequestAddress(addr, family);\n\n const options = buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction: Transaction = new Transaction(\n request,\n resolvedAddr,\n this,\n options,\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 close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n await this.transport.close();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { type AddressInfo, type Socket } from "node:net";
2
2
  import type { Candidate } from "../candidate";
3
3
  import { type Address, Event } from "../imports/common";
4
- import type { Protocol } from "../types/model";
4
+ import type { Protocol, TransactionRequestOptions } from "../types/model";
5
5
  import { type Message } from "./message";
6
6
  import { Transaction } from "./transaction";
7
7
  type SocketEntry = {
@@ -30,7 +30,7 @@ declare abstract class BaseTcpProtocol implements Protocol {
30
30
  private sendFrame;
31
31
  sendStun(message: Message, addr: Address): Promise<void>;
32
32
  sendData(data: Buffer, addr: Address): Promise<void>;
33
- request(request: Message, addr: Address, integrityKey?: Buffer, retransmissions?: number, onRequestSent?: (attempt: number) => void): Promise<[Message, readonly [string, number]]>;
33
+ request(request: Message, addr: Address, integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): Promise<[Message, readonly [string, number]]>;
34
34
  pruneForSelection(remoteAddr?: Address): Promise<void>;
35
35
  get activeSocketCount(): number;
36
36
  get address(): AddressInfo;
@@ -146,7 +146,15 @@ class BaseTcpProtocol {
146
146
  if ((message.messageClass === const_1.classes.RESPONSE ||
147
147
  message.messageClass === const_1.classes.ERROR) &&
148
148
  this.transactions[message.transactionIdHex]) {
149
- this.transactions[message.transactionIdHex].responseReceived(message, addr);
149
+ const transaction = this.transactions[message.transactionIdHex];
150
+ const verified = transaction.integrityKey
151
+ ? (0, message_1.parseMessage)(data, transaction.integrityKey)
152
+ : message;
153
+ if (!verified) {
154
+ log("STUN response failed MESSAGE-INTEGRITY check");
155
+ return;
156
+ }
157
+ transaction.responseReceived(verified, addr);
150
158
  }
151
159
  else if (message.messageClass === const_1.classes.REQUEST) {
152
160
  this.onRequestReceived.execute(message, addr, data);
@@ -174,7 +182,7 @@ class BaseTcpProtocol {
174
182
  async sendData(data, addr) {
175
183
  await this.sendFrame(data, addr);
176
184
  }
177
- async request(request, addr, integrityKey, retransmissions, onRequestSent) {
185
+ async request(request, addr, integrityKey, retransmissionsOrOptions, onRequestSent) {
178
186
  if (this.transactions[request.transactionIdHex]) {
179
187
  throw new Error("already requested");
180
188
  }
@@ -182,7 +190,9 @@ class BaseTcpProtocol {
182
190
  request.addMessageIntegrity(integrityKey);
183
191
  request.addFingerprint();
184
192
  }
185
- const transaction = new transaction_1.Transaction(request, addr, this, retransmissions, onRequestSent);
193
+ const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr);
194
+ const options = (0, transaction_1.buildTransactionOptions)(integrityKey, retransmissionsOrOptions, onRequestSent);
195
+ const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
186
196
  this.transactions[request.transactionIdHex] = transaction;
187
197
  try {
188
198
  return await transaction.run();
@@ -1 +1 @@
1
- {"version":3,"file":"tcpProtocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/tcpProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AddressInfo, type Socket, connect, createServer } from \"node:net\";\n\nimport type { Candidate } from \"../candidate\";\nimport { type Address, Event, debug } from \"../imports/common\";\nimport type { Protocol } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport { encodeTcpFrame, splitTcpFrames } from \"./tcpFrame\";\nimport { Transaction } from \"./transaction\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/tcpProtocol.ts\");\n\ntype SocketEntry = {\n socket: Socket;\n buffer: Buffer;\n remoteAddr?: Address;\n};\n\nfunction socketKey(addr: Address) {\n return `${addr[0]}:${addr[1]}`;\n}\n\nfunction addressFromSocket(socket: Socket) {\n if (!socket.remoteAddress || !socket.remotePort) {\n return;\n }\n return [socket.remoteAddress, socket.remotePort] as Address;\n}\n\nasync function waitForListening(\n server: ReturnType<typeof createServer>,\n host: string,\n port?: number,\n) {\n return await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n server.off(\"listening\", onListening);\n reject(error);\n };\n const onListening = () => {\n server.off(\"error\", onError);\n resolve();\n };\n\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen({\n host,\n port: port ?? 0,\n exclusive: true,\n });\n });\n}\n\nabstract class BaseTcpProtocol implements Protocol {\n static readonly type = \"tcp\";\n readonly type = BaseTcpProtocol.type;\n transactions: { [key: string]: Transaction } = {};\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n\n protected readonly sockets = new Map<string, SocketEntry>();\n\n abstract connectionMade(...args: any[]): Promise<void>;\n protected abstract getSocket(addr: Address): Promise<SocketEntry>;\n\n protected rememberSocket(entry: SocketEntry) {\n const remoteAddr = entry.remoteAddr;\n if (!remoteAddr) {\n return;\n }\n\n this.sockets.set(socketKey(remoteAddr), entry);\n }\n\n protected forgetSocket(remoteAddr?: Address) {\n if (!remoteAddr) {\n return;\n }\n this.sockets.delete(socketKey(remoteAddr));\n }\n\n protected registerSocket(socket: Socket, remoteAddr?: Address) {\n const entry: SocketEntry = {\n socket,\n buffer: Buffer.alloc(0),\n remoteAddr,\n };\n\n if (remoteAddr) {\n this.rememberSocket(entry);\n }\n\n socket.on(\"data\", (data) => {\n entry.buffer = Buffer.concat([entry.buffer, data]);\n const { frames, rest } = splitTcpFrames(entry.buffer);\n entry.buffer = rest;\n\n const socketAddr = entry.remoteAddr ?? addressFromSocket(socket);\n if (!entry.remoteAddr && socketAddr) {\n entry.remoteAddr = socketAddr;\n this.rememberSocket(entry);\n }\n if (!socketAddr) {\n return;\n }\n\n for (const frame of frames) {\n if (frame.length === 0) {\n continue;\n }\n this.handleFrame(frame, socketAddr);\n }\n });\n socket.on(\"close\", () => {\n this.forgetSocket(entry.remoteAddr);\n });\n socket.on(\"error\", (error) => {\n log(\"tcp socket error\", error);\n });\n\n return entry;\n }\n\n private handleFrame(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 this.transactions[message.transactionIdHex]\n ) {\n this.transactions[message.transactionIdHex].responseReceived(\n message,\n addr,\n );\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"tcp frame parse error\", error);\n }\n }\n\n private async sendFrame(data: Buffer, addr: Address) {\n const entry = await this.getSocket(addr);\n await new Promise<void>((resolve, reject) => {\n entry.socket.write(encodeTcpFrame(data), (error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.sendFrame(message.bytes, addr);\n }\n\n async sendData(data: Buffer, addr: Address) {\n await this.sendFrame(data, addr);\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.transactions[request.transactionIdHex]) {\n throw new Error(\"already requested\");\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 retransmissions,\n onRequestSent,\n );\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async pruneForSelection(remoteAddr?: Address) {\n for (const [key, entry] of this.sockets.entries()) {\n if (remoteAddr && key === socketKey(remoteAddr)) {\n continue;\n }\n entry.socket.destroy();\n this.sockets.delete(key);\n }\n }\n\n get activeSocketCount() {\n return this.sockets.size;\n }\n\n get address() {\n return {} as AddressInfo;\n }\n\n async close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n\n await this.pruneForSelection();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n }\n}\n\nexport class TcpActiveProtocol extends BaseTcpProtocol {\n private readonly pendingSockets = new Map<string, Promise<SocketEntry>>();\n\n async connectionMade(localIp: string) {\n this.localIp = localIp;\n }\n\n protected async getSocket(addr: Address) {\n const key = socketKey(addr);\n const existing = this.sockets.get(key);\n if (existing) {\n return existing;\n }\n\n const pending = this.pendingSockets.get(key);\n if (pending) {\n return await pending;\n }\n\n const connecting = new Promise<SocketEntry>((resolve, reject) => {\n const socket = connect({\n host: addr[0],\n port: addr[1],\n localAddress: this.localIp,\n });\n const entry = this.registerSocket(socket, addr);\n\n const onError = (error: Error) => {\n socket.off(\"connect\", onConnect);\n reject(error);\n };\n const onConnect = () => {\n socket.off(\"error\", onError);\n resolve(entry);\n };\n\n socket.once(\"error\", onError);\n socket.once(\"connect\", onConnect);\n });\n\n this.pendingSockets.set(key, connecting);\n\n try {\n return await connecting;\n } finally {\n this.pendingSockets.delete(key);\n }\n }\n}\n\nexport class TcpPassiveProtocol extends BaseTcpProtocol {\n private server = createServer((socket) => {\n this.registerSocket(socket, addressFromSocket(socket));\n });\n\n async connectionMade(localIp: string, portRange?: [number, number]) {\n this.localIp = localIp;\n\n if (portRange) {\n let lastError: Error | undefined;\n for (let port = portRange[0]; port <= portRange[1]; port++) {\n try {\n await waitForListening(this.server, localIp, port);\n return;\n } catch (error) {\n lastError = error as Error;\n }\n }\n throw lastError ?? new Error(\"tcp port not found\");\n }\n\n await waitForListening(this.server, localIp);\n }\n\n protected async getSocket(addr: Address) {\n const entry = this.sockets.get(socketKey(addr));\n if (!entry) {\n throw new Error(\"tcp passive connection not established\");\n }\n return entry;\n }\n\n get listeningPort() {\n const address = this.server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"tcp passive protocol is not listening\");\n }\n return address.port;\n }\n\n override async close() {\n await super.close();\n await new Promise<void>((resolve) => {\n this.server.close(() => resolve());\n });\n }\n}\n"]}
1
+ {"version":3,"file":"tcpProtocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/tcpProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AddressInfo, type Socket, connect, createServer } from \"node:net\";\n\nimport type { Candidate } from \"../candidate\";\nimport { type Address, Event, debug } from \"../imports/common\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport { encodeTcpFrame, splitTcpFrames } from \"./tcpFrame\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"./transaction\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/tcpProtocol.ts\");\n\ntype SocketEntry = {\n socket: Socket;\n buffer: Buffer;\n remoteAddr?: Address;\n};\n\nfunction socketKey(addr: Address) {\n return `${addr[0]}:${addr[1]}`;\n}\n\nfunction addressFromSocket(socket: Socket) {\n if (!socket.remoteAddress || !socket.remotePort) {\n return;\n }\n return [socket.remoteAddress, socket.remotePort] as Address;\n}\n\nasync function waitForListening(\n server: ReturnType<typeof createServer>,\n host: string,\n port?: number,\n) {\n return await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n server.off(\"listening\", onListening);\n reject(error);\n };\n const onListening = () => {\n server.off(\"error\", onError);\n resolve();\n };\n\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen({\n host,\n port: port ?? 0,\n exclusive: true,\n });\n });\n}\n\nabstract class BaseTcpProtocol implements Protocol {\n static readonly type = \"tcp\";\n readonly type = BaseTcpProtocol.type;\n transactions: { [key: string]: Transaction } = {};\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n\n protected readonly sockets = new Map<string, SocketEntry>();\n\n abstract connectionMade(...args: any[]): Promise<void>;\n protected abstract getSocket(addr: Address): Promise<SocketEntry>;\n\n protected rememberSocket(entry: SocketEntry) {\n const remoteAddr = entry.remoteAddr;\n if (!remoteAddr) {\n return;\n }\n\n this.sockets.set(socketKey(remoteAddr), entry);\n }\n\n protected forgetSocket(remoteAddr?: Address) {\n if (!remoteAddr) {\n return;\n }\n this.sockets.delete(socketKey(remoteAddr));\n }\n\n protected registerSocket(socket: Socket, remoteAddr?: Address) {\n const entry: SocketEntry = {\n socket,\n buffer: Buffer.alloc(0),\n remoteAddr,\n };\n\n if (remoteAddr) {\n this.rememberSocket(entry);\n }\n\n socket.on(\"data\", (data) => {\n entry.buffer = Buffer.concat([entry.buffer, data]);\n const { frames, rest } = splitTcpFrames(entry.buffer);\n entry.buffer = rest;\n\n const socketAddr = entry.remoteAddr ?? addressFromSocket(socket);\n if (!entry.remoteAddr && socketAddr) {\n entry.remoteAddr = socketAddr;\n this.rememberSocket(entry);\n }\n if (!socketAddr) {\n return;\n }\n\n for (const frame of frames) {\n if (frame.length === 0) {\n continue;\n }\n this.handleFrame(frame, socketAddr);\n }\n });\n socket.on(\"close\", () => {\n this.forgetSocket(entry.remoteAddr);\n });\n socket.on(\"error\", (error) => {\n log(\"tcp socket error\", error);\n });\n\n return entry;\n }\n\n private handleFrame(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 this.transactions[message.transactionIdHex]\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"tcp frame parse error\", error);\n }\n }\n\n private async sendFrame(data: Buffer, addr: Address) {\n const entry = await this.getSocket(addr);\n await new Promise<void>((resolve, reject) => {\n entry.socket.write(encodeTcpFrame(data), (error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.sendFrame(message.bytes, addr);\n }\n\n async sendData(data: Buffer, addr: Address) {\n await this.sendFrame(data, addr);\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.transactions[request.transactionIdHex]) {\n throw new Error(\"already requested\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\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.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async pruneForSelection(remoteAddr?: Address) {\n for (const [key, entry] of this.sockets.entries()) {\n if (remoteAddr && key === socketKey(remoteAddr)) {\n continue;\n }\n entry.socket.destroy();\n this.sockets.delete(key);\n }\n }\n\n get activeSocketCount() {\n return this.sockets.size;\n }\n\n get address() {\n return {} as AddressInfo;\n }\n\n async close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n\n await this.pruneForSelection();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n }\n}\n\nexport class TcpActiveProtocol extends BaseTcpProtocol {\n private readonly pendingSockets = new Map<string, Promise<SocketEntry>>();\n\n async connectionMade(localIp: string) {\n this.localIp = localIp;\n }\n\n protected async getSocket(addr: Address) {\n const key = socketKey(addr);\n const existing = this.sockets.get(key);\n if (existing) {\n return existing;\n }\n\n const pending = this.pendingSockets.get(key);\n if (pending) {\n return await pending;\n }\n\n const connecting = new Promise<SocketEntry>((resolve, reject) => {\n const socket = connect({\n host: addr[0],\n port: addr[1],\n localAddress: this.localIp,\n });\n const entry = this.registerSocket(socket, addr);\n\n const onError = (error: Error) => {\n socket.off(\"connect\", onConnect);\n reject(error);\n };\n const onConnect = () => {\n socket.off(\"error\", onError);\n resolve(entry);\n };\n\n socket.once(\"error\", onError);\n socket.once(\"connect\", onConnect);\n });\n\n this.pendingSockets.set(key, connecting);\n\n try {\n return await connecting;\n } finally {\n this.pendingSockets.delete(key);\n }\n }\n}\n\nexport class TcpPassiveProtocol extends BaseTcpProtocol {\n private server = createServer((socket) => {\n this.registerSocket(socket, addressFromSocket(socket));\n });\n\n async connectionMade(localIp: string, portRange?: [number, number]) {\n this.localIp = localIp;\n\n if (portRange) {\n let lastError: Error | undefined;\n for (let port = portRange[0]; port <= portRange[1]; port++) {\n try {\n await waitForListening(this.server, localIp, port);\n return;\n } catch (error) {\n lastError = error as Error;\n }\n }\n throw lastError ?? new Error(\"tcp port not found\");\n }\n\n await waitForListening(this.server, localIp);\n }\n\n protected async getSocket(addr: Address) {\n const entry = this.sockets.get(socketKey(addr));\n if (!entry) {\n throw new Error(\"tcp passive connection not established\");\n }\n return entry;\n }\n\n get listeningPort() {\n const address = this.server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"tcp passive protocol is not listening\");\n }\n return address.port;\n }\n\n override async close() {\n await super.close();\n await new Promise<void>((resolve) => {\n this.server.close(() => resolve());\n });\n }\n}\n"]}
@@ -1,20 +1,57 @@
1
1
  import { type Address } from "../imports/common";
2
- import type { Protocol } from "../types/model";
2
+ import type { Protocol, TransactionRequestOptions } from "../types/model";
3
3
  import type { Message } from "./message";
4
+ /**
5
+ * Resolve a request target to a concrete IP before creating a Transaction so
6
+ * response source-address checks match the UDP peer address (hostname ≠ IP).
7
+ */
8
+ export declare function resolveRequestAddress(addr: Address, family?: 0 | 4 | 6): Promise<Address>;
9
+ /**
10
+ * Normalize legacy positional args and the options-object form into one shape.
11
+ * Existing callers pass `(retransmissions?, onRequestSent?)`.
12
+ */
13
+ export declare function normalizeTransactionOptions(retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): TransactionRequestOptions;
14
+ /** Compare ICE transport addresses (host, port). */
15
+ export declare function addressEquals(a: Address, b: Address): boolean;
4
16
  export declare class Transaction {
5
17
  private request;
6
18
  private addr;
7
19
  private protocol;
8
- private retransmissions?;
9
- private onRequestSent?;
10
20
  private timeoutDelay;
11
21
  ended: boolean;
12
22
  private tries;
13
23
  private readonly triesMax;
14
24
  private readonly onResponse;
15
- constructor(request: Message, addr: Address, protocol: Protocol, retransmissions?: number | undefined, onRequestSent?: ((attempt: number) => void) | undefined);
25
+ private readonly onRequestSent?;
26
+ private readonly signal?;
27
+ /** Remote address this transaction was sent to; responses must match. */
28
+ readonly expectedAddr: Address;
29
+ /**
30
+ * When set, protocol layers re-parse the wire response with this key so
31
+ * MESSAGE-INTEGRITY failures are rejected before responseReceived.
32
+ */
33
+ readonly integrityKey?: Buffer;
34
+ private waitTimer?;
35
+ private waitResolve?;
36
+ private onAbort?;
37
+ constructor(request: Message, addr: Address, protocol: Protocol, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void);
38
+ /**
39
+ * Accept a matching authenticated non-error response from the expected
40
+ * remote address. Wrong address, missing MESSAGE-INTEGRITY (when required),
41
+ * or non-success class is rejected without completing the transaction
42
+ * (wrong address / unauthenticated responses are ignored so we keep waiting).
43
+ */
16
44
  responseReceived: (message: Message, addr: Address) => void;
17
45
  run: () => Promise<[Message, readonly [string, number]]>;
46
+ private attachAbortListener;
47
+ private failWithTimeout;
48
+ private clearWait;
49
+ private wait;
18
50
  private retry;
19
51
  cancel(): void;
20
52
  }
53
+ /**
54
+ * Build Transaction options for Protocol.request, folding integrityKey into
55
+ * options so response path can re-verify MESSAGE-INTEGRITY.
56
+ */
57
+ export declare function buildTransactionOptions(integrityKey: Buffer | undefined, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): TransactionRequestOptions;