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,11 +1,37 @@
1
1
  import type { Candidate } from "../candidate";
2
2
  import type { Address, Event } from "../imports/common";
3
3
  import type { Message } from "../stun/message";
4
+ /**
5
+ * Options for a STUN transaction / Protocol.request.
6
+ * Retransmission count and response wait deadline are independent
7
+ * so consent freshness (retransmissions: 0, longer timeout) can be expressed.
8
+ */
9
+ export interface TransactionRequestOptions {
10
+ /** Number of retransmissions after the initial send. 0 = send once. */
11
+ retransmissions?: number;
12
+ /**
13
+ * Initial response wait deadline in milliseconds.
14
+ * Doubled after each retransmission when retransmissions > 0.
15
+ * Defaults to RETRY_RTO when omitted.
16
+ */
17
+ responseTimeout?: number;
18
+ /** Called for each wire send (attempt 0 is the initial transmission). */
19
+ onRequestSent?: (attempt: number) => void;
20
+ /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */
21
+ signal?: AbortSignal;
22
+ /**
23
+ * When set, responses must include MESSAGE-INTEGRITY and pass HMAC
24
+ * verification (protocol re-parses the wire bytes with this key; the
25
+ * transaction also rejects unsigned Messages as defense-in-depth).
26
+ * Unsigned or forged responses must not complete the transaction.
27
+ */
28
+ integrityKey?: Buffer;
29
+ }
4
30
  export interface Protocol {
5
31
  type: string;
6
32
  onRequestReceived: Event<[Message, Address, Buffer]>;
7
33
  onDataReceived: Event<[Buffer]>;
8
- request: (message: Message, addr: Address, integrityKey?: Buffer, retransmissions?: any, onRequestSent?: (attempt: number) => void) => Promise<[Message, Address]>;
34
+ request: (message: Message, addr: Address, integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void) => Promise<[Message, Address]>;
9
35
  close: () => Promise<void>;
10
36
  connectionMade: (...args: any) => Promise<void>;
11
37
  sendStun: (message: Message, addr: Address) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../ice/src/types/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { Candidate } from \"../candidate\";\nimport type { Address, Event } from \"../imports/common\";\nimport type { Message } from \"../stun/message\";\n\nexport interface Protocol {\n type: string;\n onRequestReceived: Event<[Message, Address, Buffer]>;\n onDataReceived: Event<[Buffer]>;\n request: (\n message: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissions?: any,\n onRequestSent?: (attempt: number) => void,\n ) => Promise<[Message, Address]>;\n close: () => Promise<void>;\n connectionMade: (...args: any) => Promise<void>;\n sendStun: (message: Message, addr: Address) => Promise<void>;\n sendData: (data: Buffer, addr: Address) => Promise<void>;\n localCandidate?: Candidate;\n sentMessage?: Message;\n responseAddr?: Address;\n responseMessage?: string;\n localIp?: string;\n}\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../ice/src/types/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { Candidate } from \"../candidate\";\nimport type { Address, Event } from \"../imports/common\";\nimport type { Message } from \"../stun/message\";\n\n/**\n * Options for a STUN transaction / Protocol.request.\n * Retransmission count and response wait deadline are independent\n * so consent freshness (retransmissions: 0, longer timeout) can be expressed.\n */\nexport interface TransactionRequestOptions {\n /** Number of retransmissions after the initial send. 0 = send once. */\n retransmissions?: number;\n /**\n * Initial response wait deadline in milliseconds.\n * Doubled after each retransmission when retransmissions > 0.\n * Defaults to RETRY_RTO when omitted.\n */\n responseTimeout?: number;\n /** Called for each wire send (attempt 0 is the initial transmission). */\n onRequestSent?: (attempt: number) => void;\n /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */\n signal?: AbortSignal;\n /**\n * When set, responses must include MESSAGE-INTEGRITY and pass HMAC\n * verification (protocol re-parses the wire bytes with this key; the\n * transaction also rejects unsigned Messages as defense-in-depth).\n * Unsigned or forged responses must not complete the transaction.\n */\n integrityKey?: Buffer;\n}\n\nexport interface Protocol {\n type: string;\n onRequestReceived: Event<[Message, Address, Buffer]>;\n onDataReceived: Event<[Buffer]>;\n request: (\n message: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) => Promise<[Message, Address]>;\n close: () => Promise<void>;\n connectionMade: (...args: any) => Promise<void>;\n sendStun: (message: Message, addr: Address) => Promise<void>;\n sendData: (data: Buffer, addr: Address) => Promise<void>;\n localCandidate?: Candidate;\n sentMessage?: Message;\n responseAddr?: Address;\n responseMessage?: string;\n localIp?: string;\n}\n"]}
@@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
35
  Object.defineProperty(exports, "__esModule", { value: true });
39
36
  exports.url2Address = void 0;
40
37
  exports.getGlobalIp = getGlobalIp;
@@ -42,8 +39,8 @@ exports.isLinkLocalAddress = isLinkLocalAddress;
42
39
  exports.nodeIpAddress = nodeIpAddress;
43
40
  exports.getHostAddresses = getHostAddresses;
44
41
  const os = __importStar(require("node:os"));
45
- const ip_1 = __importDefault(require("ip"));
46
42
  const common_1 = require("./imports/common");
43
+ const selectAddresses_1 = require("./internal/selectAddresses");
47
44
  const const_1 = require("./stun/const");
48
45
  const message_1 = require("./stun/message");
49
46
  const protocol_1 = require("./stun/protocol");
@@ -64,35 +61,9 @@ function isLinkLocalAddress(info) {
64
61
  info.address?.startsWith("fe80::")));
65
62
  }
66
63
  function nodeIpAddress(family, { useLinkLocalAddress, } = {}) {
67
- // https://chromium.googlesource.com/external/webrtc/+/master/rtc_base/network.cc#236
68
- const costlyNetworks = ["ipsec", "tun", "utun", "tap"];
69
- const banNetworks = ["vmnet", "veth"];
70
64
  const interfaces = os.networkInterfaces();
71
65
  logger(interfaces);
72
- const all = Object.keys(interfaces)
73
- .map((nic) => {
74
- for (const word of [...costlyNetworks, ...banNetworks]) {
75
- if (nic.startsWith(word)) {
76
- return {
77
- nic,
78
- addresses: [],
79
- };
80
- }
81
- }
82
- const addresses = interfaces[nic].filter((details) => (0, common_1.normalizeFamilyNodeV18)(details.family) === family &&
83
- !ip_1.default.isLoopback(details.address) &&
84
- (useLinkLocalAddress ? true : !isLinkLocalAddress(details)));
85
- return {
86
- nic,
87
- addresses: addresses.map((address) => address.address),
88
- };
89
- })
90
- .filter((address) => !!address);
91
- // os.networkInterfaces doesn't actually return addresses in a good order.
92
- // have seen instances where en0 (ethernet) is after en1 (wlan), etc.
93
- // eth0 > eth1
94
- all.sort((a, b) => a.nic.localeCompare(b.nic));
95
- return Object.values(all).flatMap((entry) => entry.addresses);
66
+ return (0, selectAddresses_1.selectAddressesFromInterfaces)(interfaces, family, { useLinkLocalAddress }, isLinkLocalAddress);
96
67
  }
97
68
  function getHostAddresses(useIpv4, useIpv6, options = {}) {
98
69
  const address = [];
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../ice/src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as os from \"node:os\";\nimport nodeIp from \"ip\";\nimport {\n type Address,\n type InterfaceAddresses,\n debug,\n normalizeFamilyNodeV18,\n} from \"./imports/common\";\nimport { classes, methods } from \"./stun/const\";\nimport { Message } from \"./stun/message\";\nimport { StunProtocol } from \"./stun/protocol\";\n\nconst logger = debug(\"werift-ice : packages/ice/src/utils.ts\");\n\nexport async function getGlobalIp(\n stunServer?: Address,\n interfaceAddresses?: InterfaceAddresses,\n) {\n const protocol = new StunProtocol();\n await protocol.connectionMade(true, undefined, interfaceAddresses);\n const request = new Message(methods.BINDING, classes.REQUEST);\n const [response] = await protocol.request(\n request,\n stunServer ?? [\"stun.l.google.com\", 19302],\n );\n await protocol.close();\n\n const address = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n return address[0] as string;\n}\n\nexport function isLinkLocalAddress(info: os.NetworkInterfaceInfo) {\n return (\n (normalizeFamilyNodeV18(info.family) === 4 &&\n info.address?.startsWith(\"169.254.\")) ||\n (normalizeFamilyNodeV18(info.family) === 6 &&\n info.address?.startsWith(\"fe80::\"))\n );\n}\n\nexport function nodeIpAddress(\n family: number,\n {\n useLinkLocalAddress,\n }: {\n /** such as google cloud run */\n useLinkLocalAddress?: boolean;\n } = {},\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\n const interfaces = os.networkInterfaces();\n\n logger(interfaces);\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: [],\n };\n }\n }\n const addresses = interfaces[nic]!.filter(\n (details) =>\n normalizeFamilyNodeV18(details.family) === family &&\n !nodeIp.isLoopback(details.address) &&\n (useLinkLocalAddress ? true : !isLinkLocalAddress(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\nexport function getHostAddresses(\n useIpv4: boolean,\n useIpv6: boolean,\n options: {\n /** such as google cloud run */\n useLinkLocalAddress?: boolean;\n } = {},\n) {\n const address: string[] = [];\n if (useIpv4) {\n address.push(...nodeIpAddress(4, options));\n }\n if (useIpv6) {\n address.push(...nodeIpAddress(6, options));\n }\n return address;\n}\n\nexport const url2Address = (url?: string) => {\n if (!url) return;\n const [address, port] = url.split(\":\");\n return [address, Number.parseInt(port)] as Address;\n};\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../ice/src/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,kCAeC;AAED,gDAOC;AAED,sCAiBC;AAED,4CAgBC;AA3ED,4CAA8B;AAC9B,6CAK0B;AAC1B,gEAA2E;AAC3E,wCAAgD;AAChD,4CAAyC;AACzC,8CAA+C;AAE/C,MAAM,MAAM,GAAG,IAAA,cAAK,EAAC,wCAAwC,CAAC,CAAC;AAExD,KAAK,UAAU,WAAW,CAC/B,UAAoB,EACpB,kBAAuC;IAEvC,MAAM,QAAQ,GAAG,IAAI,uBAAY,EAAE,CAAC;IACpC,MAAM,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,eAAO,CAAC,OAAO,EAAE,eAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,QAAQ,CAAC,OAAO,CACvC,OAAO,EACP,UAAU,IAAI,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAC3C,CAAC;IACF,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IAEvB,MAAM,OAAO,GAAG,QAAQ,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,CAAC;IACjE,OAAO,OAAO,CAAC,CAAC,CAAW,CAAC;AAC9B,CAAC;AAED,SAAgB,kBAAkB,CAAC,IAA6B;IAC9D,OAAO,CACL,CAAC,IAAA,+BAAsB,EAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC,IAAA,+BAAsB,EAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;YACxC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,CACtC,CAAC;AACJ,CAAC;AAED,SAAgB,aAAa,CAC3B,MAAc,EACd,EACE,mBAAmB,MAIjB,EAAE;IAEN,MAAM,UAAU,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAC1C,MAAM,CAAC,UAAU,CAAC,CAAC;IACnB,OAAO,IAAA,+CAA6B,EAClC,UAAU,EACV,MAAM,EACN,EAAE,mBAAmB,EAAE,EACvB,kBAAkB,CACnB,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAC9B,OAAgB,EAChB,OAAgB,EAChB,UAGI,EAAE;IAEN,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAEM,MAAM,WAAW,GAAG,CAAC,GAAY,EAAE,EAAE;IAC1C,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAY,CAAC;AACrD,CAAC,CAAC;AAJW,QAAA,WAAW,eAItB","sourcesContent":["import * as os from \"node:os\";\nimport {\n type Address,\n type InterfaceAddresses,\n debug,\n normalizeFamilyNodeV18,\n} from \"./imports/common\";\nimport { selectAddressesFromInterfaces } from \"./internal/selectAddresses\";\nimport { classes, methods } from \"./stun/const\";\nimport { Message } from \"./stun/message\";\nimport { StunProtocol } from \"./stun/protocol\";\n\nconst logger = debug(\"werift-ice : packages/ice/src/utils.ts\");\n\nexport async function getGlobalIp(\n stunServer?: Address,\n interfaceAddresses?: InterfaceAddresses,\n) {\n const protocol = new StunProtocol();\n await protocol.connectionMade(true, undefined, interfaceAddresses);\n const request = new Message(methods.BINDING, classes.REQUEST);\n const [response] = await protocol.request(\n request,\n stunServer ?? [\"stun.l.google.com\", 19302],\n );\n await protocol.close();\n\n const address = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n return address[0] as string;\n}\n\nexport function isLinkLocalAddress(info: os.NetworkInterfaceInfo) {\n return (\n (normalizeFamilyNodeV18(info.family) === 4 &&\n info.address?.startsWith(\"169.254.\")) ||\n (normalizeFamilyNodeV18(info.family) === 6 &&\n info.address?.startsWith(\"fe80::\"))\n );\n}\n\nexport function nodeIpAddress(\n family: number,\n {\n useLinkLocalAddress,\n }: {\n /** such as google cloud run */\n useLinkLocalAddress?: boolean;\n } = {},\n): string[] {\n const interfaces = os.networkInterfaces();\n logger(interfaces);\n return selectAddressesFromInterfaces(\n interfaces,\n family,\n { useLinkLocalAddress },\n isLinkLocalAddress,\n );\n}\n\nexport function getHostAddresses(\n useIpv4: boolean,\n useIpv6: boolean,\n options: {\n /** such as google cloud run */\n useLinkLocalAddress?: boolean;\n } = {},\n) {\n const address: string[] = [];\n if (useIpv4) {\n address.push(...nodeIpAddress(4, options));\n }\n if (useIpv6) {\n address.push(...nodeIpAddress(6, options));\n }\n return address;\n}\n\nexport const url2Address = (url?: string) => {\n if (!url) return;\n const [address, port] = url.split(\":\");\n return [address, Number.parseInt(port)] as Address;\n};\n"]}
@@ -1,40 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
2
  Object.defineProperty(exports, "__esModule", { value: true });
39
3
  exports.ATTRIBUTES_BY_NAME = exports.ATTRIBUTES_BY_TYPE = exports.AttributeRepository = void 0;
40
4
  exports.unpackErrorCode = unpackErrorCode;
@@ -43,17 +7,16 @@ exports.packErrorCode = packErrorCode;
43
7
  exports.packUnknownAttributes = packUnknownAttributes;
44
8
  exports.unpackUnknownAttributes = unpackUnknownAttributes;
45
9
  exports.packXorAddress = packXorAddress;
46
- const Int64 = __importStar(require("int64-buffer"));
47
- const ip_1 = __importDefault(require("ip"));
48
10
  const const_1 = require("./const");
11
+ const ip_1 = require("./ip");
49
12
  function packAddress(value) {
50
13
  const [address] = value;
51
- const protocol = ip_1.default.isV4Format(address) ? const_1.IPV4_PROTOCOL : const_1.IPV6_PROTOCOL;
14
+ const protocol = (0, ip_1.isIpV4Address)(address) ? const_1.IPV4_PROTOCOL : const_1.IPV6_PROTOCOL;
52
15
  const buffer = Buffer.alloc(4);
53
16
  buffer.writeUInt8(0, 0);
54
17
  buffer.writeUInt8(protocol, 1);
55
18
  buffer.writeUInt16BE(value[1], 2);
56
- return Buffer.concat([buffer, ip_1.default.toBuffer(address)]);
19
+ return Buffer.concat([buffer, (0, ip_1.ipAddressToBuffer)(address)]);
57
20
  }
58
21
  function unpackErrorCode(data) {
59
22
  if (data.length < 4) {
@@ -76,12 +39,12 @@ function unpackAddress(data) {
76
39
  if (address.length !== 4) {
77
40
  throw new Error("STUN address has invalid length for IPv4");
78
41
  }
79
- return [ip_1.default.toString(address), port];
42
+ return [(0, ip_1.bufferToIpAddress)(address), port];
80
43
  case const_1.IPV6_PROTOCOL:
81
44
  if (address.length !== 16) {
82
45
  throw new Error("STUN address has invalid length for IPv6");
83
46
  }
84
- return [ip_1.default.toString(address), port];
47
+ return [(0, ip_1.bufferToIpAddress)(address), port];
85
48
  default:
86
49
  throw new Error("STUN address has unknown protocol");
87
50
  }
@@ -144,12 +107,11 @@ const packUnsignedShort = (value) => {
144
107
  };
145
108
  const unpackUnsignedShort = (data) => data.readUInt16BE(0);
146
109
  const packUnsigned64 = (value) => {
147
- return new Int64.Int64BE(value.toString()).toBuffer();
148
- };
149
- const unpackUnsigned64 = (data) => {
150
- const int = new Int64.Int64BE(data);
151
- return BigInt(int.toString());
110
+ const buffer = Buffer.allocUnsafe(8);
111
+ buffer.writeBigUInt64BE(value, 0);
112
+ return buffer;
152
113
  };
114
+ const unpackUnsigned64 = (data) => data.readBigUInt64BE(0);
153
115
  const packString = (value) => Buffer.from(value, "utf8");
154
116
  const unpackString = (data) => data.toString("utf8");
155
117
  const packSoftware = (value) => {
@@ -1 +1 @@
1
- {"version":3,"file":"attributes.js","sourceRoot":"","sources":["../../../../../ice-server/src/stun/attributes.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Int64 from \"int64-buffer\";\nimport nodeIp from \"ip\";\n\nimport type { Address } from \"../../../common/src\";\n\nimport {\n type AttributeKeys,\n COOKIE,\n IPV4_PROTOCOL,\n IPV6_PROTOCOL,\n} from \"./const\";\n\nfunction packAddress(value: Address) {\n const [address] = value;\n const protocol = nodeIp.isV4Format(address) ? IPV4_PROTOCOL : IPV6_PROTOCOL;\n\n const buffer = Buffer.alloc(4);\n buffer.writeUInt8(0, 0);\n buffer.writeUInt8(protocol, 1);\n buffer.writeUInt16BE(value[1], 2);\n\n return Buffer.concat([buffer, nodeIp.toBuffer(address)]);\n}\n\nexport function unpackErrorCode(data: Buffer): [number, string] {\n if (data.length < 4) {\n throw new Error(\"STUN error code is less than 4 bytes\");\n }\n\n const codeHigh = data.readUInt8(2);\n const codeLow = data.readUInt8(3);\n const reason = data.slice(4).toString(\"utf8\");\n return [codeHigh * 100 + codeLow, reason];\n}\n\nfunction unpackAddress(data: Buffer): Address {\n if (data.length < 4) {\n throw new Error(\"STUN address length is less than 4 bytes\");\n }\n\n const protocol = data.readUInt8(1);\n const port = data.readUInt16BE(2);\n const address = data.slice(4);\n\n switch (protocol) {\n case IPV4_PROTOCOL:\n if (address.length !== 4) {\n throw new Error(\"STUN address has invalid length for IPv4\");\n }\n return [nodeIp.toString(address), port];\n case IPV6_PROTOCOL:\n if (address.length !== 16) {\n throw new Error(\"STUN address has invalid length for IPv6\");\n }\n return [nodeIp.toString(address), port];\n default:\n throw new Error(\"STUN address has unknown protocol\");\n }\n}\n\nconst cookieBuffer = Buffer.alloc(6);\ncookieBuffer.writeUInt16BE(COOKIE >> 16, 0);\ncookieBuffer.writeUInt32BE(COOKIE, 2);\n\nfunction xorAddress(data: Buffer, transactionId: Buffer) {\n const xPad = [...cookieBuffer, ...transactionId];\n let xData = data.slice(0, 2);\n\n for (let i = 2; i < data.length; i++) {\n const num = data[i] ^ xPad[i - 2];\n const buf = Buffer.alloc(1);\n buf.writeUIntBE(num, 0, 1);\n xData = Buffer.concat([xData, buf]);\n }\n return xData;\n}\n\nexport function unpackXorAddress(data: Buffer, transactionId: Buffer): Address {\n return unpackAddress(xorAddress(data, transactionId));\n}\n\nexport function packErrorCode(value: [number, string]) {\n const buffer = Buffer.alloc(4);\n buffer.writeUInt16BE(0, 0);\n buffer.writeUInt8(Math.floor(value[0] / 100), 2);\n buffer.writeUInt8(value[0] % 100, 3);\n const encoded = Buffer.from(value[1], \"utf8\");\n return Buffer.concat([buffer, encoded]);\n}\n\nexport function packUnknownAttributes(value: number[]) {\n const buffer = Buffer.alloc(value.length * 2);\n value.forEach((attributeType, index) => {\n buffer.writeUInt16BE(attributeType, index * 2);\n });\n return buffer;\n}\n\nexport function unpackUnknownAttributes(data: Buffer) {\n if (data.length % 2 !== 0) {\n throw new Error(\"UNKNOWN-ATTRIBUTES must have an even length\");\n }\n\n const attributes: number[] = [];\n for (let offset = 0; offset < data.length; offset += 2) {\n attributes.push(data.readUInt16BE(offset));\n }\n return attributes;\n}\n\nexport function packXorAddress(value: Address, transactionId: Buffer) {\n return xorAddress(packAddress(value), transactionId);\n}\n\nconst packUnsigned = (value: number) => {\n const buffer = Buffer.alloc(4);\n buffer.writeUInt32BE(value, 0);\n return buffer;\n};\n\nconst unpackUnsigned = (data: Buffer) => data.readUInt32BE(0);\n\nconst packUnsignedShort = (value: number) => {\n const buffer = Buffer.alloc(4);\n buffer.writeUInt16BE(value, 0);\n return buffer;\n};\n\nconst unpackUnsignedShort = (data: Buffer) => data.readUInt16BE(0);\n\nconst packUnsigned64 = (value: bigint) => {\n return new Int64.Int64BE(value.toString()).toBuffer();\n};\n\nconst unpackUnsigned64 = (data: Buffer) => {\n const int = new Int64.Int64BE(data);\n return BigInt(int.toString());\n};\n\nconst packString = (value: string) => Buffer.from(value, \"utf8\");\nconst unpackString = (data: Buffer) => data.toString(\"utf8\");\n\nconst packSoftware = (value: string) => {\n if ([...value].length >= 128) {\n throw new Error(\"SOFTWARE must be shorter than 128 characters\");\n }\n return packString(value);\n};\n\nconst packBytes = (value: Buffer) => value;\nconst unpackBytes = (data: Buffer) => data;\n\nconst packNone = () => Buffer.alloc(0);\nconst unpackNone = () => null;\n\nexport type ATTRIBUTE = [\n number,\n AttributeKey,\n (...args: any[]) => Buffer,\n (...args: any[]) => any,\n];\n\nexport type RawAttribute = {\n type: number;\n length?: number;\n value: Buffer;\n};\n\nconst ATTRIBUTES: ATTRIBUTE[] = [\n [0x0001, \"MAPPED-ADDRESS\", packAddress, unpackAddress],\n [0x0003, \"CHANGE-REQUEST\", packUnsigned, unpackUnsigned],\n [0x0004, \"SOURCE-ADDRESS\", packAddress, unpackAddress],\n [0x0005, \"CHANGED-ADDRESS\", packAddress, unpackAddress],\n [0x0006, \"USERNAME\", packString, unpackString],\n [0x0008, \"MESSAGE-INTEGRITY\", packBytes, unpackBytes],\n [0x0009, \"ERROR-CODE\", packErrorCode, unpackErrorCode],\n [\n 0x000a,\n \"UNKNOWN-ATTRIBUTES\",\n packUnknownAttributes,\n unpackUnknownAttributes,\n ],\n [0x000c, \"CHANNEL-NUMBER\", packUnsignedShort, unpackUnsignedShort],\n [0x000d, \"LIFETIME\", packUnsigned, unpackUnsigned],\n [0x0012, \"XOR-PEER-ADDRESS\", packXorAddress, unpackXorAddress],\n [0x0013, \"DATA\", packBytes, unpackBytes],\n [0x0014, \"REALM\", packString, unpackString],\n [0x0015, \"NONCE\", packBytes, unpackBytes],\n [0x0016, \"XOR-RELAYED-ADDRESS\", packXorAddress, unpackXorAddress],\n [0x0017, \"REQUESTED-ADDRESS-FAMILY\", packUnsigned, unpackUnsigned],\n [0x0018, \"EVEN-PORT\", packBytes, unpackBytes],\n [0x0019, \"REQUESTED-TRANSPORT\", packUnsigned, unpackUnsigned],\n [0x001c, \"MESSAGE-INTEGRITY-SHA256\", packBytes, unpackBytes],\n [0x001d, \"PASSWORD-ALGORITHM\", packBytes, unpackBytes],\n [0x001e, \"USERHASH\", packBytes, unpackBytes],\n [0x0020, \"XOR-MAPPED-ADDRESS\", packXorAddress, unpackXorAddress],\n [0x0022, \"RESERVATION-TOKEN\", packBytes, unpackBytes],\n [0x0024, \"PRIORITY\", packUnsigned, unpackUnsigned],\n [0x0025, \"USE-CANDIDATE\", packNone, unpackNone],\n [0x8002, \"PASSWORD-ALGORITHMS\", packBytes, unpackBytes],\n [0x8003, \"ALTERNATE-DOMAIN\", packString, unpackString],\n [0x8022, \"SOFTWARE\", packSoftware, unpackString],\n [0x8023, \"ALTERNATE-SERVER\", packAddress, unpackAddress],\n [0x8028, \"FINGERPRINT\", packUnsigned, unpackUnsigned],\n [0x8029, \"ICE-CONTROLLED\", packUnsigned64, unpackUnsigned64],\n [0x802a, \"ICE-CONTROLLING\", packUnsigned64, unpackUnsigned64],\n [0x802b, \"RESPONSE-ORIGIN\", packAddress, unpackAddress],\n [0x802c, \"OTHER-ADDRESS\", packAddress, unpackAddress],\n];\n\nexport class AttributeRepository {\n constructor(protected attributes: AttributePair[] = []) {}\n\n getAttributes() {\n return this.attributes;\n }\n\n setAttribute(key: AttributeKey, value: any) {\n const existing = this.attributes.find((attribute) => attribute[0] === key);\n if (existing) {\n existing[1] = value;\n } else {\n this.attributes.push([key, value]);\n }\n return this;\n }\n\n getAttributeValue(key: AttributeKey) {\n const attribute = this.attributes.find((candidate) => candidate[0] === key);\n return attribute?.[1];\n }\n\n get attributesKeys(): AttributeKey[] {\n return this.attributes.map((attribute) => attribute[0]);\n }\n\n clear() {\n this.attributes = [];\n }\n}\n\nexport type AttributeKey = (typeof AttributeKeys)[number];\nexport type AttributePair = [AttributeKey, any];\n\nexport const ATTRIBUTES_BY_TYPE = ATTRIBUTES.reduce(\n (acc, cur) => {\n acc[cur[0]] = cur;\n return acc;\n },\n {} as { [key: string]: ATTRIBUTE },\n);\n\nexport const ATTRIBUTES_BY_NAME = ATTRIBUTES.reduce(\n (acc, cur) => {\n acc[cur[1]] = cur;\n return acc;\n },\n {} as { [key: string]: ATTRIBUTE },\n);\n"]}
1
+ {"version":3,"file":"attributes.js","sourceRoot":"","sources":["../../../../../ice-server/src/stun/attributes.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Address } from \"../../../common/src\";\n\nimport {\n type AttributeKeys,\n COOKIE,\n IPV4_PROTOCOL,\n IPV6_PROTOCOL,\n} from \"./const\";\nimport { bufferToIpAddress, ipAddressToBuffer, isIpV4Address } from \"./ip\";\n\nfunction packAddress(value: Address) {\n const [address] = value;\n const protocol = isIpV4Address(address) ? IPV4_PROTOCOL : IPV6_PROTOCOL;\n\n const buffer = Buffer.alloc(4);\n buffer.writeUInt8(0, 0);\n buffer.writeUInt8(protocol, 1);\n buffer.writeUInt16BE(value[1], 2);\n\n return Buffer.concat([buffer, ipAddressToBuffer(address)]);\n}\n\nexport function unpackErrorCode(data: Buffer): [number, string] {\n if (data.length < 4) {\n throw new Error(\"STUN error code is less than 4 bytes\");\n }\n\n const codeHigh = data.readUInt8(2);\n const codeLow = data.readUInt8(3);\n const reason = data.slice(4).toString(\"utf8\");\n return [codeHigh * 100 + codeLow, reason];\n}\n\nfunction unpackAddress(data: Buffer): Address {\n if (data.length < 4) {\n throw new Error(\"STUN address length is less than 4 bytes\");\n }\n\n const protocol = data.readUInt8(1);\n const port = data.readUInt16BE(2);\n const address = data.slice(4);\n\n switch (protocol) {\n case IPV4_PROTOCOL:\n if (address.length !== 4) {\n throw new Error(\"STUN address has invalid length for IPv4\");\n }\n return [bufferToIpAddress(address), port];\n case IPV6_PROTOCOL:\n if (address.length !== 16) {\n throw new Error(\"STUN address has invalid length for IPv6\");\n }\n return [bufferToIpAddress(address), port];\n default:\n throw new Error(\"STUN address has unknown protocol\");\n }\n}\n\nconst cookieBuffer = Buffer.alloc(6);\ncookieBuffer.writeUInt16BE(COOKIE >> 16, 0);\ncookieBuffer.writeUInt32BE(COOKIE, 2);\n\nfunction xorAddress(data: Buffer, transactionId: Buffer) {\n const xPad = [...cookieBuffer, ...transactionId];\n let xData = data.slice(0, 2);\n\n for (let i = 2; i < data.length; i++) {\n const num = data[i] ^ xPad[i - 2];\n const buf = Buffer.alloc(1);\n buf.writeUIntBE(num, 0, 1);\n xData = Buffer.concat([xData, buf]);\n }\n return xData;\n}\n\nexport function unpackXorAddress(data: Buffer, transactionId: Buffer): Address {\n return unpackAddress(xorAddress(data, transactionId));\n}\n\nexport function packErrorCode(value: [number, string]) {\n const buffer = Buffer.alloc(4);\n buffer.writeUInt16BE(0, 0);\n buffer.writeUInt8(Math.floor(value[0] / 100), 2);\n buffer.writeUInt8(value[0] % 100, 3);\n const encoded = Buffer.from(value[1], \"utf8\");\n return Buffer.concat([buffer, encoded]);\n}\n\nexport function packUnknownAttributes(value: number[]) {\n const buffer = Buffer.alloc(value.length * 2);\n value.forEach((attributeType, index) => {\n buffer.writeUInt16BE(attributeType, index * 2);\n });\n return buffer;\n}\n\nexport function unpackUnknownAttributes(data: Buffer) {\n if (data.length % 2 !== 0) {\n throw new Error(\"UNKNOWN-ATTRIBUTES must have an even length\");\n }\n\n const attributes: number[] = [];\n for (let offset = 0; offset < data.length; offset += 2) {\n attributes.push(data.readUInt16BE(offset));\n }\n return attributes;\n}\n\nexport function packXorAddress(value: Address, transactionId: Buffer) {\n return xorAddress(packAddress(value), transactionId);\n}\n\nconst packUnsigned = (value: number) => {\n const buffer = Buffer.alloc(4);\n buffer.writeUInt32BE(value, 0);\n return buffer;\n};\n\nconst unpackUnsigned = (data: Buffer) => data.readUInt32BE(0);\n\nconst packUnsignedShort = (value: number) => {\n const buffer = Buffer.alloc(4);\n buffer.writeUInt16BE(value, 0);\n return buffer;\n};\n\nconst unpackUnsignedShort = (data: Buffer) => data.readUInt16BE(0);\n\nconst packUnsigned64 = (value: bigint) => {\n const buffer = Buffer.allocUnsafe(8);\n buffer.writeBigUInt64BE(value, 0);\n return buffer;\n};\n\nconst unpackUnsigned64 = (data: Buffer) => data.readBigUInt64BE(0);\n\nconst packString = (value: string) => Buffer.from(value, \"utf8\");\nconst unpackString = (data: Buffer) => data.toString(\"utf8\");\n\nconst packSoftware = (value: string) => {\n if ([...value].length >= 128) {\n throw new Error(\"SOFTWARE must be shorter than 128 characters\");\n }\n return packString(value);\n};\n\nconst packBytes = (value: Buffer) => value;\nconst unpackBytes = (data: Buffer) => data;\n\nconst packNone = () => Buffer.alloc(0);\nconst unpackNone = () => null;\n\nexport type ATTRIBUTE = [\n number,\n AttributeKey,\n (...args: any[]) => Buffer,\n (...args: any[]) => any,\n];\n\nexport type RawAttribute = {\n type: number;\n length?: number;\n value: Buffer;\n};\n\nconst ATTRIBUTES: ATTRIBUTE[] = [\n [0x0001, \"MAPPED-ADDRESS\", packAddress, unpackAddress],\n [0x0003, \"CHANGE-REQUEST\", packUnsigned, unpackUnsigned],\n [0x0004, \"SOURCE-ADDRESS\", packAddress, unpackAddress],\n [0x0005, \"CHANGED-ADDRESS\", packAddress, unpackAddress],\n [0x0006, \"USERNAME\", packString, unpackString],\n [0x0008, \"MESSAGE-INTEGRITY\", packBytes, unpackBytes],\n [0x0009, \"ERROR-CODE\", packErrorCode, unpackErrorCode],\n [\n 0x000a,\n \"UNKNOWN-ATTRIBUTES\",\n packUnknownAttributes,\n unpackUnknownAttributes,\n ],\n [0x000c, \"CHANNEL-NUMBER\", packUnsignedShort, unpackUnsignedShort],\n [0x000d, \"LIFETIME\", packUnsigned, unpackUnsigned],\n [0x0012, \"XOR-PEER-ADDRESS\", packXorAddress, unpackXorAddress],\n [0x0013, \"DATA\", packBytes, unpackBytes],\n [0x0014, \"REALM\", packString, unpackString],\n [0x0015, \"NONCE\", packBytes, unpackBytes],\n [0x0016, \"XOR-RELAYED-ADDRESS\", packXorAddress, unpackXorAddress],\n [0x0017, \"REQUESTED-ADDRESS-FAMILY\", packUnsigned, unpackUnsigned],\n [0x0018, \"EVEN-PORT\", packBytes, unpackBytes],\n [0x0019, \"REQUESTED-TRANSPORT\", packUnsigned, unpackUnsigned],\n [0x001c, \"MESSAGE-INTEGRITY-SHA256\", packBytes, unpackBytes],\n [0x001d, \"PASSWORD-ALGORITHM\", packBytes, unpackBytes],\n [0x001e, \"USERHASH\", packBytes, unpackBytes],\n [0x0020, \"XOR-MAPPED-ADDRESS\", packXorAddress, unpackXorAddress],\n [0x0022, \"RESERVATION-TOKEN\", packBytes, unpackBytes],\n [0x0024, \"PRIORITY\", packUnsigned, unpackUnsigned],\n [0x0025, \"USE-CANDIDATE\", packNone, unpackNone],\n [0x8002, \"PASSWORD-ALGORITHMS\", packBytes, unpackBytes],\n [0x8003, \"ALTERNATE-DOMAIN\", packString, unpackString],\n [0x8022, \"SOFTWARE\", packSoftware, unpackString],\n [0x8023, \"ALTERNATE-SERVER\", packAddress, unpackAddress],\n [0x8028, \"FINGERPRINT\", packUnsigned, unpackUnsigned],\n [0x8029, \"ICE-CONTROLLED\", packUnsigned64, unpackUnsigned64],\n [0x802a, \"ICE-CONTROLLING\", packUnsigned64, unpackUnsigned64],\n [0x802b, \"RESPONSE-ORIGIN\", packAddress, unpackAddress],\n [0x802c, \"OTHER-ADDRESS\", packAddress, unpackAddress],\n];\n\nexport class AttributeRepository {\n constructor(protected attributes: AttributePair[] = []) {}\n\n getAttributes() {\n return this.attributes;\n }\n\n setAttribute(key: AttributeKey, value: any) {\n const existing = this.attributes.find((attribute) => attribute[0] === key);\n if (existing) {\n existing[1] = value;\n } else {\n this.attributes.push([key, value]);\n }\n return this;\n }\n\n getAttributeValue(key: AttributeKey) {\n const attribute = this.attributes.find((candidate) => candidate[0] === key);\n return attribute?.[1];\n }\n\n get attributesKeys(): AttributeKey[] {\n return this.attributes.map((attribute) => attribute[0]);\n }\n\n clear() {\n this.attributes = [];\n }\n}\n\nexport type AttributeKey = (typeof AttributeKeys)[number];\nexport type AttributePair = [AttributeKey, any];\n\nexport const ATTRIBUTES_BY_TYPE = ATTRIBUTES.reduce(\n (acc, cur) => {\n acc[cur[0]] = cur;\n return acc;\n },\n {} as { [key: string]: ATTRIBUTE },\n);\n\nexport const ATTRIBUTES_BY_NAME = ATTRIBUTES.reduce(\n (acc, cur) => {\n acc[cur[1]] = cur;\n return acc;\n },\n {} as { [key: string]: ATTRIBUTE },\n);\n"]}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Convert an IPv4 / IPv6 text address to the STUN wire binary form.
3
+ * IPv4 → 4 bytes, IPv6 → 16 bytes (supports :: compression and IPv4-mapped).
4
+ */
5
+ export declare function ipAddressToBuffer(address: string): Buffer;
6
+ /**
7
+ * Convert STUN address bytes (4 or 16) back to a text IP address.
8
+ * IPv6 uses the same zero-run compression style as the previous `ip` helper.
9
+ */
10
+ export declare function bufferToIpAddress(buf: Buffer): string;
11
+ export declare function isIpV4Address(address: string): boolean;
12
+ export declare function isIpV6Address(address: string): boolean;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ipAddressToBuffer = ipAddressToBuffer;
4
+ exports.bufferToIpAddress = bufferToIpAddress;
5
+ exports.isIpV4Address = isIpV4Address;
6
+ exports.isIpV6Address = isIpV6Address;
7
+ const node_net_1 = require("node:net");
8
+ /**
9
+ * Convert an IPv4 / IPv6 text address to the STUN wire binary form.
10
+ * IPv4 → 4 bytes, IPv6 → 16 bytes (supports :: compression and IPv4-mapped).
11
+ */
12
+ function ipAddressToBuffer(address) {
13
+ if ((0, node_net_1.isIPv4)(address)) {
14
+ const buf = Buffer.allocUnsafe(4);
15
+ const parts = address.split(".");
16
+ for (let i = 0; i < 4; i++) {
17
+ buf[i] = Number(parts[i]) & 0xff;
18
+ }
19
+ return buf;
20
+ }
21
+ if (!(0, node_net_1.isIPv6)(address)) {
22
+ throw new Error(`Invalid ip address: ${address}`);
23
+ }
24
+ const sections = address.split(":", 8);
25
+ for (let i = 0; i < sections.length; i++) {
26
+ let v4Buffer;
27
+ if ((0, node_net_1.isIPv4)(sections[i])) {
28
+ v4Buffer = ipAddressToBuffer(sections[i]);
29
+ sections[i] = v4Buffer.subarray(0, 2).toString("hex");
30
+ }
31
+ if (v4Buffer && ++i < 8) {
32
+ sections.splice(i, 0, v4Buffer.subarray(2, 4).toString("hex"));
33
+ }
34
+ }
35
+ if (sections[0] === "") {
36
+ while (sections.length < 8)
37
+ sections.unshift("0");
38
+ }
39
+ else if (sections[sections.length - 1] === "") {
40
+ while (sections.length < 8)
41
+ sections.push("0");
42
+ }
43
+ else if (sections.length < 8) {
44
+ let emptyIndex = 0;
45
+ for (; emptyIndex < sections.length && sections[emptyIndex] !== ""; emptyIndex++)
46
+ ;
47
+ const zeros = [];
48
+ for (let n = 9 - sections.length; n > 0; n--) {
49
+ zeros.push("0");
50
+ }
51
+ sections.splice(emptyIndex, 1, ...zeros);
52
+ }
53
+ const result = Buffer.allocUnsafe(16);
54
+ let offset = 0;
55
+ for (const section of sections) {
56
+ const word = Number.parseInt(section, 16) || 0;
57
+ result[offset++] = (word >> 8) & 0xff;
58
+ result[offset++] = word & 0xff;
59
+ }
60
+ return result;
61
+ }
62
+ /**
63
+ * Convert STUN address bytes (4 or 16) back to a text IP address.
64
+ * IPv6 uses the same zero-run compression style as the previous `ip` helper.
65
+ */
66
+ function bufferToIpAddress(buf) {
67
+ if (buf.length === 4) {
68
+ return `${buf[0]}.${buf[1]}.${buf[2]}.${buf[3]}`;
69
+ }
70
+ if (buf.length !== 16) {
71
+ throw new Error(`Invalid ip address buffer length: ${buf.length}`);
72
+ }
73
+ const hextets = [];
74
+ for (let i = 0; i < 16; i += 2) {
75
+ hextets.push(buf.readUInt16BE(i).toString(16));
76
+ }
77
+ let result = hextets.join(":");
78
+ result = result.replace(/(^|:)0(:0)*:0(:|$)/, "$1::$3");
79
+ result = result.replace(/:{3,4}/, "::");
80
+ return result;
81
+ }
82
+ function isIpV4Address(address) {
83
+ return (0, node_net_1.isIPv4)(address);
84
+ }
85
+ function isIpV6Address(address) {
86
+ return (0, node_net_1.isIPv6)(address);
87
+ }
88
+ //# sourceMappingURL=ip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ip.js","sourceRoot":"","sources":["../../../../../ice-server/src/stun/ip.ts"],"names":[],"mappings":"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","sourcesContent":["import { isIPv4, isIPv6 } from \"node:net\";\n\n/**\n * Convert an IPv4 / IPv6 text address to the STUN wire binary form.\n * IPv4 → 4 bytes, IPv6 → 16 bytes (supports :: compression and IPv4-mapped).\n */\nexport function ipAddressToBuffer(address: string): Buffer {\n if (isIPv4(address)) {\n const buf = Buffer.allocUnsafe(4);\n const parts = address.split(\".\");\n for (let i = 0; i < 4; i++) {\n buf[i] = Number(parts[i]) & 0xff;\n }\n return buf;\n }\n\n if (!isIPv6(address)) {\n throw new Error(`Invalid ip address: ${address}`);\n }\n\n const sections = address.split(\":\", 8);\n for (let i = 0; i < sections.length; i++) {\n let v4Buffer: Buffer | undefined;\n if (isIPv4(sections[i])) {\n v4Buffer = ipAddressToBuffer(sections[i]);\n sections[i] = v4Buffer.subarray(0, 2).toString(\"hex\");\n }\n if (v4Buffer && ++i < 8) {\n sections.splice(i, 0, v4Buffer.subarray(2, 4).toString(\"hex\"));\n }\n }\n\n if (sections[0] === \"\") {\n while (sections.length < 8) sections.unshift(\"0\");\n } else if (sections[sections.length - 1] === \"\") {\n while (sections.length < 8) sections.push(\"0\");\n } else if (sections.length < 8) {\n let emptyIndex = 0;\n for (\n ;\n emptyIndex < sections.length && sections[emptyIndex] !== \"\";\n emptyIndex++\n );\n const zeros: string[] = [];\n for (let n = 9 - sections.length; n > 0; n--) {\n zeros.push(\"0\");\n }\n sections.splice(emptyIndex, 1, ...zeros);\n }\n\n const result = Buffer.allocUnsafe(16);\n let offset = 0;\n for (const section of sections) {\n const word = Number.parseInt(section, 16) || 0;\n result[offset++] = (word >> 8) & 0xff;\n result[offset++] = word & 0xff;\n }\n return result;\n}\n\n/**\n * Convert STUN address bytes (4 or 16) back to a text IP address.\n * IPv6 uses the same zero-run compression style as the previous `ip` helper.\n */\nexport function bufferToIpAddress(buf: Buffer): string {\n if (buf.length === 4) {\n return `${buf[0]}.${buf[1]}.${buf[2]}.${buf[3]}`;\n }\n\n if (buf.length !== 16) {\n throw new Error(`Invalid ip address buffer length: ${buf.length}`);\n }\n\n const hextets: string[] = [];\n for (let i = 0; i < 16; i += 2) {\n hextets.push(buf.readUInt16BE(i).toString(16));\n }\n let result = hextets.join(\":\");\n result = result.replace(/(^|:)0(:0)*:0(:|$)/, \"$1::$3\");\n result = result.replace(/:{3,4}/, \"::\");\n return result;\n}\n\nexport function isIpV4Address(address: string): boolean {\n return isIPv4(address);\n}\n\nexport function isIpV6Address(address: string): boolean {\n return isIPv6(address);\n}\n"]}
@@ -15,6 +15,9 @@ function parseMessage(data, integrityKey) {
15
15
  const transactionId = Buffer.from(data.slice(const_1.HEADER_LENGTH - 12, const_1.HEADER_LENGTH));
16
16
  const attributeRepository = new attributes_1.AttributeRepository();
17
17
  const rawAttributes = [];
18
+ // When integrityKey is provided, MESSAGE-INTEGRITY must be present and valid
19
+ // (RFC 5389 short-term credentials / RFC 7675 authenticated consent responses).
20
+ let messageIntegrityVerified = false;
18
21
  for (let pos = const_1.HEADER_LENGTH; pos < data.length;) {
19
22
  if (pos + 4 > data.length) {
20
23
  return undefined;
@@ -57,6 +60,7 @@ function parseMessage(data, integrityKey) {
57
60
  if (!integrity.equals(expected)) {
58
61
  return undefined;
59
62
  }
63
+ messageIntegrityVerified = true;
60
64
  }
61
65
  }
62
66
  else {
@@ -68,6 +72,10 @@ function parseMessage(data, integrityKey) {
68
72
  }
69
73
  pos = valueEnd + padLen;
70
74
  }
75
+ // Reject unsigned messages when the caller required authentication.
76
+ if (integrityKey && !messageIntegrityVerified) {
77
+ return undefined;
78
+ }
71
79
  return new Message(messageType & 0x3eef, messageType & 0x0110, transactionId, attributeRepository.getAttributes(), rawAttributes);
72
80
  }
73
81
  class Message extends attributes_1.AttributeRepository {
@@ -1 +1 @@
1
- {"version":3,"file":"message.js","sourceRoot":"","sources":["../../../../../ice-server/src/stun/message.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, randomBytes } from \"crypto\";\n\nimport { crc32 } from \"../../../common/src\";\n\nimport {\n ATTRIBUTES_BY_NAME,\n ATTRIBUTES_BY_TYPE,\n type AttributeKey,\n type AttributePair,\n AttributeRepository,\n type RawAttribute,\n packXorAddress,\n unpackXorAddress,\n} from \"./attributes\";\nimport {\n COOKIE,\n FINGERPRINT_LENGTH,\n FINGERPRINT_XOR,\n HEADER_LENGTH,\n INTEGRITY_LENGTH,\n type classes,\n isStunMessage,\n type methods,\n} from \"./const\";\n\nexport function parseMessage(\n data: Buffer,\n integrityKey?: Buffer,\n): Message | undefined {\n if (!isStunMessage(data)) {\n return undefined;\n }\n\n const messageType = data.readUInt16BE(0);\n const transactionId = Buffer.from(\n data.slice(HEADER_LENGTH - 12, HEADER_LENGTH),\n );\n\n const attributeRepository = new AttributeRepository();\n const rawAttributes: RawAttribute[] = [];\n\n for (let pos = HEADER_LENGTH; pos < data.length; ) {\n if (pos + 4 > data.length) {\n return undefined;\n }\n\n const attrType = data.readUInt16BE(pos);\n const attrLen = data.readUInt16BE(pos + 2);\n const valueStart = pos + 4;\n const valueEnd = valueStart + attrLen;\n\n if (valueEnd > data.length) {\n return undefined;\n }\n\n const payload = data.slice(valueStart, valueEnd);\n const padLen = paddingLength(attrLen);\n if (valueEnd + padLen > data.length) {\n return undefined;\n }\n\n const attribute = ATTRIBUTES_BY_TYPE[attrType];\n if (attribute) {\n const [, attrName, , attrUnpack] = attribute;\n let value: unknown;\n try {\n value =\n attrUnpack.name === unpackXorAddress.name\n ? attrUnpack(payload, transactionId)\n : attrUnpack(payload);\n } catch {\n return undefined;\n }\n attributeRepository.setAttribute(attrName as AttributeKey, value);\n\n if (attrName === \"FINGERPRINT\") {\n const fingerprint = messageFingerprint(data.slice(0, pos));\n if (\n attributeRepository.getAttributeValue(\"FINGERPRINT\") !== fingerprint\n ) {\n return undefined;\n }\n } else if (attrName === \"MESSAGE-INTEGRITY\" && integrityKey) {\n const integrity = messageIntegrity(data.slice(0, pos), integrityKey);\n const expected =\n attributeRepository.getAttributeValue(\"MESSAGE-INTEGRITY\");\n if (!integrity.equals(expected)) {\n return undefined;\n }\n }\n } else {\n rawAttributes.push({\n type: attrType,\n length: attrLen,\n value: Buffer.from(payload),\n });\n }\n\n pos = valueEnd + padLen;\n }\n\n return new Message(\n messageType & 0x3eef,\n messageType & 0x0110,\n transactionId,\n attributeRepository.getAttributes(),\n rawAttributes,\n );\n}\n\nexport class Message extends AttributeRepository {\n constructor(\n public messageMethod: methods,\n public messageClass: classes,\n public transactionId: Buffer = randomBytes(12),\n attributes: AttributePair[] = [],\n public rawAttributes: RawAttribute[] = [],\n ) {\n super(attributes);\n }\n\n toJSON() {\n return this.json;\n }\n\n get json() {\n return {\n messageMethod: this.messageMethod,\n messageClass: this.messageClass,\n attributes: this.attributes,\n rawAttributes: this.rawAttributes.map((attribute) => ({\n type: attribute.type,\n length: attribute.value.length,\n })),\n };\n }\n\n get transactionIdHex() {\n return this.transactionId.toString(\"hex\");\n }\n\n appendRawAttribute(type: number, value: Buffer) {\n this.rawAttributes.push({ type, value: Buffer.from(value) });\n return this;\n }\n\n get unknownAttributeTypes() {\n return this.rawAttributes.map((attribute) => attribute.type);\n }\n\n get bytes() {\n const body = Buffer.concat(\n this.serializedAttributes.map((attribute) =>\n serializeAttribute(attribute.type, attribute.value),\n ),\n );\n\n const header = Buffer.alloc(8);\n header.writeUInt16BE(this.messageMethod | this.messageClass, 0);\n header.writeUInt16BE(body.length, 2);\n header.writeUInt32BE(COOKIE, 4);\n\n return Buffer.concat([header, this.transactionId, body]);\n }\n\n addMessageIntegrity(key: Buffer) {\n this.setAttribute(\"MESSAGE-INTEGRITY\", this.messageIntegrity(key));\n return this;\n }\n\n messageIntegrity(key: Buffer) {\n const checkData = setBodyLength(\n this.bytes,\n this.bytes.length - HEADER_LENGTH + INTEGRITY_LENGTH,\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\",\n );\n }\n\n addFingerprint() {\n this.setAttribute(\"FINGERPRINT\", messageFingerprint(this.bytes));\n return this;\n }\n\n private get serializedAttributes() {\n const attributes: RawAttribute[] = [];\n\n for (const attrName of this.attributesKeys) {\n const attrValue = this.getAttributeValue(attrName);\n const [attrType, , attrPack] = ATTRIBUTES_BY_NAME[attrName];\n const value =\n attrPack.name === packXorAddress.name\n ? attrPack(attrValue, this.transactionId)\n : attrPack(attrValue);\n attributes.push({ type: attrType, value });\n }\n\n attributes.push(\n ...this.rawAttributes.map((attribute) => ({\n type: attribute.type,\n value: Buffer.from(attribute.value),\n })),\n );\n\n return attributes;\n }\n}\n\nfunction serializeAttribute(type: number, value: Buffer) {\n const attrLen = value.length;\n const padLen = paddingLength(attrLen);\n const header = Buffer.alloc(4);\n header.writeUInt16BE(type, 0);\n header.writeUInt16BE(attrLen, 2);\n return Buffer.concat([header, value, Buffer.alloc(padLen)]);\n}\n\nconst setBodyLength = (data: Buffer, length: number) => {\n const output = Buffer.alloc(data.length);\n data.copy(output, 0, 0, 2);\n output.writeUInt16BE(length, 2);\n data.copy(output, 4, 4);\n return output;\n};\n\nfunction messageFingerprint(data: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + FINGERPRINT_LENGTH,\n );\n return (crc32(checkData) ^ FINGERPRINT_XOR) >>> 0;\n}\n\nfunction messageIntegrity(data: Buffer, key: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + INTEGRITY_LENGTH,\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\",\n );\n}\n\nexport function paddingLength(length: number) {\n const rest = length % 4;\n return rest === 0 ? 0 : 4 - rest;\n}\n"]}
1
+ {"version":3,"file":"message.js","sourceRoot":"","sources":["../../../../../ice-server/src/stun/message.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, randomBytes } from \"crypto\";\n\nimport { crc32 } from \"../../../common/src\";\n\nimport {\n ATTRIBUTES_BY_NAME,\n ATTRIBUTES_BY_TYPE,\n type AttributeKey,\n type AttributePair,\n AttributeRepository,\n type RawAttribute,\n packXorAddress,\n unpackXorAddress,\n} from \"./attributes\";\nimport {\n COOKIE,\n FINGERPRINT_LENGTH,\n FINGERPRINT_XOR,\n HEADER_LENGTH,\n INTEGRITY_LENGTH,\n type classes,\n isStunMessage,\n type methods,\n} from \"./const\";\n\nexport function parseMessage(\n data: Buffer,\n integrityKey?: Buffer,\n): Message | undefined {\n if (!isStunMessage(data)) {\n return undefined;\n }\n\n const messageType = data.readUInt16BE(0);\n const transactionId = Buffer.from(\n data.slice(HEADER_LENGTH - 12, HEADER_LENGTH),\n );\n\n const attributeRepository = new AttributeRepository();\n const rawAttributes: RawAttribute[] = [];\n // When integrityKey is provided, MESSAGE-INTEGRITY must be present and valid\n // (RFC 5389 short-term credentials / RFC 7675 authenticated consent responses).\n let messageIntegrityVerified = false;\n\n for (let pos = HEADER_LENGTH; pos < data.length; ) {\n if (pos + 4 > data.length) {\n return undefined;\n }\n\n const attrType = data.readUInt16BE(pos);\n const attrLen = data.readUInt16BE(pos + 2);\n const valueStart = pos + 4;\n const valueEnd = valueStart + attrLen;\n\n if (valueEnd > data.length) {\n return undefined;\n }\n\n const payload = data.slice(valueStart, valueEnd);\n const padLen = paddingLength(attrLen);\n if (valueEnd + padLen > data.length) {\n return undefined;\n }\n\n const attribute = ATTRIBUTES_BY_TYPE[attrType];\n if (attribute) {\n const [, attrName, , attrUnpack] = attribute;\n let value: unknown;\n try {\n value =\n attrUnpack.name === unpackXorAddress.name\n ? attrUnpack(payload, transactionId)\n : attrUnpack(payload);\n } catch {\n return undefined;\n }\n attributeRepository.setAttribute(attrName as AttributeKey, value);\n\n if (attrName === \"FINGERPRINT\") {\n const fingerprint = messageFingerprint(data.slice(0, pos));\n if (\n attributeRepository.getAttributeValue(\"FINGERPRINT\") !== fingerprint\n ) {\n return undefined;\n }\n } else if (attrName === \"MESSAGE-INTEGRITY\" && integrityKey) {\n const integrity = messageIntegrity(data.slice(0, pos), integrityKey);\n const expected =\n attributeRepository.getAttributeValue(\"MESSAGE-INTEGRITY\");\n if (!integrity.equals(expected)) {\n return undefined;\n }\n messageIntegrityVerified = true;\n }\n } else {\n rawAttributes.push({\n type: attrType,\n length: attrLen,\n value: Buffer.from(payload),\n });\n }\n\n pos = valueEnd + padLen;\n }\n\n // Reject unsigned messages when the caller required authentication.\n if (integrityKey && !messageIntegrityVerified) {\n return undefined;\n }\n\n return new Message(\n messageType & 0x3eef,\n messageType & 0x0110,\n transactionId,\n attributeRepository.getAttributes(),\n rawAttributes,\n );\n}\n\nexport class Message extends AttributeRepository {\n constructor(\n public messageMethod: methods,\n public messageClass: classes,\n public transactionId: Buffer = randomBytes(12),\n attributes: AttributePair[] = [],\n public rawAttributes: RawAttribute[] = [],\n ) {\n super(attributes);\n }\n\n toJSON() {\n return this.json;\n }\n\n get json() {\n return {\n messageMethod: this.messageMethod,\n messageClass: this.messageClass,\n attributes: this.attributes,\n rawAttributes: this.rawAttributes.map((attribute) => ({\n type: attribute.type,\n length: attribute.value.length,\n })),\n };\n }\n\n get transactionIdHex() {\n return this.transactionId.toString(\"hex\");\n }\n\n appendRawAttribute(type: number, value: Buffer) {\n this.rawAttributes.push({ type, value: Buffer.from(value) });\n return this;\n }\n\n get unknownAttributeTypes() {\n return this.rawAttributes.map((attribute) => attribute.type);\n }\n\n get bytes() {\n const body = Buffer.concat(\n this.serializedAttributes.map((attribute) =>\n serializeAttribute(attribute.type, attribute.value),\n ),\n );\n\n const header = Buffer.alloc(8);\n header.writeUInt16BE(this.messageMethod | this.messageClass, 0);\n header.writeUInt16BE(body.length, 2);\n header.writeUInt32BE(COOKIE, 4);\n\n return Buffer.concat([header, this.transactionId, body]);\n }\n\n addMessageIntegrity(key: Buffer) {\n this.setAttribute(\"MESSAGE-INTEGRITY\", this.messageIntegrity(key));\n return this;\n }\n\n messageIntegrity(key: Buffer) {\n const checkData = setBodyLength(\n this.bytes,\n this.bytes.length - HEADER_LENGTH + INTEGRITY_LENGTH,\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\",\n );\n }\n\n addFingerprint() {\n this.setAttribute(\"FINGERPRINT\", messageFingerprint(this.bytes));\n return this;\n }\n\n private get serializedAttributes() {\n const attributes: RawAttribute[] = [];\n\n for (const attrName of this.attributesKeys) {\n const attrValue = this.getAttributeValue(attrName);\n const [attrType, , attrPack] = ATTRIBUTES_BY_NAME[attrName];\n const value =\n attrPack.name === packXorAddress.name\n ? attrPack(attrValue, this.transactionId)\n : attrPack(attrValue);\n attributes.push({ type: attrType, value });\n }\n\n attributes.push(\n ...this.rawAttributes.map((attribute) => ({\n type: attribute.type,\n value: Buffer.from(attribute.value),\n })),\n );\n\n return attributes;\n }\n}\n\nfunction serializeAttribute(type: number, value: Buffer) {\n const attrLen = value.length;\n const padLen = paddingLength(attrLen);\n const header = Buffer.alloc(4);\n header.writeUInt16BE(type, 0);\n header.writeUInt16BE(attrLen, 2);\n return Buffer.concat([header, value, Buffer.alloc(padLen)]);\n}\n\nconst setBodyLength = (data: Buffer, length: number) => {\n const output = Buffer.alloc(data.length);\n data.copy(output, 0, 0, 2);\n output.writeUInt16BE(length, 2);\n data.copy(output, 4, 4);\n return output;\n};\n\nfunction messageFingerprint(data: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + FINGERPRINT_LENGTH,\n );\n return (crc32(checkData) ^ FINGERPRINT_XOR) >>> 0;\n}\n\nfunction messageIntegrity(data: Buffer, key: Buffer) {\n const checkData = setBodyLength(\n data,\n data.length - HEADER_LENGTH + INTEGRITY_LENGTH,\n );\n return Buffer.from(\n createHmac(\"sha1\", key).update(checkData).digest(\"hex\"),\n \"hex\",\n );\n}\n\nexport function paddingLength(length: number) {\n const rest = length % 4;\n return rest === 0 ? 0 : 4 - rest;\n}\n"]}