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
@@ -1,388 +0,0 @@
1
- /**
2
- * @file RTCDataChannel.ts
3
- * @description WebRTC DataChannel implementation for peer-to-peer data transfer.
4
- * @module datachannel/RTCDataChannel
5
- *
6
- * Implements the W3C RTCDataChannel interface
7
- * (https://www.w3.org/TR/webrtc/#rtcdatachannel).
8
- */
9
-
10
- import { EventEmitter } from 'events';
11
-
12
- /**
13
- * RTCDataChannelState - Current state of the data channel
14
- * @readonly
15
- * @enum {string}
16
- */
17
- export const RTCDataChannelState = Object.freeze({
18
- CONNECTING: 'connecting',
19
- OPEN: 'open',
20
- CLOSING: 'closing',
21
- CLOSED: 'closed'
22
- });
23
-
24
- type RTCDataChannelReadyState = 'connecting' | 'open' | 'closing' | 'closed';
25
- type RTCDataChannelBinaryType = 'arraybuffer' | 'blob';
26
-
27
- /**
28
- * Package-internal events that wire an RTCDataChannel to the SCTP transport.
29
- * They are keyed by Symbol so they never collide with — or leak into — the
30
- * public event surface ('open'/'message'/'close'/'error'/'bufferedamountlow').
31
- * The SCTP data-channel manager and the channel communicate purely by emitting
32
- * these on the channel's own EventEmitter:
33
- *
34
- * - SEND channel → transport: outbound frame `(data: Buffer, isBinary: boolean)`
35
- * - RECEIVE transport → channel: inbound frame `(data: Buffer, isBinary: boolean)`
36
- * - OPEN transport → channel: transition the channel to 'open'
37
- * - SET_ID transport → channel: assign the SCTP stream id `(id: number)`
38
- */
39
- export const RTCDataChannelEvents = Object.freeze({
40
- SEND: Symbol('rtcdatachannel:send'),
41
- RECEIVE: Symbol('rtcdatachannel:receive'),
42
- OPEN: Symbol('rtcdatachannel:open'),
43
- SET_ID: Symbol('rtcdatachannel:setId'),
44
- });
45
-
46
- /**
47
- * RTCDataChannelInit - Configuration for creating a data channel
48
- * @typedef {Object} RTCDataChannelInit
49
- * @property {boolean} [ordered=true] - Whether messages must arrive in order
50
- * @property {number} [maxPacketLifeTime] - Maximum packet lifetime in milliseconds
51
- * @property {number} [maxRetransmits] - Maximum number of retransmissions
52
- * @property {string} [protocol=''] - Subprotocol name
53
- * @property {boolean} [negotiated=false] - Whether channel was negotiated out-of-band
54
- * @property {number} [id] - Channel ID (required if negotiated is true)
55
- */
56
- export interface RTCDataChannelInit {
57
- ordered?: boolean;
58
- maxPacketLifeTime?: number;
59
- maxRetransmits?: number;
60
- protocol?: string;
61
- negotiated?: boolean;
62
- id?: number;
63
- }
64
-
65
- /**
66
- * @class RTCDataChannel
67
- * @extends EventEmitter
68
- * @description Represents a bidirectional data channel between peers.
69
- * Provides reliable or unreliable data transfer with configurable ordering.
70
- *
71
- * Events:
72
- * - 'open': Fired when the channel opens
73
- * - 'message': Fired when a message is received
74
- * - 'bufferedamountlow': Fired when bufferedAmount drops below threshold
75
- * - 'error': Fired when an error occurs
76
- * - 'closing': Fired when the channel is closing
77
- * - 'close': Fired when the channel closes
78
- *
79
- * @example
80
- * const dataChannel = peerConnection.createDataChannel('myChannel', {
81
- * ordered: true,
82
- * maxRetransmits: 3
83
- * });
84
- *
85
- * dataChannel.on('open', () => {
86
- * console.log('Channel opened');
87
- * dataChannel.send('Hello!');
88
- * });
89
- *
90
- * dataChannel.on('message', (event) => {
91
- * console.log('Received:', event.data);
92
- * });
93
- */
94
- export class RTCDataChannel extends EventEmitter {
95
- #label: string;
96
- #ordered: boolean;
97
- #maxPacketLifeTime: number | null;
98
- #maxRetransmits: number | null;
99
- #protocol: string;
100
- #negotiated: boolean;
101
- #id: number | null;
102
- #readyState: RTCDataChannelReadyState;
103
- #bufferedAmount: number;
104
- #bufferedAmountLowThreshold: number;
105
- #binaryType: RTCDataChannelBinaryType;
106
- /** Whether a transport is listening for outbound SEND events. */
107
- #connected: boolean;
108
-
109
- /**
110
- * Create an RTCDataChannel instance.
111
- * @param {string} label - Channel label
112
- * @param {RTCDataChannelInit} [init] - Channel configuration
113
- */
114
- constructor(label: string, init: RTCDataChannelInit = {}) {
115
- super();
116
-
117
- if (typeof label !== 'string') {
118
- throw new TypeError('label must be a string');
119
- }
120
-
121
- // Channel configuration
122
- this.#label = label;
123
- this.#ordered = init.ordered !== undefined ? init.ordered : true;
124
- this.#maxPacketLifeTime = init.maxPacketLifeTime || null;
125
- this.#maxRetransmits = init.maxRetransmits || null;
126
- this.#protocol = init.protocol || '';
127
- this.#negotiated = init.negotiated || false;
128
- this.#id = init.id !== undefined ? init.id : null;
129
-
130
- // State
131
- this.#readyState = RTCDataChannelState.CONNECTING as RTCDataChannelReadyState;
132
- this.#bufferedAmount = 0;
133
- this.#bufferedAmountLowThreshold = 0;
134
- this.#binaryType = 'arraybuffer'; // or 'blob'
135
- this.#connected = false;
136
-
137
- // Transport drives the channel via internal (Symbol-keyed) events.
138
- this.on(RTCDataChannelEvents.SET_ID, (id: number) => { this.#id = id; });
139
- this.on(RTCDataChannelEvents.OPEN, () => {
140
- this.#connected = true;
141
- this.#setState(RTCDataChannelState.OPEN as RTCDataChannelReadyState);
142
- });
143
- this.on(RTCDataChannelEvents.RECEIVE, (data: Buffer, isBinary: boolean) => {
144
- this.#receiveMessage(data, isBinary);
145
- });
146
- }
147
-
148
- /**
149
- * Get the channel label.
150
- * @returns {string} Channel label
151
- */
152
- get label(): string {
153
- return this.#label;
154
- }
155
-
156
- /**
157
- * Check if messages are delivered in order.
158
- * @returns {boolean} True if ordered
159
- */
160
- get ordered(): boolean {
161
- return this.#ordered;
162
- }
163
-
164
- /**
165
- * Get the maximum packet lifetime in milliseconds.
166
- * @returns {number|null} Maximum lifetime or null if not set
167
- */
168
- get maxPacketLifeTime(): number | null {
169
- return this.#maxPacketLifeTime;
170
- }
171
-
172
- /**
173
- * Get the maximum number of retransmissions.
174
- * @returns {number|null} Maximum retransmits or null if not set
175
- */
176
- get maxRetransmits(): number | null {
177
- return this.#maxRetransmits;
178
- }
179
-
180
- /**
181
- * Get the subprotocol name.
182
- * @returns {string} Protocol name
183
- */
184
- get protocol(): string {
185
- return this.#protocol;
186
- }
187
-
188
- /**
189
- * Check if the channel was negotiated out-of-band.
190
- * @returns {boolean} True if negotiated
191
- */
192
- get negotiated(): boolean {
193
- return this.#negotiated;
194
- }
195
-
196
- /**
197
- * Get the channel ID.
198
- * @returns {number|null} Channel ID or null if not assigned
199
- */
200
- get id(): number | null {
201
- return this.#id;
202
- }
203
-
204
- /**
205
- * Get the current state of the channel.
206
- * @returns {string} Channel state
207
- */
208
- get readyState(): RTCDataChannelReadyState {
209
- return this.#readyState;
210
- }
211
-
212
- /**
213
- * Get the number of bytes queued to send.
214
- * @returns {number} Buffered amount in bytes
215
- */
216
- get bufferedAmount(): number {
217
- return this.#bufferedAmount;
218
- }
219
-
220
- /**
221
- * Get the threshold for bufferedamountlow event.
222
- * @returns {number} Threshold in bytes
223
- */
224
- get bufferedAmountLowThreshold(): number {
225
- return this.#bufferedAmountLowThreshold;
226
- }
227
-
228
- /**
229
- * Set the threshold for bufferedamountlow event.
230
- * @param {number} value - Threshold in bytes
231
- */
232
- set bufferedAmountLowThreshold(value: number) {
233
- this.#bufferedAmountLowThreshold = value;
234
- }
235
-
236
- /**
237
- * Get the binary data type.
238
- * @returns {string} 'arraybuffer' or 'blob'
239
- */
240
- get binaryType(): RTCDataChannelBinaryType {
241
- return this.#binaryType;
242
- }
243
-
244
- /**
245
- * Set the binary data type.
246
- * @param {string} value - 'arraybuffer' or 'blob'
247
- * @throws {TypeError} If value is invalid
248
- */
249
- set binaryType(value: RTCDataChannelBinaryType) {
250
- if (value !== 'arraybuffer' && value !== 'blob') {
251
- throw new TypeError('binaryType must be "arraybuffer" or "blob"');
252
- }
253
- this.#binaryType = value;
254
- }
255
-
256
- /**
257
- * Check if the channel is reliable (deprecated).
258
- * @returns {boolean} True if ordered and no packet lifetime/retransmit limits
259
- * @deprecated Use ordered, maxPacketLifeTime, and maxRetransmits instead
260
- */
261
- get reliable(): boolean {
262
- return this.#ordered &&
263
- this.#maxPacketLifeTime === null &&
264
- this.#maxRetransmits === null;
265
- }
266
-
267
- /**
268
- * Send a message through the channel.
269
- * @param {string|ArrayBuffer|ArrayBufferView|Blob} data - Data to send
270
- * @throws {Error} If channel is not open or data is invalid
271
- */
272
- send(data: string | ArrayBuffer | ArrayBufferView | Buffer): void {
273
- if (this.#readyState !== RTCDataChannelState.OPEN) {
274
- throw new Error('RTCDataChannel.readyState is not "open"');
275
- }
276
-
277
- let dataToSend: Buffer;
278
- let byteLength = 0;
279
- let isBinary: boolean;
280
-
281
- if (typeof data === 'string') {
282
- dataToSend = Buffer.from(data, 'utf8');
283
- byteLength = dataToSend.length;
284
- isBinary = false;
285
- } else if (data instanceof ArrayBuffer) {
286
- dataToSend = Buffer.from(data);
287
- byteLength = data.byteLength;
288
- isBinary = true;
289
- } else if (ArrayBuffer.isView(data)) {
290
- dataToSend = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
291
- byteLength = data.byteLength;
292
- isBinary = true;
293
- } else if (Buffer.isBuffer(data)) {
294
- dataToSend = data as Buffer;
295
- byteLength = (data as Buffer).length;
296
- isBinary = true;
297
- } else if (data && typeof (data as { arrayBuffer?: unknown }).arrayBuffer === 'function') {
298
- // Blob-like object
299
- throw new Error('Blob sending not yet implemented');
300
- } else {
301
- throw new TypeError('Invalid data type');
302
- }
303
-
304
- // Emit the outbound frame for the transport to carry. The isBinary flag
305
- // lets the peer reconstruct the right JS type; binary is transmitted as raw
306
- // bytes (no JSON), avoiding corruption of Buffer/ArrayBuffer payloads.
307
- if (!this.#connected) {
308
- throw new Error('Data channel not connected to a transport');
309
- }
310
-
311
- // Update buffered amount, then decrement once the transport has taken it.
312
- this.#bufferedAmount += byteLength;
313
- try {
314
- this.emit(RTCDataChannelEvents.SEND, dataToSend, isBinary);
315
- this.#bufferedAmount = Math.max(0, this.#bufferedAmount - byteLength);
316
- this.#emitBufferedAmountLow();
317
- } catch (err) {
318
- this.#bufferedAmount = Math.max(0, this.#bufferedAmount - byteLength);
319
- this.emit('error', err);
320
- throw err;
321
- }
322
- }
323
-
324
- /** Emit bufferedamountlow if appropriate. */
325
- #emitBufferedAmountLow(): void {
326
- if (this.#bufferedAmount <= this.#bufferedAmountLowThreshold) {
327
- this.emit('bufferedamountlow');
328
- }
329
- }
330
-
331
- /**
332
- * Close the data channel.
333
- */
334
- close(): void {
335
- if (this.#readyState === RTCDataChannelState.CLOSING ||
336
- this.#readyState === RTCDataChannelState.CLOSED) {
337
- return;
338
- }
339
-
340
- this.#setState(RTCDataChannelState.CLOSING as RTCDataChannelReadyState);
341
-
342
- // Transition to closed asynchronously
343
- setImmediate(() => {
344
- if (this.#readyState === RTCDataChannelState.CLOSING) {
345
- this.#setState(RTCDataChannelState.CLOSED as RTCDataChannelReadyState);
346
- }
347
- });
348
- }
349
-
350
- /** Set the channel state and emit the matching lifecycle event. */
351
- #setState(newState: RTCDataChannelReadyState): void {
352
- const oldState = this.#readyState;
353
- if (oldState === newState) {
354
- return;
355
- }
356
-
357
- this.#readyState = newState;
358
-
359
- // Emit state-specific events
360
- if (newState === RTCDataChannelState.OPEN) {
361
- this.emit('open');
362
- } else if (newState === RTCDataChannelState.CLOSING) {
363
- this.emit('closing');
364
- } else if (newState === RTCDataChannelState.CLOSED) {
365
- this.emit('close');
366
- }
367
- }
368
-
369
- /**
370
- * Deliver a received message to listeners.
371
- *
372
- * Mirrors the browser RTCDataChannel: text frames surface as a string;
373
- * binary frames surface as an ArrayBuffer (binaryType 'arraybuffer') or a
374
- * Node Buffer (binaryType 'blob', which we approximate with Buffer since
375
- * Node has no Blob in older runtimes).
376
- */
377
- #receiveMessage(data: Buffer, isBinary: boolean): void {
378
- let payload: string | ArrayBuffer | Buffer;
379
- if (!isBinary) {
380
- payload = data.toString('utf8');
381
- } else if (this.#binaryType === 'arraybuffer') {
382
- payload = (data.buffer as ArrayBuffer).slice(data.byteOffset, data.byteOffset + data.byteLength);
383
- } else {
384
- payload = data;
385
- }
386
- this.emit('message', { data: payload });
387
- }
388
- }