node-rtc-connection 2.0.4 → 2.0.5

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 (53) hide show
  1. package/index.cjs +1 -0
  2. package/index.mjs +1 -0
  3. package/package.json +10 -47
  4. package/dist/index.cjs +0 -32
  5. package/dist/index.mjs +0 -43
  6. package/src/crypto/der.ts +0 -205
  7. package/src/crypto/x509.ts +0 -146
  8. package/src/datachannel/RTCDataChannel.ts +0 -388
  9. package/src/dtls/RTCCertificate.ts +0 -396
  10. package/src/dtls/cipher.ts +0 -198
  11. package/src/dtls/connection.ts +0 -974
  12. package/src/dtls/prf.ts +0 -62
  13. package/src/dtls/protocol.ts +0 -204
  14. package/src/foundation/ByteBufferQueue.ts +0 -237
  15. package/src/foundation/RTCError.ts +0 -276
  16. package/src/ice/RTCIceCandidate.ts +0 -349
  17. package/src/ice/ice-agent.ts +0 -609
  18. package/src/ice/stun-message.ts +0 -260
  19. package/src/index.ts +0 -72
  20. package/src/peerconnection/RTCPeerConnection.ts +0 -430
  21. package/src/sctp/association.ts +0 -523
  22. package/src/sctp/chunks.ts +0 -350
  23. package/src/sctp/crc32c.ts +0 -57
  24. package/src/sctp/datachannel-manager.ts +0 -187
  25. package/src/sctp/dcep.ts +0 -94
  26. package/src/sdp/RTCSessionDescription.ts +0 -115
  27. package/src/sdp/sdp-utils.ts +0 -229
  28. package/src/stun/stun-client.ts +0 -936
  29. package/src/transport-stack.ts +0 -165
  30. /package/{dist/types → types}/crypto/der.d.ts +0 -0
  31. /package/{dist/types → types}/crypto/x509.d.ts +0 -0
  32. /package/{dist/types → types}/datachannel/RTCDataChannel.d.ts +0 -0
  33. /package/{dist/types → types}/dtls/RTCCertificate.d.ts +0 -0
  34. /package/{dist/types → types}/dtls/cipher.d.ts +0 -0
  35. /package/{dist/types → types}/dtls/connection.d.ts +0 -0
  36. /package/{dist/types → types}/dtls/prf.d.ts +0 -0
  37. /package/{dist/types → types}/dtls/protocol.d.ts +0 -0
  38. /package/{dist/types → types}/foundation/ByteBufferQueue.d.ts +0 -0
  39. /package/{dist/types → types}/foundation/RTCError.d.ts +0 -0
  40. /package/{dist/types → types}/ice/RTCIceCandidate.d.ts +0 -0
  41. /package/{dist/types → types}/ice/ice-agent.d.ts +0 -0
  42. /package/{dist/types → types}/ice/stun-message.d.ts +0 -0
  43. /package/{dist/types → types}/index.d.ts +0 -0
  44. /package/{dist/types → types}/peerconnection/RTCPeerConnection.d.ts +0 -0
  45. /package/{dist/types → types}/sctp/association.d.ts +0 -0
  46. /package/{dist/types → types}/sctp/chunks.d.ts +0 -0
  47. /package/{dist/types → types}/sctp/crc32c.d.ts +0 -0
  48. /package/{dist/types → types}/sctp/datachannel-manager.d.ts +0 -0
  49. /package/{dist/types → types}/sctp/dcep.d.ts +0 -0
  50. /package/{dist/types → types}/sdp/RTCSessionDescription.d.ts +0 -0
  51. /package/{dist/types → types}/sdp/sdp-utils.d.ts +0 -0
  52. /package/{dist/types → types}/stun/stun-client.d.ts +0 -0
  53. /package/{dist/types → types}/transport-stack.d.ts +0 -0
package/src/dtls/prf.ts DELETED
@@ -1,62 +0,0 @@
1
- /**
2
- * @file prf.ts
3
- * @description TLS 1.2 pseudo-random function (RFC 5246 §5) with SHA-256.
4
- * @module dtls/prf
5
- *
6
- * The cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uses P_SHA256 for
7
- * the PRF. This module also exposes the underlying HMAC-based P_hash.
8
- */
9
-
10
- 'use strict';
11
-
12
- import * as crypto from 'crypto';
13
-
14
- /**
15
- * P_hash(secret, seed) expanded to `length` bytes (RFC 5246 §5).
16
- * A(0) = seed
17
- * A(i) = HMAC(secret, A(i-1))
18
- * P_hash = HMAC(secret, A(1)+seed) | HMAC(secret, A(2)+seed) | ...
19
- *
20
- * @param hashAlg - Node hash name, e.g. 'sha256'.
21
- * @param secret
22
- * @param seed
23
- * @param length
24
- */
25
- export function pHash(
26
- hashAlg: string,
27
- secret: Buffer,
28
- seed: Buffer,
29
- length: number
30
- ): Buffer {
31
- const out: Buffer[] = [];
32
- let total = 0;
33
- let a = seed; // A(0)
34
- while (total < length) {
35
- a = crypto.createHmac(hashAlg, secret).update(a).digest(); // A(i)
36
- const chunk = crypto
37
- .createHmac(hashAlg, secret)
38
- .update(Buffer.concat([a, seed]))
39
- .digest();
40
- out.push(chunk);
41
- total += chunk.length;
42
- }
43
- return Buffer.concat(out).slice(0, length);
44
- }
45
-
46
- /**
47
- * TLS 1.2 PRF = P_SHA256(secret, label + seed).
48
- *
49
- * @param secret
50
- * @param label - ASCII label, e.g. "master secret".
51
- * @param seed
52
- * @param length
53
- */
54
- export function prf(
55
- secret: Buffer,
56
- label: string,
57
- seed: Buffer,
58
- length: number
59
- ): Buffer {
60
- const labelAndSeed = Buffer.concat([Buffer.from(label, 'ascii'), seed]);
61
- return pHash('sha256', secret, labelAndSeed, length);
62
- }
@@ -1,204 +0,0 @@
1
- /**
2
- * @file protocol.ts
3
- * @description DTLS 1.2 wire-format constants and TLV/vector encoders.
4
- * @module dtls/protocol
5
- *
6
- * Covers exactly what WebRTC's data channel needs:
7
- * cipher suite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xC02B)
8
- * curve secp256r1, signature scheme ecdsa_secp256r1_sha256.
9
- *
10
- * References: RFC 6347 (DTLS 1.2), RFC 5246 (TLS 1.2), RFC 8422 (ECC).
11
- */
12
-
13
- 'use strict';
14
-
15
- // DTLS 1.2 on the wire is version 0xFEFD (i.e. ~1.2).
16
- export const DTLS_1_2 = 0xfefd;
17
-
18
- export const CONTENT_TYPE = Object.freeze({
19
- CHANGE_CIPHER_SPEC: 20,
20
- ALERT: 21,
21
- HANDSHAKE: 22,
22
- APPLICATION_DATA: 23,
23
- });
24
-
25
- export const HANDSHAKE_TYPE = Object.freeze({
26
- HELLO_REQUEST: 0,
27
- CLIENT_HELLO: 1,
28
- SERVER_HELLO: 2,
29
- HELLO_VERIFY_REQUEST: 3,
30
- CERTIFICATE: 11,
31
- SERVER_KEY_EXCHANGE: 12,
32
- CERTIFICATE_REQUEST: 13,
33
- SERVER_HELLO_DONE: 14,
34
- CERTIFICATE_VERIFY: 15,
35
- CLIENT_KEY_EXCHANGE: 16,
36
- FINISHED: 20,
37
- });
38
-
39
- export const ALERT_LEVEL = Object.freeze({ WARNING: 1, FATAL: 2 });
40
- export const ALERT_DESC = Object.freeze({
41
- CLOSE_NOTIFY: 0,
42
- HANDSHAKE_FAILURE: 40,
43
- BAD_CERTIFICATE: 42,
44
- DECRYPT_ERROR: 51,
45
- INTERNAL_ERROR: 80,
46
- });
47
-
48
- // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
49
- export const CIPHER_SUITE = 0xc02b;
50
-
51
- export const NAMED_GROUP = Object.freeze({ secp256r1: 0x0017 });
52
- export const EC_POINT_FORMAT = Object.freeze({ uncompressed: 0 });
53
-
54
- // SignatureAndHashAlgorithm
55
- export const HASH_ALG = Object.freeze({ sha256: 4, sha384: 5, sha512: 6 });
56
- export const SIG_ALG = Object.freeze({ rsa: 1, ecdsa: 3 });
57
-
58
- // ClientCertificateType
59
- export const CERT_TYPE = Object.freeze({ ecdsa_sign: 64, rsa_sign: 1 });
60
-
61
- export const EXTENSION = Object.freeze({
62
- SUPPORTED_GROUPS: 10,
63
- EC_POINT_FORMATS: 11,
64
- SIGNATURE_ALGORITHMS: 13,
65
- EXTENDED_MASTER_SECRET: 23,
66
- RENEGOTIATION_INFO: 0xff01,
67
- });
68
-
69
- export const FINISHED_LABEL = Object.freeze({
70
- CLIENT: 'client finished',
71
- SERVER: 'server finished',
72
- });
73
-
74
- /** A parsed DTLS record from {@link parseRecords}. */
75
- export interface Record {
76
- type: number;
77
- version: number;
78
- epoch: number;
79
- seq: number;
80
- fragment: Buffer;
81
- }
82
-
83
- /** A parsed handshake message header from {@link parseHandshake}. */
84
- export interface Handshake {
85
- msgType: number;
86
- length: number;
87
- messageSeq: number;
88
- fragmentOffset: number;
89
- fragmentLength: number;
90
- body: Buffer;
91
- }
92
-
93
- // ---- Vector / integer encoders -------------------------------------------
94
-
95
- /** Encode a uint24 (3 bytes, big-endian). */
96
- export function uint24(n: number): Buffer {
97
- return Buffer.from([(n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]);
98
- }
99
-
100
- /** Read a uint24 at offset. */
101
- export function readUint24(buf: Buffer, off: number): number {
102
- return (buf[off]! << 16) | (buf[off + 1]! << 8) | buf[off + 2]!;
103
- }
104
-
105
- /** Length-prefixed vector with a 1-byte length. */
106
- export function vec8(body: Buffer): Buffer {
107
- return Buffer.concat([Buffer.from([body.length]), body]);
108
- }
109
-
110
- /** Length-prefixed vector with a 2-byte length. */
111
- export function vec16(body: Buffer): Buffer {
112
- const len = Buffer.alloc(2);
113
- len.writeUInt16BE(body.length, 0);
114
- return Buffer.concat([len, body]);
115
- }
116
-
117
- /** Length-prefixed vector with a 3-byte length. */
118
- export function vec24(body: Buffer): Buffer {
119
- return Buffer.concat([uint24(body.length), body]);
120
- }
121
-
122
- // ---- Record layer ---------------------------------------------------------
123
-
124
- /**
125
- * Encode a DTLS record (13-byte header + fragment).
126
- * @param type - CONTENT_TYPE
127
- * @param epoch
128
- * @param seq - 48-bit sequence number
129
- * @param fragment
130
- * @param version
131
- */
132
- export function encodeRecord(
133
- type: number,
134
- epoch: number,
135
- seq: number,
136
- fragment: Buffer,
137
- version: number = DTLS_1_2
138
- ): Buffer {
139
- const header = Buffer.alloc(13);
140
- header.writeUInt8(type, 0);
141
- header.writeUInt16BE(version, 1);
142
- header.writeUInt16BE(epoch, 3);
143
- header.writeUIntBE(seq, 5, 6);
144
- header.writeUInt16BE(fragment.length, 11);
145
- return Buffer.concat([header, fragment]);
146
- }
147
-
148
- /**
149
- * Parse one or more DTLS records from a datagram. Multiple records may be
150
- * packed into a single UDP packet.
151
- * @param packet
152
- */
153
- export function parseRecords(packet: Buffer): Record[] {
154
- const records: Record[] = [];
155
- let off = 0;
156
- while (off + 13 <= packet.length) {
157
- const type = packet.readUInt8(off);
158
- const version = packet.readUInt16BE(off + 1);
159
- const epoch = packet.readUInt16BE(off + 3);
160
- const seq = packet.readUIntBE(off + 5, 6);
161
- const length = packet.readUInt16BE(off + 11);
162
- const start = off + 13;
163
- if (start + length > packet.length) break;
164
- records.push({ type, version, epoch, seq, fragment: packet.slice(start, start + length) });
165
- off = start + length;
166
- }
167
- return records;
168
- }
169
-
170
- // ---- Handshake layer -------------------------------------------------------
171
-
172
- /**
173
- * Encode a DTLS handshake message header + body (unfragmented).
174
- * @param msgType - HANDSHAKE_TYPE
175
- * @param messageSeq
176
- * @param body
177
- */
178
- export function encodeHandshake(
179
- msgType: number,
180
- messageSeq: number,
181
- body: Buffer
182
- ): Buffer {
183
- const header = Buffer.alloc(12);
184
- header.writeUInt8(msgType, 0);
185
- uint24(body.length).copy(header, 1); // length
186
- header.writeUInt16BE(messageSeq, 4); // message_seq
187
- uint24(0).copy(header, 6); // fragment_offset
188
- uint24(body.length).copy(header, 9); // fragment_length
189
- return Buffer.concat([header, body]);
190
- }
191
-
192
- /**
193
- * Parse a handshake message header.
194
- * @param buf - starts at the handshake header
195
- */
196
- export function parseHandshake(buf: Buffer): Handshake {
197
- const msgType = buf.readUInt8(0);
198
- const length = readUint24(buf, 1);
199
- const messageSeq = buf.readUInt16BE(4);
200
- const fragmentOffset = readUint24(buf, 6);
201
- const fragmentLength = readUint24(buf, 9);
202
- const body = buf.slice(12, 12 + fragmentLength);
203
- return { msgType, length, messageSeq, fragmentOffset, fragmentLength, body };
204
- }
@@ -1,237 +0,0 @@
1
- /**
2
- * @file ByteBufferQueue - Efficient byte buffer with O(1) append and O(n) read.
3
- *
4
- * This class provides efficient management of byte buffers with O(1) append operations
5
- * and O(n) read operations. Clients can append entire buffers then copy data out across
6
- * buffer boundaries.
7
- *
8
- * @license MIT
9
- * @author nmhung1210
10
- */
11
-
12
- 'use strict';
13
-
14
- /**
15
- * A ByteBufferQueue manages a queue of byte buffers with efficient operations.
16
- *
17
- * Invariants maintained:
18
- * - size_ = sum of all buffer sizes - frontBufferOffset_
19
- * - No buffer in the queue is empty
20
- * - If queue is empty, frontBufferOffset_ = 0
21
- * - Otherwise, frontBufferOffset_ < front buffer size
22
- */
23
- class ByteBufferQueue {
24
- /**
25
- * Total number of bytes available to read.
26
- * @private {number}
27
- */
28
- #size: number;
29
-
30
- /**
31
- * Double-ended queue of byte buffers.
32
- * Append() pushes to the back, ReadInto() consumes from the front.
33
- * @private {Buffer[]}
34
- */
35
- #buffers: Buffer[];
36
-
37
- /**
38
- * Offset from which to start reading the front buffer.
39
- * @private {number}
40
- */
41
- #frontBufferOffset: number;
42
-
43
- constructor() {
44
- this.#size = 0;
45
- this.#buffers = [];
46
- this.#frontBufferOffset = 0;
47
- }
48
-
49
- /**
50
- * Number of bytes that can be read.
51
- * @returns {number}
52
- */
53
- get size(): number {
54
- return this.#size;
55
- }
56
-
57
- /**
58
- * Returns true if no bytes are available to read.
59
- * @returns {boolean}
60
- */
61
- get empty(): boolean {
62
- return this.#size === 0;
63
- }
64
-
65
- /**
66
- * Copies data into the given buffer. Consumes bytes from the queue.
67
- * Returns the number of bytes written to bufferOut.
68
- *
69
- * @param {Buffer} bufferOut - Destination buffer to read into
70
- * @returns {number} Number of bytes actually read
71
- * @throws {TypeError} If bufferOut is not a Buffer
72
- */
73
- readInto(bufferOut: Buffer): number {
74
- if (!Buffer.isBuffer(bufferOut)) {
75
- throw new TypeError('bufferOut must be a Buffer');
76
- }
77
-
78
- let readAmount = 0;
79
- let outputOffset = 0;
80
-
81
- while (outputOffset < bufferOut.length && this.#buffers.length > 0) {
82
- const frontBuffer = this.#buffers[0]!;
83
- const availableInFront = frontBuffer.length - this.#frontBufferOffset;
84
- const remainingOutput = bufferOut.length - outputOffset;
85
- const toCopy = Math.min(availableInFront, remainingOutput);
86
-
87
- // Copy data from front buffer to output
88
- frontBuffer.copy(
89
- bufferOut,
90
- outputOffset,
91
- this.#frontBufferOffset,
92
- this.#frontBufferOffset + toCopy
93
- );
94
-
95
- readAmount += toCopy;
96
- outputOffset += toCopy;
97
-
98
- if (toCopy < availableInFront) {
99
- // Partial read, update offset
100
- this.#frontBufferOffset += toCopy;
101
- } else {
102
- // Consumed entire front buffer, remove it
103
- this.#buffers.shift();
104
- this.#frontBufferOffset = 0;
105
- }
106
- }
107
-
108
- this.#size -= readAmount;
109
- this.#checkInvariants();
110
- return readAmount;
111
- }
112
-
113
- /**
114
- * Appends a buffer to the queue. Takes ownership of the buffer.
115
- * Empty buffers are ignored.
116
- *
117
- * @param {Buffer} buffer - Buffer to append
118
- * @throws {TypeError} If buffer is not a Buffer
119
- */
120
- append(buffer: Buffer): void {
121
- if (!Buffer.isBuffer(buffer)) {
122
- throw new TypeError('buffer must be a Buffer');
123
- }
124
-
125
- if (buffer.length === 0) {
126
- return; // Ignore empty buffers
127
- }
128
-
129
- this.#size += buffer.length;
130
- this.#buffers.push(buffer);
131
- this.#checkInvariants();
132
- }
133
-
134
- /**
135
- * Clears all stored buffers.
136
- */
137
- clear(): void {
138
- this.#buffers = [];
139
- this.#frontBufferOffset = 0;
140
- this.#size = 0;
141
- this.#checkInvariants();
142
- }
143
-
144
- /**
145
- * Reads and consumes exactly n bytes.
146
- *
147
- * @param {number} n - Number of bytes to read
148
- * @returns {Buffer} Buffer containing exactly n bytes
149
- * @throws {RangeError} If fewer than n bytes are available
150
- */
151
- read(n: number): Buffer {
152
- if (n > this.#size) {
153
- throw new RangeError(`Cannot read ${n} bytes, only ${this.#size} available`);
154
- }
155
- if (n === 0) {
156
- return Buffer.allocUnsafe(0);
157
- }
158
-
159
- const result = Buffer.allocUnsafe(n);
160
- const bytesRead = this.readInto(result);
161
-
162
- if (bytesRead !== n) {
163
- throw new Error(`Internal error: read ${bytesRead} bytes, expected ${n}`);
164
- }
165
-
166
- return result;
167
- }
168
-
169
- /**
170
- * Peeks at data without consuming it.
171
- *
172
- * @param {number} [n=this.#size] - Number of bytes to peek
173
- * @returns {Buffer} Buffer containing up to n bytes (not consumed)
174
- */
175
- peek(n: number = this.#size): Buffer {
176
- const peekAmount = Math.min(n, this.#size);
177
- if (peekAmount === 0) {
178
- return Buffer.allocUnsafe(0);
179
- }
180
-
181
- const result = Buffer.allocUnsafe(peekAmount);
182
- let written = 0;
183
- let bufferIndex = 0;
184
- let offset = this.#frontBufferOffset;
185
-
186
- while (written < peekAmount && bufferIndex < this.#buffers.length) {
187
- const buffer = this.#buffers[bufferIndex]!;
188
- const available = buffer.length - offset;
189
- const toCopy = Math.min(available, peekAmount - written);
190
-
191
- buffer.copy(result, written, offset, offset + toCopy);
192
- written += toCopy;
193
-
194
- bufferIndex++;
195
- offset = 0; // Reset offset for subsequent buffers
196
- }
197
-
198
- return result;
199
- }
200
-
201
- /**
202
- * Checks internal invariants (development mode only).
203
- * @private
204
- * @throws {Error} If invariants are violated
205
- */
206
- #checkInvariants(): void {
207
- if (process.env.NODE_ENV !== 'production') {
208
- let bufferSizeSum = 0;
209
- for (const buffer of this.#buffers) {
210
- if (buffer.length === 0) {
211
- throw new Error('Invariant violation: empty buffer in queue');
212
- }
213
- bufferSizeSum += buffer.length;
214
- }
215
-
216
- const expectedSize = bufferSizeSum - this.#frontBufferOffset;
217
- if (this.#size !== expectedSize) {
218
- throw new Error(
219
- `Invariant violation: size=${this.#size}, expected=${expectedSize}`
220
- );
221
- }
222
-
223
- if (this.#buffers.length === 0) {
224
- if (this.#frontBufferOffset !== 0) {
225
- throw new Error('Invariant violation: offset non-zero with empty queue');
226
- }
227
- } else {
228
- if (this.#frontBufferOffset >= this.#buffers[0]!.length) {
229
- throw new Error('Invariant violation: offset >= front buffer size');
230
- }
231
- }
232
- }
233
- }
234
- }
235
-
236
- export default ByteBufferQueue;
237
- export { ByteBufferQueue };