node-rtc-connection 1.0.19 → 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.
- package/README.md +94 -85
- package/index.cjs +1 -0
- package/index.mjs +1 -0
- package/package.json +14 -46
- package/types/crypto/der.d.ts +107 -0
- package/types/crypto/x509.d.ts +56 -0
- package/types/datachannel/RTCDataChannel.d.ts +179 -0
- package/types/dtls/RTCCertificate.d.ts +163 -0
- package/types/dtls/cipher.d.ts +81 -0
- package/types/dtls/connection.d.ts +81 -0
- package/types/dtls/prf.d.ts +29 -0
- package/types/dtls/protocol.d.ts +127 -0
- package/types/foundation/ByteBufferQueue.d.ts +71 -0
- package/types/foundation/RTCError.d.ts +152 -0
- package/types/ice/RTCIceCandidate.d.ts +161 -0
- package/types/ice/ice-agent.d.ts +154 -0
- package/types/ice/stun-message.d.ts +92 -0
- package/types/index.d.ts +29 -0
- package/types/peerconnection/RTCPeerConnection.d.ts +74 -0
- package/types/sctp/association.d.ts +77 -0
- package/types/sctp/chunks.d.ts +200 -0
- package/types/sctp/crc32c.d.ts +24 -0
- package/types/sctp/datachannel-manager.d.ts +51 -0
- package/types/sctp/dcep.d.ts +56 -0
- package/types/sdp/RTCSessionDescription.d.ts +73 -0
- package/types/sdp/sdp-utils.d.ts +103 -0
- package/types/stun/stun-client.d.ts +119 -0
- package/types/transport-stack.d.ts +68 -0
- package/dist/index.cjs +0 -5618
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs +0 -5616
- package/dist/index.mjs.map +0 -1
- package/src/datachannel/RTCDataChannel.js +0 -354
- package/src/dtls/RTCCertificate.js +0 -310
- package/src/dtls/RTCDtlsTransport.js +0 -247
- package/src/foundation/ByteBufferQueue.js +0 -235
- package/src/foundation/RTCError.js +0 -226
- package/src/ice/RTCIceCandidate.js +0 -301
- package/src/ice/RTCIceTransport.js +0 -1018
- package/src/index.d.ts +0 -400
- package/src/index.js +0 -92
- package/src/network/network-transport.js +0 -478
- package/src/peerconnection/RTCPeerConnection.js +0 -875
- package/src/sctp/RTCSctpTransport.js +0 -253
- package/src/sdp/RTCSessionDescription.js +0 -102
- package/src/sdp/sdp-utils.js +0 -224
- package/src/stun/stun-client.js +0 -777
package/README.md
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# node-rtc-connection
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/node-rtc-connection)
|
|
4
|
+
[](https://www.npmjs.com/package/node-rtc-connection)
|
|
5
|
+
[](https://github.com/nmhung1210/node-rtc-connection/actions/workflows/test.yml)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
|
|
10
|
+
A from-scratch, pure-Node.js WebRTC data-channel implementation that
|
|
11
|
+
**interoperates with browsers**. No native dependencies — the entire ICE / DTLS
|
|
12
|
+
/ SCTP stack is built on Node's `crypto` and `dgram`. Written in TypeScript;
|
|
13
|
+
ships type declarations.
|
|
4
14
|
|
|
5
15
|
## Features
|
|
6
16
|
|
|
7
|
-
- ✅ **
|
|
8
|
-
- ✅ **
|
|
9
|
-
- ✅ **
|
|
10
|
-
- ✅ **TURN
|
|
11
|
-
- ✅ **
|
|
12
|
-
- ✅ **
|
|
13
|
-
- ✅ **
|
|
17
|
+
- ✅ **Browser interoperable**: Verified end-to-end against Chromium (Playwright) and OpenSSL
|
|
18
|
+
- ✅ **Real protocols, not stubs**: Genuine DTLS 1.2 handshake + SCTP association over UDP
|
|
19
|
+
- ✅ **ICE** (RFC 8445): connectivity checks with MESSAGE-INTEGRITY, host/srflx/relay candidates
|
|
20
|
+
- ✅ **STUN/TURN** (RFC 5389/5766): NAT traversal and relay for restrictive networks
|
|
21
|
+
- ✅ **DTLS 1.2** (RFC 6347): `ECDHE_ECDSA_AES128_GCM`, mutual auth, self-signed ECDSA certs
|
|
22
|
+
- ✅ **SCTP + DCEP** (RFC 8831/8832): ordered/unordered data channels, string + binary
|
|
23
|
+
- ✅ **W3C API**: familiar `RTCPeerConnection` / `RTCDataChannel` surface
|
|
24
|
+
- ✅ **Pure Node.js, no native deps**; CommonJS + ESM bundles with TypeScript types
|
|
14
25
|
|
|
15
26
|
## Installation
|
|
16
27
|
|
|
@@ -18,6 +29,16 @@ A Node.js WebRTC implementation with full ICE/STUN/TURN support for real peer-to
|
|
|
18
29
|
npm install node-rtc-connection
|
|
19
30
|
```
|
|
20
31
|
|
|
32
|
+
Works from both CommonJS and ES modules, and bundles TypeScript declarations:
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
// CommonJS
|
|
36
|
+
const { RTCPeerConnection } = require('node-rtc-connection');
|
|
37
|
+
|
|
38
|
+
// ES modules / TypeScript
|
|
39
|
+
import { RTCPeerConnection } from 'node-rtc-connection';
|
|
40
|
+
```
|
|
41
|
+
|
|
21
42
|
## Quick Start
|
|
22
43
|
|
|
23
44
|
### Basic Local Connection (No STUN/TURN)
|
|
@@ -170,51 +191,34 @@ const config = {
|
|
|
170
191
|
const pc = new RTCPeerConnection(config);
|
|
171
192
|
```
|
|
172
193
|
|
|
173
|
-
###
|
|
194
|
+
### ICE server URLs
|
|
174
195
|
|
|
175
|
-
|
|
196
|
+
ICE server URLs are parsed with query-string support:
|
|
176
197
|
|
|
177
198
|
```javascript
|
|
178
199
|
const config = {
|
|
179
200
|
iceServers: [
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
urls: 'turn:turn.example.com:3478?transport=udp',
|
|
183
|
-
username: 'user',
|
|
184
|
-
credential: 'pass'
|
|
185
|
-
},
|
|
186
|
-
|
|
187
|
-
// Multiple parameters
|
|
188
|
-
{
|
|
189
|
-
urls: 'turn:turn.example.com:3478?transport=tcp&ttl=86400',
|
|
190
|
-
username: 'user',
|
|
191
|
-
credential: 'pass'
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
// Multiple URLs with different transports
|
|
201
|
+
{ urls: 'stun:stun.l.google.com:19302' },
|
|
195
202
|
{
|
|
196
203
|
urls: [
|
|
197
|
-
'turn:turn.
|
|
198
|
-
'turn:turn.
|
|
199
|
-
'turns:turn.cloudflare.com:5349?transport=tcp'
|
|
204
|
+
'turn:turn.example.com:3478?transport=udp',
|
|
205
|
+
'turn:turn.example.com:53?transport=udp'
|
|
200
206
|
],
|
|
201
|
-
username: '
|
|
202
|
-
credential: '
|
|
207
|
+
username: 'user',
|
|
208
|
+
credential: 'pass'
|
|
203
209
|
}
|
|
204
210
|
]
|
|
205
211
|
};
|
|
206
212
|
```
|
|
207
213
|
|
|
208
|
-
**
|
|
209
|
-
|
|
210
|
-
- `ttl=<seconds>` - Set allocation lifetime for TURN (default: 600)
|
|
211
|
-
- Custom parameters - Can be added for vendor-specific features
|
|
214
|
+
**URL format:** `stun:host[:port]` and `turn:host[:port][?transport=udp&...]`.
|
|
215
|
+
The default port is `3478` (`5349` for the `turns:` scheme).
|
|
212
216
|
|
|
213
|
-
**
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
> **Transport support:** connectivity currently uses **UDP only**. STUN
|
|
218
|
+
> reflexive and TURN relay candidates are gathered over UDP; `transport=tcp`
|
|
219
|
+
> and the `turns:` (TLS) scheme are parsed but not yet used for the data path,
|
|
220
|
+
> so list a UDP TURN URL for the relay to work. Unknown query parameters are
|
|
221
|
+
> preserved and ignored.
|
|
218
222
|
|
|
219
223
|
## Data Channel API
|
|
220
224
|
|
|
@@ -375,51 +379,29 @@ createPeerConnection().catch(console.error);
|
|
|
375
379
|
|
|
376
380
|
## Example Files
|
|
377
381
|
|
|
378
|
-
The package includes
|
|
382
|
+
The package includes runnable examples in `examples/`:
|
|
379
383
|
|
|
380
|
-
- **`examples/
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
- **`examples/
|
|
384
|
-
|
|
384
|
+
- **`examples/node-to-node.ts`** — Two node-rtc-connection peers in one process
|
|
385
|
+
establish a real data channel and exchange string + binary messages. The
|
|
386
|
+
quickest way to see the full ICE/DTLS/SCTP stack work.
|
|
387
|
+
- **`examples/browser-server.ts`** + **`examples/browser-client.html`** — A
|
|
388
|
+
Node.js HTTP server that runs a node-rtc-connection peer (the offerer) and serves a chat
|
|
389
|
+
page. A browser opens the page, runs its native `RTCPeerConnection` as the
|
|
390
|
+
answerer, and the two establish a genuine WebRTC data channel over UDP.
|
|
385
391
|
|
|
386
|
-
Run examples:
|
|
392
|
+
Run them (the examples are TypeScript, run via `tsx`):
|
|
387
393
|
```bash
|
|
388
|
-
|
|
389
|
-
node
|
|
390
|
-
node examples/turn-demo.js
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
## Configuration File
|
|
394
|
+
# Node ↔ Node
|
|
395
|
+
npm run example:node
|
|
394
396
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
```json
|
|
398
|
-
{
|
|
399
|
-
"iceServers": [
|
|
400
|
-
{ "urls": "stun:stun.l.google.com:19302" }
|
|
401
|
-
],
|
|
402
|
-
"localDemo": {
|
|
403
|
-
"iceServers": []
|
|
404
|
-
},
|
|
405
|
-
"stunOnly": {
|
|
406
|
-
"iceServers": [
|
|
407
|
-
{ "urls": "stun:stun.l.google.com:19302" }
|
|
408
|
-
]
|
|
409
|
-
},
|
|
410
|
-
"turnConfig": {
|
|
411
|
-
"iceServers": [
|
|
412
|
-
{ "urls": "stun:stun.example.com:3478" },
|
|
413
|
-
{
|
|
414
|
-
"urls": "turn:turn.example.com:3478",
|
|
415
|
-
"username": "user",
|
|
416
|
-
"credential": "pass"
|
|
417
|
-
}
|
|
418
|
-
]
|
|
419
|
-
}
|
|
420
|
-
}
|
|
397
|
+
# Node ↔ Browser — then open http://localhost:3000
|
|
398
|
+
npm run example:browser
|
|
421
399
|
```
|
|
422
400
|
|
|
401
|
+
> The browser example uses plain HTTP for signaling and folds ICE candidates
|
|
402
|
+
> into the SDP (non-trickle) to keep it simple. A production app would typically
|
|
403
|
+
> use WebSockets with trickle ICE.
|
|
404
|
+
|
|
423
405
|
## API Reference
|
|
424
406
|
|
|
425
407
|
### RTCPeerConnection
|
|
@@ -449,7 +431,7 @@ new RTCPeerConnection(configuration?)
|
|
|
449
431
|
### RTCDataChannel
|
|
450
432
|
|
|
451
433
|
#### Methods
|
|
452
|
-
- `send(data)` - Send
|
|
434
|
+
- `send(data)` - Send `string`, `ArrayBuffer`, a typed array / `ArrayBufferView`, or a Node `Buffer`
|
|
453
435
|
- `close()` - Close the channel
|
|
454
436
|
|
|
455
437
|
#### Properties
|
|
@@ -462,11 +444,12 @@ new RTCPeerConnection(configuration?)
|
|
|
462
444
|
- `id` - Channel ID
|
|
463
445
|
- `readyState` - Current state ('connecting', 'open', 'closing', 'closed')
|
|
464
446
|
- `bufferedAmount` - Bytes queued to send
|
|
447
|
+
- `binaryType` - `'arraybuffer'` (default) or `'blob'`; controls how received binary frames are delivered
|
|
465
448
|
|
|
466
449
|
## Requirements
|
|
467
450
|
|
|
468
|
-
- Node.js
|
|
469
|
-
- UDP
|
|
451
|
+
- Node.js 18 or higher
|
|
452
|
+
- UDP network access for ICE connectivity (and to a TURN server, if used)
|
|
470
453
|
|
|
471
454
|
## Setting Up Your Own TURN Server
|
|
472
455
|
|
|
@@ -480,14 +463,40 @@ apt-get install coturn
|
|
|
480
463
|
turnserver -v -L 0.0.0.0 -a -u user:password -r realm
|
|
481
464
|
```
|
|
482
465
|
|
|
466
|
+
## Development
|
|
467
|
+
|
|
468
|
+
The project is written in strict TypeScript. Sources live in `src/`; tests in
|
|
469
|
+
`test/` run directly through [`tsx`](https://github.com/privatenumber/tsx) (no
|
|
470
|
+
precompile step).
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
npm run build # rollup → minified dist/ bundles + dist/types/ declarations
|
|
474
|
+
npm run typecheck # strict tsc --noEmit over src + tests
|
|
475
|
+
npm test # full suite (auto-starts a coturn container for the TURN test)
|
|
476
|
+
npm run test:unit # SKIP_INTEGRATION=1 — no Docker / browser / external servers
|
|
477
|
+
npm run test:coverage # full suite under c8
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
The full test suite proves interoperability against external references:
|
|
481
|
+
DTLS handshakes against `openssl`, an end-to-end data channel against real
|
|
482
|
+
Chromium (via Playwright), and a relay path against a real `coturn` server.
|
|
483
|
+
Integration tests skip gracefully when their dependency (Docker, openssl,
|
|
484
|
+
Chromium) is unavailable or when `SKIP_INTEGRATION=1`.
|
|
485
|
+
|
|
483
486
|
## License
|
|
484
487
|
|
|
485
|
-
|
|
488
|
+
MIT
|
|
486
489
|
|
|
487
490
|
## Contributing
|
|
488
491
|
|
|
489
|
-
Contributions are welcome! Please
|
|
492
|
+
Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for
|
|
493
|
+
the development workflow and conventions, and our
|
|
494
|
+
[Code of Conduct](./CODE_OF_CONDUCT.md). Security issues should be reported
|
|
495
|
+
privately — see [SECURITY.md](./SECURITY.md). Release notes live in
|
|
496
|
+
[CHANGELOG.md](./CHANGELOG.md).
|
|
490
497
|
|
|
491
498
|
## Acknowledgments
|
|
492
499
|
|
|
493
|
-
This
|
|
500
|
+
This is a from-scratch, pure-Node.js implementation that follows the relevant
|
|
501
|
+
IETF RFCs (8445 ICE, 6347 DTLS 1.2, 8831 SCTP-over-DTLS, 8832 DCEP) and the W3C
|
|
502
|
+
WebRTC specification.
|
package/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("crypto"),t=require("events"),r=require("dgram"),s=require("os");function i(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(r){if("default"!==r){var s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:function(){return e[r]}})}}),t.default=e,Object.freeze(t)}var n=i(e),a=i(r),o=i(s);const c=Object.freeze({NONE:"none",DATA_CHANNEL_FAILURE:"data-channel-failure",DTLS_FAILURE:"dtls-failure",FINGERPRINT_FAILURE:"fingerprint-failure",SCTP_FAILURE:"sctp-failure",SDP_SYNTAX_ERROR:"sdp-syntax-error",HARDWARE_ENCODER_NOT_AVAILABLE:"hardware-encoder-not-available",HARDWARE_ENCODER_ERROR:"hardware-encoder-error",INVALID_STATE:"invalid-state",INVALID_MODIFICATION:"invalid-modification",INVALID_ACCESS_ERROR:"invalid-access-error",OPERATION_ERROR:"operation-error"});class h extends Error{static DetailType=c;#e;#t;#r;#s;#i;#n;constructor(e={},t=""){super(t),this.name="RTCError",Error.captureStackTrace&&Error.captureStackTrace(this,h);const r=e.errorDetail||c.NONE;if("string"!=typeof r)throw new TypeError("errorDetail must be a string");this.#e=r,this.#t=this.#a(e.sdpLineNumber,"sdpLineNumber"),this.#r=this.#a(e.httpRequestStatusCode,"httpRequestStatusCode"),this.#s=this.#a(e.sctpCauseCode,"sctpCauseCode"),this.#i=this.#o(e.receivedAlert,"receivedAlert"),this.#n=this.#o(e.sentAlert,"sentAlert")}#a(e,t){if(null==e)return null;const r=Number(e);if(!Number.isInteger(r))throw new TypeError(`${t} must be an integer`);return r}#o(e,t){if(null==e)return null;const r=Number(e);if(!Number.isInteger(r)||r<0)throw new TypeError(`${t} must be an unsigned integer`);return r}get errorDetail(){return this.#e}get sdpLineNumber(){return this.#t}get httpRequestStatusCode(){return this.#r}get sctpCauseCode(){return this.#s}get receivedAlert(){return this.#i}get sentAlert(){return this.#n}toJSON(){const e={name:this.name,message:this.message,errorDetail:this.#e};return null!==this.#t&&(e.sdpLineNumber=this.#t),null!==this.#r&&(e.httpRequestStatusCode=this.#r),null!==this.#s&&(e.sctpCauseCode=this.#s),null!==this.#i&&(e.receivedAlert=this.#i),null!==this.#n&&(e.sentAlert=this.#n),e}static fromNative(e){const t={errorDetail:e.error_detail||c.NONE};return void 0!==e.sctp_cause_code&&(t.sctpCauseCode=e.sctp_cause_code),new h(t,e.message||"Unknown error")}}class d{#c;#h;#d;#l;#u;constructor(e={}){if(null===e.sdpMid&&null===e.sdpMLineIndex)throw new TypeError("sdpMid and sdpMLineIndex are both null");this.#c=e.candidate||"",this.#h=void 0!==e.sdpMid?e.sdpMid:null,this.#d=void 0!==e.sdpMLineIndex?e.sdpMLineIndex:null,this.#l=e.usernameFragment||null,this.#u=this.#f(this.#c)}#f(e){const t={foundation:null,component:null,protocol:null,priority:null,address:null,port:null,type:null,tcpType:null,relatedAddress:null,relatedPort:null};if(!e||!e.startsWith("candidate:"))return t;const r=e.substring(10).trim().split(/\s+/);if(r.length<8)return t;t.foundation=r[0],t.component=r[1],t.protocol=r[2].toLowerCase(),t.priority=parseInt(r[3],10),t.address=r[4],t.port=parseInt(r[5],10),"typ"===r[6]&&(t.type=r[7]);for(let e=8;e<r.length;e+=2){const s=r[e],i=r[e+1];"raddr"===s?t.relatedAddress=i:"rport"===s?t.relatedPort=parseInt(i,10):"tcptype"===s&&(t.tcpType=i)}return t}get candidate(){return this.#c}get sdpMid(){return this.#h}get sdpMLineIndex(){return this.#d}get usernameFragment(){return this.#l}get foundation(){return this.#u.foundation}get component(){return this.#u.component}get priority(){return this.#u.priority}get address(){return this.#u.address}get protocol(){return this.#u.protocol}get port(){return this.#u.port}get type(){return this.#u.type}get tcpType(){return this.#u.tcpType}get relatedAddress(){return this.#u.relatedAddress}get relatedPort(){return this.#u.relatedPort}toJSON(){const e={candidate:this.#c,sdpMid:this.#h,sdpMLineIndex:this.#d};return this.#l&&(e.usernameFragment=this.#l),e}static fromString(e,t=null,r=0){return new d({candidate:e,sdpMid:t,sdpMLineIndex:r})}static isValid(e){return!(!e||"string"!=typeof e)&&(!!e.startsWith("candidate:")&&e.substring(10).trim().split(/\s+/).length>=8)}}const l=Object.freeze({BOOLEAN:1,INTEGER:2,BIT_STRING:3,OCTET_STRING:4,NULL:5,OID:6,UTF8_STRING:12,PRINTABLE_STRING:19,IA5_STRING:22,UTC_TIME:23,GENERALIZED_TIME:24,SEQUENCE:48,SET:49});function u(e){if(e<128)return Buffer.from([e]);const t=[];let r=e;for(;r>0;)t.unshift(255&r),r>>>=8;return Buffer.from([128|t.length,...t])}function f(e,t){return Buffer.concat([Buffer.from([e]),u(t.length),t])}function p(e){let t=0;for(;t<e.length-1&&0===e[t];)t++;let r=e.slice(t);return 128&r[0]&&(r=Buffer.concat([Buffer.from([0]),r])),f(l.INTEGER,r)}function E(e){const t=[];let r=e;for(;r>0;)t.unshift(255&r),r=Math.floor(r/256);return 128&t[0]&&t.unshift(0),f(l.INTEGER,Buffer.from(t))}function m(e){const t=e.split(".").map(Number);if(t.length<2)throw new Error(`Invalid OID: ${e}`);const r=[40*t[0]+t[1]];for(let e=2;e<t.length;e++){let s=t[e];const i=[127&s];for(s=Math.floor(s/128);s>0;)i.unshift(127&s|128),s=Math.floor(s/128);r.push(...i)}return f(l.OID,Buffer.from(r))}function g(e){return f(l.SEQUENCE,Buffer.concat(e))}function I(e){const t=e.getUTCFullYear(),r=(e,t=2)=>String(e).padStart(t,"0"),s=r(e.getUTCMonth()+1),i=r(e.getUTCDate()),n=r(e.getUTCHours()),a=r(e.getUTCMinutes()),o=r(e.getUTCSeconds());if(t<2050){const e=r(t%100);return f(l.UTC_TIME,Buffer.from(`${e}${s}${i}${n}${a}${o}Z`,"ascii"))}return f(l.GENERALIZED_TIME,Buffer.from(`${t}${s}${i}${n}${a}${o}Z`,"ascii"))}const C=Object.freeze({ecPublicKey:"1.2.840.10045.2.1",prime256v1:"1.2.840.10045.3.1.7",ecdsaWithSHA256:"1.2.840.10045.4.3.2",commonName:"2.5.4.3"});function T(){return g([m(C.ecdsaWithSHA256)])}function S(e,t="sha-256"){const r=t.replace("-","").toLowerCase();return n.createHash(r).update(e).digest("hex").toUpperCase().match(/.{2}/g).join(":")}function y(e={}){const{name:t,days:r=30}=e,{certDer:s,privateKey:i,publicKey:a,notAfter:o}=function(e={}){const t=e.commonName||`WebRTC-${n.randomBytes(8).toString("hex")}`,r=e.days||30,{publicKey:s,privateKey:i}=n.generateKeyPairSync("ec",{namedCurve:"prime256v1"}),a=s.export({type:"spki",format:"der"}),o=e.notBefore||new Date(Date.now()-864e5),c=new Date(o.getTime()+24*r*60*60*1e3),h=n.randomBytes(20);h[0]&=127,0===h[0]&&(h[0]=1);const d=function(e){const t=g([m(C.commonName),(r=e,f(l.UTF8_STRING,Buffer.from(r,"utf8")))]);var r,s;return g([(s=[t],f(l.SET,Buffer.concat(s)))])}(t),u=g([(S=E(2),f(160,S)),p(h),T(),d,g([I(o),I(c)]),d,a]);var S;const y=n.sign("sha256",u,i);var A;return{certDer:g([u,T(),(A=y,f(l.BIT_STRING,Buffer.concat([Buffer.from([0]),A])))]),privateKey:i,publicKey:s,notBefore:o,notAfter:c}}({commonName:t,days:r});return{certDer:s,privateKey:i,publicKey:a,expires:o.getTime(),hash:"sha256"}}function A(e,t="sha-256"){return S(e,t)}class R{#p;#E;#m;#g;#I;constructor(e){this.#p=e.certDer||null,this.#E=e.privateKey,this.#m=e.publicKey,this.#g=e.expires,this.#I=null}getCertificateDer(){return this.#p}get expires(){return this.#g}getFingerprints(){if(!this.#p)throw new Error("Certificate has no DER encoding; cannot compute fingerprint");if(!this.#I){const e=this.#p,t=["sha-256","sha-384","sha-512"];this.#I=t.map(t=>({algorithm:t,value:A(e,t)}))}return this.#I.map(e=>({...e}))}getPrivateKeyObject(){return this.#C(this.#E,"private")}#C(e,t){return e&&"object"==typeof e&&e.type?e:"private"===t?n.createPrivateKey(e):n.createPublicKey(e)}getPrivateKey(){return this.#C(this.#E,"private").export({type:"pkcs8",format:"pem"})}getPublicKey(){return this.#C(this.#m,"public").export({type:"spki",format:"pem"})}toPEM(){const e=this.#p?`-----BEGIN CERTIFICATE-----\n${this.#p.toString("base64").match(/.{1,64}/g).join("\n")}\n-----END CERTIFICATE-----\n`:this.getPublicKey();return{pemPrivateKey:this.getPrivateKey(),pemCertificate:e}}isExpired(){return Date.now()>this.#g}static async generateCertificate(e={}){return new Promise((t,r)=>{try{let s;if(e.expires)s=e.expires;else{const t=e.days||30;s=Date.now()+24*t*60*60*1e3}setImmediate(()=>{try{const r=y({name:e.name||"webrtc",days:Math.ceil((s-Date.now())/864e5),hash:e.hash||"sha256"});r.expires=s;const i=new R(r);t(i)}catch(e){r(e)}})}catch(e){r(e)}})}static fromPEM(e,t,r){if("string"!=typeof e||0===e.length)throw new TypeError("pemPrivateKey must be a non-empty string");if("string"!=typeof t||0===t.length)throw new TypeError("pemCertificate must be a non-empty string");const s=r||Date.now()+2592e6;let i=null,a=t;const o=t.match(/-----BEGIN CERTIFICATE-----([\s\S]+?)-----END CERTIFICATE-----/);return o&&(i=Buffer.from(o[1].replace(/\s/g,""),"base64"),a=n.createPublicKey(n.createPrivateKey(e))),new R({certDer:i,privateKey:e,publicKey:a,expires:s,hash:"sha256"})}static isSupportedKeyParams(e){if(!e||"object"!=typeof e)return!1;if("RSA"===e.type){const t=e.rsaModulusLength||2048;return t>=1024&&t<=4096}if("ECDSA"===e.type){const t=e.namedCurve;return["P-256","P-384","P-521"].includes(t)}return!1}}const B=Object.freeze({CONNECTING:"connecting",OPEN:"open",CLOSING:"closing",CLOSED:"closed"}),w=Object.freeze({SEND:Symbol("rtcdatachannel:send"),RECEIVE:Symbol("rtcdatachannel:receive"),OPEN:Symbol("rtcdatachannel:open"),SET_ID:Symbol("rtcdatachannel:setId")});class N extends t.EventEmitter{#T;#S;#y;#A;#R;#B;#w;#N;#b;#O;#D;#U;constructor(e,t={}){if(super(),"string"!=typeof e)throw new TypeError("label must be a string");this.#T=e,this.#S=void 0===t.ordered||t.ordered,this.#y=t.maxPacketLifeTime||null,this.#A=t.maxRetransmits||null,this.#R=t.protocol||"",this.#B=t.negotiated||!1,this.#w=void 0!==t.id?t.id:null,this.#N=B.CONNECTING,this.#b=0,this.#O=0,this.#D="arraybuffer",this.#U=!1,this.on(w.SET_ID,e=>{this.#w=e}),this.on(w.OPEN,()=>{this.#U=!0,this.#v(B.OPEN)}),this.on(w.RECEIVE,(e,t)=>{this.#k(e,t)})}get label(){return this.#T}get ordered(){return this.#S}get maxPacketLifeTime(){return this.#y}get maxRetransmits(){return this.#A}get protocol(){return this.#R}get negotiated(){return this.#B}get id(){return this.#w}get readyState(){return this.#N}get bufferedAmount(){return this.#b}get bufferedAmountLowThreshold(){return this.#O}set bufferedAmountLowThreshold(e){this.#O=e}get binaryType(){return this.#D}set binaryType(e){if("arraybuffer"!==e&&"blob"!==e)throw new TypeError('binaryType must be "arraybuffer" or "blob"');this.#D=e}get reliable(){return this.#S&&null===this.#y&&null===this.#A}send(e){if(this.#N!==B.OPEN)throw new Error('RTCDataChannel.readyState is not "open"');let t,r,s=0;if("string"==typeof e)t=Buffer.from(e,"utf8"),s=t.length,r=!1;else if(e instanceof ArrayBuffer)t=Buffer.from(e),s=e.byteLength,r=!0;else if(ArrayBuffer.isView(e))t=Buffer.from(e.buffer,e.byteOffset,e.byteLength),s=e.byteLength,r=!0;else{if(!Buffer.isBuffer(e))throw e&&"function"==typeof e.arrayBuffer?new Error("Blob sending not yet implemented"):new TypeError("Invalid data type");t=e,s=e.length,r=!0}if(!this.#U)throw new Error("Data channel not connected to a transport");this.#b+=s;try{this.emit(w.SEND,t,r),this.#b=Math.max(0,this.#b-s),this.#L()}catch(e){throw this.#b=Math.max(0,this.#b-s),this.emit("error",e),e}}#L(){this.#b<=this.#O&&this.emit("bufferedamountlow")}close(){this.#N!==B.CLOSING&&this.#N!==B.CLOSED&&(this.#v(B.CLOSING),setImmediate(()=>{this.#N===B.CLOSING&&this.#v(B.CLOSED)}))}#v(e){this.#N!==e&&(this.#N=e,e===B.OPEN?this.emit("open"):e===B.CLOSING?this.emit("closing"):e===B.CLOSED&&this.emit("close"))}#k(e,t){let r;r=t?"arraybuffer"===this.#D?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):e:e.toString("utf8"),this.emit("message",{data:r})}}const b=Object.freeze({OFFER:"offer",PRANSWER:"pranswer",ANSWER:"answer",ROLLBACK:"rollback"});class O{#P;#_;constructor(e={}){if(this.#P=e.type||null,this.#_=e.sdp||null,this.#P&&!Object.values(b).includes(this.#P))throw new TypeError(`Invalid SDP type: ${this.#P}`)}get type(){return this.#P}set type(e){if(e&&!Object.values(b).includes(e))throw new TypeError(`Invalid SDP type: ${e}`);this.#P=e}get sdp(){return this.#_}set sdp(e){this.#_=e}toJSON(){return{type:this.#P,sdp:this.#_}}}function D(e){const{iceUfrag:t,icePwd:r,fingerprint:s,setup:i="actpass",candidates:a=[],sctpPort:o=5e3,maxMessageSize:c=262144}=e,h=[];h.push("v=0");const d=n.randomBytes(4).readUInt32BE(0);h.push(`o=- ${d} 2 IN IP4 127.0.0.1`),h.push("s=-"),h.push("t=0 0"),h.push("a=group:BUNDLE 0"),h.push("a=msid-semantic: WMS"),h.push("m=application 9 UDP/DTLS/SCTP webrtc-datachannel"),h.push("c=IN IP4 0.0.0.0"),h.push("a=ice-ufrag:"+t),h.push("a=ice-pwd:"+r),h.push("a=ice-options:trickle"),s&&h.push(`a=fingerprint:${s.algorithm} ${s.value}`),h.push(`a=setup:${i}`),h.push("a=mid:0"),h.push("a=sctp-port:"+o),h.push("a=max-message-size:"+c);for(const e of a){const t=e.sdp||e.candidate;t&&h.push("a="+(t.startsWith("candidate:")?t:"candidate:"+t))}return h.join("\r\n")+"\r\n"}function U(e){const t=(e.startsWith("candidate:")?e.slice(10):e).split(/\s+/);return t.length<8?null:{candidate:e.startsWith("candidate:")?e:"candidate:"+e,foundation:t[0],component:parseInt(t[1],10),protocol:t[2].toLowerCase(),priority:parseInt(t[3],10)>>>0,address:t[4],port:parseInt(t[5],10),type:t[7]}}const v=554869826,k=Object.freeze({BINDING_REQUEST:1,BINDING_SUCCESS:257,BINDING_ERROR:273}),L=Object.freeze({MAPPED_ADDRESS:1,USERNAME:6,MESSAGE_INTEGRITY:8,ERROR_CODE:9,XOR_MAPPED_ADDRESS:32,PRIORITY:36,USE_CANDIDATE:37,FINGERPRINT:32808,ICE_CONTROLLED:32809,ICE_CONTROLLING:32810});function P(e){return e+3&-4}const _=(()=>{const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)r=1&r?3988292384^r>>>1:r>>>1;e[t]=r>>>0}return e})();class x{type;transactionId;attrs;constructor(e,t){this.type=e,this.transactionId=t||n.randomBytes(12),this.attrs=[]}addAttr(e,t){return this.attrs.push({type:e,value:t}),this}addUsername(e){return this.addAttr(L.USERNAME,Buffer.from(e,"utf8"))}addPriority(e){const t=Buffer.alloc(4);return t.writeUInt32BE(e>>>0,0),this.addAttr(L.PRIORITY,t)}addIceControlling(e){return this.addAttr(L.ICE_CONTROLLING,e)}addIceControlled(e){return this.addAttr(L.ICE_CONTROLLED,e)}addUseCandidate(){return this.addAttr(L.USE_CANDIDATE,Buffer.alloc(0))}addXorMappedAddress(e,t){return this.addAttr(L.XOR_MAPPED_ADDRESS,function(e,t){const r=Buffer.alloc(8);r.writeUInt8(0,0),r.writeUInt8(1,1),r.writeUInt16BE(8466^t,2);const s=e.split(".").map(Number),i=(s[0]<<24|s[1]<<16|s[2]<<8|s[3])>>>0;return r.writeUInt32BE((i^v)>>>0,4),r}(e,t,this.transactionId))}#x(){const e=[];for(const t of this.attrs){const r=Buffer.alloc(4);r.writeUInt16BE(t.type,0),r.writeUInt16BE(t.value.length,2);const s=Buffer.alloc(P(t.value.length));t.value.copy(s,0),e.push(r,s)}return Buffer.concat(e)}#H(e){const t=Buffer.alloc(20);return t.writeUInt16BE(this.type,0),t.writeUInt16BE(e,2),t.writeUInt32BE(v,4),this.transactionId.copy(t,8),t}build(e){let t=this.#x();if(e){const r=t.length+24,s=this.#H(r),i=n.createHmac("sha1",Buffer.from(e,"utf8")).update(Buffer.concat([s,t])).digest(),a=Buffer.alloc(4);a.writeUInt16BE(L.MESSAGE_INTEGRITY,0),a.writeUInt16BE(20,2),t=Buffer.concat([t,a,i])}const r=t.length+8,s=this.#H(r),i=(1398035790^function(e){let t=4294967295;for(let r=0;r<e.length;r++)t=_[255&(t^e[r])]^t>>>8;return(4294967295^t)>>>0}(Buffer.concat([s,t])))>>>0,a=Buffer.alloc(8);return a.writeUInt16BE(L.FINGERPRINT,0),a.writeUInt16BE(4,2),a.writeUInt32BE(i,4),t=Buffer.concat([t,a]),Buffer.concat([this.#H(t.length),t])}}const H=554869826;class F extends t.EventEmitter{#F;#M;#K;#q;#G;#$;#j;#z;constructor(e){super(),this.#F=e.server,this.#M=e.port,this.#K=e.username,this.#q=e.credential,this.#G=null,this.#$=new Map,this.#j=null,this.#z=null}async connect(){if(!this.#G)return new Promise((e,t)=>{const r=a.createSocket("udp4");this.#G=r,r.on("message",(e,t)=>{this.#V(e,t)}),r.on("error",e=>{console.error("STUN socket error:",e),t(e)}),r.bind(()=>{e()})})}async getReflexiveAddress(){await this.connect();const e=n.randomBytes(12),t=this.#W(e);return new Promise((r,s)=>{const i=setTimeout(()=>{this.#$.delete(e.toString("hex")),s(new Error("STUN request timeout"))},5e3);this.#$.set(e.toString("hex"),{resolve:e=>{clearTimeout(i),r(e)},reject:e=>{clearTimeout(i),s(e)}}),this.#G.send(t,this.#M,this.#F,t=>{t&&(clearTimeout(i),this.#$.delete(e.toString("hex")),s(t))})})}async allocateRelay(e=600){if(!this.#K||!this.#q)throw new Error("TURN requires username and credential");await this.connect();let t=n.randomBytes(12),r=this.#Y(t,e);try{return await this.#X(r,t,"allocate")}catch(s){if(s instanceof Error&&s.message.includes("401")&&this.#j&&this.#z)return t=n.randomBytes(12),r=this.#Y(t,e,!0),await this.#X(r,t,"allocate");throw s}}async refreshAllocation(e=600){if(!this.#K||!this.#q)throw new Error("TURN requires username and credential");return this.#Q("refresh",()=>{const t=n.randomBytes(12);return{transactionId:t,request:this.#Z(t,e)}})}async#Q(e,t){const r=t();try{return await this.#X(r.request,r.transactionId,e)}catch(r){if(r instanceof Error&&r.message.includes("401")&&this.#j&&this.#z){const r=t();return this.#X(r.request,r.transactionId,e)}throw r}}async createPermission(e){if(!this.#K||!this.#q)throw new Error("TURN requires username and credential");await this.#Q("createPermission",()=>{const t=n.randomBytes(12);return{transactionId:t,request:this.#J(t,e)}})}async sendIndication(e,t,r){if(!this.#K||!this.#q)throw new Error("TURN requires username and credential");const s=n.randomBytes(12),i=this.#ee(s,e,t,r);return new Promise((e,t)=>{this.#G.send(i,this.#M,this.#F,r=>{r?t(r):e()})})}#X(e,t,r){return new Promise((s,i)=>{const n=setTimeout(()=>{this.#$.delete(t.toString("hex")),i(new Error(`${r} request timeout`))},5e3);this.#$.set(t.toString("hex"),{type:r,resolve:e=>{clearTimeout(n),s(e)},reject:e=>{clearTimeout(n),i(e)}}),this.#G.send(e,this.#M,this.#F,e=>{e&&(clearTimeout(n),this.#$.delete(t.toString("hex")),i(e))})})}#W(e){const t=Buffer.alloc(20);return t.writeUInt16BE(1,0),t.writeUInt16BE(0,2),t.writeUInt32BE(H,4),e.copy(t,8),t}#Y(e,t,r=!1){const s=[],i=Buffer.alloc(8);i.writeUInt16BE(25,0),i.writeUInt16BE(4,2),i.writeUInt8(17,4),s.push(i);const n=Buffer.alloc(8);if(n.writeUInt16BE(13,0),n.writeUInt16BE(4,2),n.writeUInt32BE(t,4),s.push(n),r&&this.#j&&this.#z){const e=this.#te(6,this.#K);s.push(e);const t=this.#te(20,this.#j);s.push(t);const r=this.#te(21,this.#z);s.push(r)}return this.#re(3,e,s,r)}#J(e,t){const r=[],s=this.#se(t,0,e);return r.push(s),this.#j&&this.#z&&(r.push(this.#te(6,this.#K)),r.push(this.#te(20,this.#j)),r.push(this.#te(21,this.#z))),this.#re(8,e,r,!0)}#ee(e,t,r,s){const i=[],n=this.#se(t,r,e);i.push(n);const a=Buffer.alloc(4+s.length+(4-s.length%4)%4);return a.writeUInt16BE(19,0),a.writeUInt16BE(s.length,2),s.copy(a,4),i.push(a),this.#re(22,e,i,!1)}#se(e,t,r){const s=Buffer.alloc(12);s.writeUInt16BE(18,0),s.writeUInt16BE(8,2),s.writeUInt8(0,4),s.writeUInt8(1,5);const i=8466^t;s.writeUInt16BE(i,6);const n=e.split(".").map(Number),a=(n[0]<<24|n[1]<<16|n[2]<<8|n[3])^H;return s.writeUInt32BE(a>>>0,8),s}#Z(e,t){const r=[],s=Buffer.alloc(8);s.writeUInt16BE(13,0),s.writeUInt16BE(4,2),s.writeUInt32BE(t,4),r.push(s);const i=this.#te(6,this.#K);if(r.push(i),this.#j){const e=this.#te(20,this.#j);r.push(e)}if(this.#z){const e=this.#te(21,this.#z);r.push(e)}return this.#re(4,e,r,!0)}#re(e,t,r,s=!1){let i=Buffer.concat(r);if(s&&this.#q){const r=Buffer.alloc(20);r.writeUInt16BE(e,0),r.writeUInt16BE(i.length+24,2),r.writeUInt32BE(H,4),t.copy(r,8);const s=Buffer.concat([r,i]);let a=this.#q;if(this.#K&&this.#j){const e=`${this.#K}:${this.#j}:${this.#q}`;a=n.createHash("md5").update(e).digest()}const o=n.createHmac("sha1",a);o.update(s);const c=o.digest(),h=Buffer.alloc(4+c.length);h.writeUInt16BE(8,0),h.writeUInt16BE(c.length,2),c.copy(h,4),i=Buffer.concat([i,h])}const a=Buffer.alloc(20);return a.writeUInt16BE(e,0),a.writeUInt16BE(i.length,2),a.writeUInt32BE(H,4),t.copy(a,8),Buffer.concat([a,i])}#te(e,t){const r=Buffer.from(t,"utf8"),s=r.length,i=(4-s%4)%4,n=Buffer.alloc(4+s+i);return n.writeUInt16BE(e,0),n.writeUInt16BE(s,2),r.copy(n,4),n}#V(e,t){if(e.length<20)return;const r=e.readUInt16BE(0),s=e.readUInt16BE(2),i=e.readUInt32BE(4),n=e.slice(8,20);if(i!==H)return;if(23===r){const t=this.#ie(e.slice(20,20+s),n);if(t.xorPeerAddress&&t.data){const e={address:t.xorPeerAddress.address,port:t.xorPeerAddress.port,family:t.xorPeerAddress.family||"IPv4"};this.emit("data",t.data,e)}return}const a=n.toString("hex"),o=this.#$.get(a);if(!o)return;const c=this.#ie(e.slice(20,20+s),n);if(257===r)c.xorMappedAddress?o.resolve({address:c.xorMappedAddress.address,port:c.xorMappedAddress.port,family:c.xorMappedAddress.family}):c.mappedAddress?o.resolve({address:c.mappedAddress.address,port:c.mappedAddress.port,family:c.mappedAddress.family}):o.reject(new Error("No mapped address in STUN response")),this.#$.delete(a);else if(259===r)c.xorRelayedAddress?o.resolve({relayedAddress:c.xorRelayedAddress.address,relayedPort:c.xorRelayedAddress.port,lifetime:c.lifetime||600,type:"relay"}):o.reject(new Error("No relayed address in ALLOCATE response")),this.#$.delete(a);else if(260===r)o.resolve({lifetime:c.lifetime||600}),this.#$.delete(a);else if(264===r||265===r)o.resolve({ok:!0}),this.#$.delete(a);else if(!(272&~r)){c.realm&&(this.#j=c.realm),c.nonce&&(this.#z=c.nonce);const e=c.errorCode||"Unknown error";o.reject(new Error(`STUN error: ${e}`)),this.#$.delete(a)}}#ie(e,t){const r={};let s=0;for(;s<e.length&&!(s+4>e.length);){const i=e.readUInt16BE(s),n=e.readUInt16BE(s+2);if(s+=4,s+n>e.length)break;const a=e.slice(s,s+n);switch(i){case 32:r.xorMappedAddress=this.#ne(a,t);break;case 22:r.xorRelayedAddress=this.#ne(a,t);break;case 18:r.xorPeerAddress=this.#ne(a,t);break;case 19:r.data=a;break;case 1:r.mappedAddress=this.#ae(a);break;case 13:r.lifetime=a.readUInt32BE(0);break;case 9:r.errorCode=this.#oe(a);break;case 20:r.realm=a.toString("utf8"),this.#j=r.realm;break;case 21:r.nonce=a.toString("utf8"),this.#z=r.nonce}s+=n,s+=(4-n%4)%4}return r}#ne(e,t){const r=e.readUInt8(1),s=8466^e.readUInt16BE(2);if(1===r){const t=e.readUInt32BE(4)^H;return{family:"IPv4",port:s,address:[t>>24&255,t>>16&255,t>>8&255,255&t].join(".")}}return null}#ae(e){const t=e.readUInt8(1),r=e.readUInt16BE(2);if(1===t){const t=e.slice(4,8);return{family:"IPv4",port:r,address:Array.from(t).join(".")}}return null}#oe(e){return`${100*(7&e.readUInt8(2))+e.readUInt8(3)} ${e.slice(4).toString("utf8")}`}close(){this.#G&&(this.#G.close(),this.#G=null),this.#$.clear()}}const M={host:126,srflx:100,prflx:110,relay:0};function K(e){const t=e.match(/^(stuns?|turns?):\/?\/?([^:?]+):?(\d+)?(?:\?(.+))?$/);if(!t)return null;const r=t[1],s=t[2],i={};if(t[4])for(const e of t[4].split("&")){if(!e)continue;const t=e.indexOf("=");-1===t?i[e]=!0:i[e.slice(0,t)]=e.slice(t+1)}const n="turns"===r||"stuns"===r?5349:3478;return{scheme:r,protocol:r,host:s,port:parseInt(t[3]||String(n),10),transport:"string"==typeof i.transport?i.transport:"udp",params:i}}class q{kind;#G;onMessage;constructor(e){this.kind="host",this.#G=e,this.onMessage=null,e.on("message",(e,t)=>{this.onMessage&&this.onMessage(e,{address:t.address,port:t.port})})}send(e,t,r){this.#G.send(e,r,t)}close(){try{this.#G.close()}catch(e){}}}class G{kind;#ce;onMessage;#he;constructor(e){this.kind="relay",this.#ce=e,this.onMessage=null,this.#he=new Set,e.on("data",(e,t)=>{this.onMessage&&this.onMessage(e,{address:t.address,port:t.port})})}send(e,t,r){const s=`${t}:${r}`;this.#he.has(s)?this.#ce.sendIndication(t,r,e).catch(()=>{}):(this.#he.add(s),this.#ce.createPermission(t).then(()=>this.#ce.sendIndication(t,r,e)).catch(()=>{}))}close(){try{this.#ce.close()}catch(e){}}}class $ extends t.EventEmitter{role;localUfrag;localPwd;remoteUfrag;remotePwd;#de;#le;#ue;#fe;#pe;#Ee;#me;#ge;#Ie;#U;#Ce;constructor(e){super(),this.role=e.role,this.localUfrag=e.localUfrag,this.localPwd=e.localPwd,this.remoteUfrag=null,this.remotePwd=null,this.#de=n.randomBytes(8),this.#le=[],this.#ue=[],this.#fe=[],this.#pe=[],this.#Ee=null,this.#me=!1,this.#ge=null,this.#Ie=null,this.#U=!1,this.#Ce=new Map}async gather(e={}){const t=e.iceServers||[],r="relay"===e.iceTransportPolicy,s=await this.#Te();for(const e of t){const t=Array.isArray(e.urls)?e.urls:[e.urls];for(const i of t){const t=K(i);if(t&&"udp"===t.transport)try{"stun"!==t.scheme||r?"turn"!==t.scheme&&"turns"!==t.scheme||await this.#Se(t,e):await this.#ye(t,s[0])}catch(e){this.emit("gathererror",{url:i,error:e instanceof Error?e.message:String(e)})}}}r&&(this.#ue=this.#ue.filter(e=>"relay"===e.type)),this.emit("gatheringcomplete")}async#Te(){const e=o.networkInterfaces(),t=[];for(const r of Object.values(e))if(r)for(const e of r)"IPv4"!==e.family||e.internal||t.push(e.address);0===t.length&&t.push("127.0.0.1");const r=[];for(const e of t)r.push(await this.#Ae(e));return r}#Ae(e){return new Promise((t,r)=>{const s=a.createSocket("udp4");s.on("error",e=>this.emit("error",e)),s.bind(0,e,()=>{const{port:r}=s.address(),i=new q(s);i.onMessage=(e,t)=>this.#Re(i,e,t),this.#le.push(i);const n=this.#Be("host",e,r,i);t({socket:s,address:e,port:r,transport:i,candidate:n})})})}async#ye(e,t){if(!t)return;const r=new F({server:e.host,port:e.port});try{const e=await r.getReflexiveAddress();this.#Be("srflx",e.address,e.port,t.transport,{relatedAddress:t.address,relatedPort:t.port})}finally{r.close()}}async#Se(e,t){if(!t.username||!t.credential)throw new Error("TURN server requires username and credential");const r=new F({server:e.host,port:e.port,username:t.username,credential:t.credential,transport:e.transport}),s=await r.allocateRelay(600),i=new G(r);i.onMessage=(e,t)=>this.#Re(i,e,t),this.#le.push(i),this.#Be("relay",s.relayedAddress,s.relayedPort,i,{relatedAddress:e.host,relatedPort:e.port})}#Be(e,t,r,s,i={}){const a=n.createHash("md5").update(`${e}:${t}:${s.kind}`).digest("hex").slice(0,8),o=function(e,t=65535,r=1){return(M[e]<<24)+(t<<8)+(256-r)>>>0}(e);let c=`candidate:${a} 1 udp ${o} ${t} ${r} typ ${e}`;i.relatedAddress&&(c+=` raddr ${i.relatedAddress} rport ${i.relatedPort}`);const h={foundation:a,component:1,protocol:"udp",priority:o,address:t,port:r,type:e,transport:s,sdp:c};return this.#ue.push(h),this.emit("candidate",h),h}getLocalCandidates(){return this.#ue.slice()}setRemoteCredentials(e,t){this.remoteUfrag=e,this.remotePwd=t}addRemoteCandidate(e){e&&e.address&&e.port&&("string"==typeof e.address&&e.address.endsWith(".local")||(this.#fe.push(e),this.#we(),!this.#ge&&this.remotePwd&&this.#Ne()))}start(){this.remotePwd&&this.#fe.length>0&&this.#Ne()}#we(){for(const e of this.#ue)for(const t of this.#fe){const r=`${e.type}:${e.address}:${e.port}->${t.address}:${t.port}`;this.#pe.find(e=>e.key===r)||this.#pe.push({key:r,local:e,remote:t,state:"frozen",nominated:!1})}}#Ne(){this.#ge||this.#me||(this.#ge=setInterval(()=>this.#be(),50),this.#ge.unref&&this.#ge.unref(),this.#Ie=setTimeout(()=>{this.#U||this.emit("failed"),this.#Oe()},1e4),this.#Ie.unref&&this.#Ie.unref(),this.#be())}#Oe(){this.#ge&&(clearInterval(this.#ge),this.#ge=null),this.#Ie&&(clearTimeout(this.#Ie),this.#Ie=null)}#be(){if(!this.#me)for(const e of this.#pe)"succeeded"!==e.state&&this.#De(e)}#De(e){const t=n.randomBytes(12),r=`${this.remoteUfrag}:${this.localUfrag}`,s=new x(k.BINDING_REQUEST,t).addUsername(r).addPriority(e.local.priority);"controlling"===this.role?(s.addIceControlling(this.#de),s.addUseCandidate()):s.addIceControlled(this.#de);const i=s.build(this.remotePwd??void 0);this.#Ce.set(t.toString("hex"),e),e.state="in-progress",e.local.transport.send(i,e.remote.address,e.remote.port)}#Re(e,t,r){0!==t.length&&(t[0]<=3?this.#Ue(e,t,r):this.emit("data",t,{transport:e,address:r.address,port:r.port}))}#Ue(e,t,r){const s=function(e){if(e.length<20)return null;if(e.readUInt32BE(4)!==v)return null;const t=e.readUInt16BE(0),r=e.readUInt16BE(2);if(20+r>e.length)return null;const s=e.slice(8,20),i=new Map;let n=20;const a=20+r;for(;n+4<=a;){const t=e.readUInt16BE(n),r=e.readUInt16BE(n+2);if(n+=4,n+r>a)break;i.set(t,e.slice(n,n+r)),n+=P(r)}return{type:t,transactionId:s,attrs:i,raw:e}}(t);s&&(s.type===k.BINDING_REQUEST?this.#ve(e,s,r):s.type===k.BINDING_SUCCESS&&this.#ke(e,s,r))}#ve(e,t,r){if(this.localPwd&&!function(e,t){let r=20;const s=20+e.readUInt16BE(2);let i=-1;for(;r+4<=s;){const t=e.readUInt16BE(r),s=e.readUInt16BE(r+2);if(t===L.MESSAGE_INTEGRITY){i=r;break}r+=4+P(s)}if(i<0)return!1;const a=e.slice(i+4,i+4+20),o=i+24-20,c=Buffer.from(e.slice(0,20));c.writeUInt16BE(o,2);const h=n.createHmac("sha1",Buffer.from(t,"utf8")).update(Buffer.concat([c,e.slice(20,i)])).digest();return a.length===h.length&&n.timingSafeEqual(a,h)}(t.raw,this.localPwd))return;const s=new x(k.BINDING_SUCCESS,t.transactionId).addXorMappedAddress(r.address,r.port).build(this.localPwd);e.send(s,r.address,r.port),this.#fe.find(e=>e.address===r.address&&e.port===r.port)||this.addRemoteCandidate({address:r.address,port:r.port,type:"prflx",priority:0});const i=t.attrs.has(L.USE_CANDIDATE),a=this.#Le(e,r);i&&"controlled"===this.role&&this.#Pe(a||this.#_e(e,r))}#ke(e,t,r){const s=this.#Ce.get(t.transactionId.toString("hex"));s&&(this.#Ce.delete(t.transactionId.toString("hex")),s.state="succeeded","controlling"===this.role&&this.#Pe(s))}#Le(e,t){return this.#pe.find(r=>r.remote.address===t.address&&r.remote.port===t.port&&r.local.transport===e)}#_e(e,t){return{local:{transport:e},remote:{address:t.address,port:t.port}}}#Pe(e){!this.#Ee&&e&&(this.#Ee=e,this.#U=!0,this.#Oe(),this.emit("selected",{transport:e.local.transport,candidateType:e.local.type,remoteAddress:e.remote.address,remotePort:e.remote.port}),this.emit("connected"))}send(e){if(!this.#Ee)throw new Error("ICE not connected");this.#Ee.local.transport.send(e,this.#Ee.remote.address,this.#Ee.remote.port)}getSelectedPair(){return this.#Ee}getSelectedCandidateType(){return this.#Ee?this.#Ee.local.type:null}close(){if(!this.#me){this.#me=!0,this.#Oe();for(const e of this.#le)try{e.close()}catch(e){}this.#le=[],this.emit("closed")}}}const j=Object.freeze({CHANGE_CIPHER_SPEC:20,ALERT:21,HANDSHAKE:22,APPLICATION_DATA:23}),z=Object.freeze({HELLO_REQUEST:0,CLIENT_HELLO:1,SERVER_HELLO:2,HELLO_VERIFY_REQUEST:3,CERTIFICATE:11,SERVER_KEY_EXCHANGE:12,CERTIFICATE_REQUEST:13,SERVER_HELLO_DONE:14,CERTIFICATE_VERIFY:15,CLIENT_KEY_EXCHANGE:16,FINISHED:20}),V=Object.freeze({WARNING:1,FATAL:2}),W=Object.freeze({CLOSE_NOTIFY:0,HANDSHAKE_FAILURE:40,BAD_CERTIFICATE:42,DECRYPT_ERROR:51,INTERNAL_ERROR:80}),Y=49195,X=Object.freeze({secp256r1:23}),Q=Object.freeze({uncompressed:0}),Z=Object.freeze({sha256:4,sha384:5,sha512:6}),J=Object.freeze({rsa:1,ecdsa:3}),ee=Object.freeze({ecdsa_sign:64,rsa_sign:1}),te=Object.freeze({SUPPORTED_GROUPS:10,EC_POINT_FORMATS:11,SIGNATURE_ALGORITHMS:13,EXTENDED_MASTER_SECRET:23,RENEGOTIATION_INFO:65281}),re=Object.freeze({CLIENT:"client finished",SERVER:"server finished"});function se(e){return Buffer.from([e>>16&255,e>>8&255,255&e])}function ie(e,t){return e[t]<<16|e[t+1]<<8|e[t+2]}function ne(e){return Buffer.concat([Buffer.from([e.length]),e])}function ae(e){const t=Buffer.alloc(2);return t.writeUInt16BE(e.length,0),Buffer.concat([t,e])}function oe(e){return Buffer.concat([se(e.length),e])}function ce(e,t,r){const s=Buffer.alloc(12);return s.writeUInt8(e,0),se(r.length).copy(s,1),s.writeUInt16BE(t,4),se(0).copy(s,6),se(r.length).copy(s,9),Buffer.concat([s,r])}function he(e,t,r,s){return function(e,t,r,s){const i=[];let a=0,o=r;for(;a<s;){o=n.createHmac(e,t).update(o).digest();const s=n.createHmac(e,t).update(Buffer.concat([o,r])).digest();i.push(s),a+=s.length}return Buffer.concat(i).slice(0,s)}("sha256",e,Buffer.concat([Buffer.from(t,"ascii"),r]),s)}function de(e,t,r){return he(e,"master secret",Buffer.concat([t,r]),48)}function le(e,t){return he(e,"extended master secret",t,48)}function ue(e,t,r,s,i){const n=Buffer.alloc(13);return n.writeUInt16BE(e,0),n.writeUIntBE(t,2,6),n.writeUInt8(r,8),n.writeUInt16BE(s,9),n.writeUInt16BE(i,11),n}class fe{#xe;#He;constructor(e,t){this.#xe=e,this.#He=t}encrypt(e,t,r,s,i){const a=Buffer.alloc(8);a.writeUInt16BE(e,0),a.writeUIntBE(t,2,6);const o=Buffer.concat([this.#He,a]),c=ue(e,t,r,s,i.length),h=n.createCipheriv("aes-128-gcm",this.#xe,o);h.setAAD(c);const d=Buffer.concat([h.update(i),h.final()]),l=h.getAuthTag();return Buffer.concat([a,d,l])}decrypt(e,t,r,s,i){const a=i.slice(0,8),o=i.slice(i.length-16),c=i.slice(8,i.length-16),h=Buffer.concat([this.#He,a]),d=ue(e,t,r,s,c.length),l=n.createDecipheriv("aes-128-gcm",this.#xe,h);return l.setAAD(d),l.setAuthTag(o),Buffer.concat([l.update(c),l.final()])}}const pe=Object.freeze({CLIENT:"client",SERVER:"server"}),Ee=Object.freeze({NEW:"new",HANDSHAKING:"handshaking",CONNECTED:"connected",CLOSED:"closed",FAILED:"failed"});class me extends t.EventEmitter{role;state;#p;#E;#Fe;#Me;#Ke;#qe;#Ge;#$e;#je;#ze;#Ve;#We;#Ye;#Xe;#Qe;#Ze;#Je;#et;#tt;#rt;#st;#it;#nt;#at;#ot;#ct;#ht;constructor(e){super(),this.role=e.role,this.#p=e.certDer,this.#E=e.privateKey,this.#Fe=e.verifyFingerprint||null,this.#Me=e.output,this.state=Ee.NEW,this.#Ke=0,this.#qe=0,this.#Ge=0,this.#$e=null,this.#je=null,this.#ze=!1,this.#Ve=null,this.#We=null,this.#Ye=Buffer.alloc(0),this.#Xe=null,this.#Qe=null,this.#Ze=null,this.#Je=null,this.#et=!1,this.#tt=[],this.#rt=new Map,this.#st=0,this.#it=[],this.#nt=null,this.#at=0,this.#ot=!1}start(){this.state===Ee.NEW&&(this.state=Ee.HANDSHAKING,this.role===pe.CLIENT&&(this.#Ve=this.#dt(),this.#lt()))}#dt(){const e=n.randomBytes(32);return e.writeUInt32BE(Math.floor(Date.now()/1e3),0),e}#ut(e){const t=[];for(const r of e){const e=this.#Ge++,s=ce(r.type,e,r.body);this.#tt.push(s);const i=r.body.length;let n=0;do{const s=r.body.slice(n,n+1200),a=Buffer.alloc(12);a.writeUInt8(r.type,0),se(i).copy(a,1),a.writeUInt16BE(e,4),se(n).copy(a,6),se(s.length).copy(a,9);const o=Buffer.concat([a,s]);t.push({type:j.HANDSHAKE,payload:o}),n+=s.length}while(n<i)}this.#it=t,this.#at=0,this.#ft(),this.#pt()}#ft(){for(const e of this.#it)this.#Et(e.type,e.payload)}#mt(){this.#Et(j.CHANGE_CIPHER_SPEC,Buffer.from([1])),this.#Ke=1,this.#qe=0,this.#ze=!0}#Et(e,t){let r=t;const s=this.#qe++;this.#ze&&this.#$e&&(r=this.#$e.encrypt(this.#Ke,s,e,65277,t));const i=function(e,t,r,s,i=65277){const n=Buffer.alloc(13);return n.writeUInt8(e,0),n.writeUInt16BE(i,1),n.writeUInt16BE(t,3),n.writeUIntBE(r,5,6),n.writeUInt16BE(s.length,11),Buffer.concat([n,s])}(e,this.#Ke,s,r,65277);this.#Me(i)}#pt(){this.#gt(),this.#nt=setTimeout(()=>{this.#ot||this.state!==Ee.HANDSHAKING||(this.#at>=10?this.#It(new Error("DTLS handshake timed out")):(this.#at++,this.#ft(),this.#pt()))},1e3*Math.pow(2,this.#at)),this.#nt.unref&&this.#nt.unref()}#gt(){this.#nt&&(clearTimeout(this.#nt),this.#nt=null)}handlePacket(e){if(this.state===Ee.CLOSED||this.state===Ee.FAILED)return;let t;try{t=function(e){const t=[];let r=0;for(;r+13<=e.length;){const s=e.readUInt8(r),i=e.readUInt16BE(r+1),n=e.readUInt16BE(r+3),a=e.readUIntBE(r+5,6),o=e.readUInt16BE(r+11),c=r+13;if(c+o>e.length)break;t.push({type:s,version:i,epoch:n,seq:a,fragment:e.slice(c,c+o)}),r=c+o}return t}(e)}catch(e){return}for(const e of t)try{this.#Ct(e)}catch(e){return void this.#It(e instanceof Error?e:new Error(String(e)))}}#Ct(e){let t=e.fragment;if(e.epoch>=1){if(!this.#je)return;t=this.#je.decrypt(e.epoch,e.seq,e.type,e.version,e.fragment)}switch(e.type){case j.HANDSHAKE:this.#Tt(t);break;case j.CHANGE_CIPHER_SPEC:break;case j.APPLICATION_DATA:this.state===Ee.CONNECTED&&this.emit("data",t);break;case j.ALERT:this.#St(t)}}#St(e){if(e.length<2)return;const t=e[0],r=e[1];r===W.CLOSE_NOTIFY?this.close():t===V.FATAL&&this.#It(new Error(`DTLS fatal alert: ${r}`))}#Tt(e){const t=function(e){const t=e.readUInt8(0),r=ie(e,1),s=e.readUInt16BE(4),i=ie(e,6),n=ie(e,9);return{msgType:t,length:r,messageSeq:s,fragmentOffset:i,fragmentLength:n,body:e.slice(12,12+n)}}(e);let r=this.#rt.get(t.messageSeq);for(r||(r={type:t.msgType,length:t.length,data:Buffer.alloc(t.length),received:0,ranges:[]},this.#rt.set(t.messageSeq,r)),t.body.copy(r.data,t.fragmentOffset),r.received=Math.max(r.received,t.fragmentOffset+t.fragmentLength);;){const e=this.#rt.get(this.#st);if(!e||e.received<e.length)break;this.#rt.delete(this.#st),this.#st++,this.#yt(e.type,e.data)}}#At(e,t){const r=this.#st-1;this.#tt.push(ce(e,r,t))}#yt(e,t){this.role===pe.CLIENT?this.#Rt(e,t):this.#Bt(e,t)}#wt(){const e=n.createHash("sha256");for(const t of this.#tt)e.update(t);return e.digest()}#Nt(){return Buffer.concat(this.#tt)}#lt(){const e=this.#bt();if(0===this.#Ye.length){const t=this.#Ge++,r=ce(z.CLIENT_HELLO,t,e);this.#it=[{type:j.HANDSHAKE,payload:r}],this.#ft(),this.#pt()}else{const t=this.#Ge++,r=ce(z.CLIENT_HELLO,t,e);this.#tt.push(r),this.#it=[{type:j.HANDSHAKE,payload:r}],this.#at=0,this.#ft(),this.#pt()}}#bt(){const e=[];e.push(Buffer.from([254,253])),e.push(this.#Ve),e.push(ne(Buffer.alloc(0))),e.push(ne(this.#Ye));const t=Buffer.alloc(2);return t.writeUInt16BE(Y,0),e.push(ae(t)),e.push(ne(Buffer.from([0]))),e.push(ae(this.#Ot())),Buffer.concat(e)}#Ot(){const e=[],t=Buffer.alloc(2);t.writeUInt16BE(X.secp256r1,0),e.push(this.#Dt(te.SUPPORTED_GROUPS,ae(t))),e.push(this.#Dt(te.EC_POINT_FORMATS,ne(Buffer.from([Q.uncompressed]))));const r=Buffer.from([Z.sha256,J.ecdsa]);return e.push(this.#Dt(te.SIGNATURE_ALGORITHMS,ae(r))),e.push(this.#Dt(te.EXTENDED_MASTER_SECRET,Buffer.alloc(0))),Buffer.concat(e)}#Dt(e,t){const r=Buffer.alloc(4);return r.writeUInt16BE(e,0),r.writeUInt16BE(t.length,2),Buffer.concat([r,t])}#Rt(e,t){switch(e){case z.HELLO_VERIFY_REQUEST:{const e=t.readUInt8(2);this.#Ye=t.slice(3,3+e),this.#gt(),this.#lt();break}case z.SERVER_HELLO:this.#At(e,t),this.#Ut(t);break;case z.CERTIFICATE:this.#At(e,t),this.#Ze=this.#vt(t);break;case z.SERVER_KEY_EXCHANGE:this.#At(e,t),this.#kt(t);break;case z.CERTIFICATE_REQUEST:this.#At(e,t);break;case z.SERVER_HELLO_DONE:this.#At(e,t),this.#gt(),this.#Lt();break;case z.FINISHED:this.#Pt(t,re.SERVER),this.#At(e,t),this.#_t()}}#Ut(e){let t=2;this.#We=e.slice(t,t+32),t+=32,t+=1+e.readUInt8(t);const r=e.readUInt16BE(t);if(t+=2,r!==Y)throw new Error(`Server chose unsupported cipher suite 0x${r.toString(16)}`);if(t+=1,t+2<=e.length){const r=e.readUInt16BE(t);t+=2;const s=t+r;for(;t+4<=s;){const r=e.readUInt16BE(t),s=e.readUInt16BE(t+2);t+=4,r===te.EXTENDED_MASTER_SECRET&&(this.#et=!0),t+=s}}}#Lt(){this.#Xe=n.createECDH("prime256v1"),this.#Xe.generateKeys();const e=this.#Xe.getPublicKey(),t=this.#Xe.computeSecret(this.#Je),r=this.#xt(),s=ne(e),i=this.#Ge,a=i+1,o=ce(z.CERTIFICATE,i,r),c=ce(z.CLIENT_KEY_EXCHANGE,a,s);if(this.#et){const e=n.createHash("sha256");for(const t of this.#tt)e.update(t);e.update(o),e.update(c);const r=e.digest();this.#Qe=le(t,r)}else this.#Qe=de(t,this.#Ve,this.#We);this.#Ht();const h=Buffer.concat([...this.#tt,o,c]),d=n.sign("sha256",h,{key:this.#E,dsaEncoding:"der"}),l=Buffer.concat([Buffer.from([Z.sha256,J.ecdsa]),ae(d)]);this.#ut([{type:z.CERTIFICATE,body:r},{type:z.CLIENT_KEY_EXCHANGE,body:s},{type:z.CERTIFICATE_VERIFY,body:l}]),this.#mt(),this.#Ft(re.CLIENT)}#Bt(e,t){switch(e){case z.CLIENT_HELLO:this.#Mt(t);break;case z.CERTIFICATE:this.#At(e,t),this.#Ze=this.#vt(t);break;case z.CLIENT_KEY_EXCHANGE:{this.#At(e,t);const r=t.readUInt8(0);this.#Je=t.slice(1,1+r);const s=this.#Xe.computeSecret(this.#Je);this.#et?this.#Qe=le(s,this.#wt()):this.#Qe=de(s,this.#Ve,this.#We),this.#Ht();break}case z.CERTIFICATE_VERIFY:this.#Kt(t),this.#At(e,t);break;case z.FINISHED:this.#Pt(t,re.CLIENT),this.#At(e,t),this.#mt(),this.#Ft(re.SERVER),this.#_t()}}#Mt(e){let t=2;const r=e.slice(t,t+32);t+=32,t+=1+e.readUInt8(t);const s=e.readUInt8(t),i=e.slice(t+1,t+1+s);t+=1+s;const n=e.readUInt16BE(t),a=e.slice(t+2,t+2+n);t+=2+n,t+=1+e.readUInt8(t);let o=!1,c=!1;for(let e=0;e+1<a.length;e+=2)255===a.readUInt16BE(e)&&(c=!0);if(t+2<=e.length){const r=e.readUInt16BE(t);t+=2;const s=t+r;for(;t+4<=s;){const r=e.readUInt16BE(t),s=e.readUInt16BE(t+2);t+=4,r===te.EXTENDED_MASTER_SECRET&&(o=!0),r===te.RENEGOTIATION_INFO&&(c=!0),t+=s}}if(this.#ht=c,0===i.length)return this.#Ve=r,this.#qt(this.#Gt(r)),this.#rt.clear(),void(this.#st=1);const h=this.#Gt(r);if(!i.equals(h))return this.#qt(h),this.#rt.clear(),void(this.#st=1);this.#Ve=r,this.#et=o,this.#At(z.CLIENT_HELLO,e),this.#$t()}#Gt(e){return this.#ct||(this.#ct=n.randomBytes(32)),n.createHmac("sha256",this.#ct).update(e).digest().slice(0,20)}#qt(e){const t=Buffer.concat([Buffer.from([254,255]),ne(e)]),r=ce(z.HELLO_VERIFY_REQUEST,0,t);this.#Et(j.HANDSHAKE,r),this.#Ge=1}#$t(){this.#We=this.#dt(),this.#Xe=n.createECDH("prime256v1"),this.#Xe.generateKeys();const e=this.#Xe.getPublicKey(),t=this.#jt(),r=this.#xt(),s=Buffer.concat([Buffer.from([3]),(()=>{const e=Buffer.alloc(2);return e.writeUInt16BE(X.secp256r1,0),e})(),ne(e)]),i=Buffer.concat([this.#Ve,this.#We,s]),a=n.sign("sha256",i,{key:this.#E,dsaEncoding:"der"}),o=Buffer.concat([s,Buffer.from([Z.sha256,J.ecdsa]),ae(a)]),c=ne(Buffer.from([ee.ecdsa_sign,ee.rsa_sign])),h=ae(Buffer.from([Z.sha256,J.ecdsa])),d=ae(Buffer.alloc(0)),l=Buffer.concat([c,h,d]),u=Buffer.alloc(0);this.#ut([{type:z.SERVER_HELLO,body:t},{type:z.CERTIFICATE,body:r},{type:z.SERVER_KEY_EXCHANGE,body:o},{type:z.CERTIFICATE_REQUEST,body:l},{type:z.SERVER_HELLO_DONE,body:u}])}#jt(){const e=[];e.push(Buffer.from([254,253])),e.push(this.#We),e.push(ne(Buffer.alloc(0)));const t=Buffer.alloc(2);t.writeUInt16BE(Y,0),e.push(t),e.push(Buffer.from([0]));const r=[];return this.#et&&r.push(this.#Dt(te.EXTENDED_MASTER_SECRET,Buffer.alloc(0))),r.push(this.#Dt(te.EC_POINT_FORMATS,ne(Buffer.from([Q.uncompressed])))),this.#ht&&r.push(this.#Dt(te.RENEGOTIATION_INFO,ne(Buffer.alloc(0)))),e.push(ae(Buffer.concat(r))),Buffer.concat(e)}#Kt(e){const t=e.readUInt16BE(2),r=e.slice(4,4+t),s=this.#Nt(),i=this.#zt(this.#Ze);if(!n.verify("sha256",s,{key:i,dsaEncoding:"der"},r))throw new Error("Client CertificateVerify signature invalid")}#xt(){const e=oe(this.#p);return oe(e)}#vt(e){let t=3;if(t+3>3+ie(e,0))return null;const r=ie(e,t);t+=3;const s=e.slice(t,t+r);if(this.#Fe){const e={algorithm:"sha-256",value:S(s,"sha-256")};if(!this.#Fe(e,s))throw new Error("Remote certificate fingerprint mismatch")}return s}#kt(e){let t=0;const r=e.readUInt8(t);t+=1;const s=e.readUInt16BE(t);if(t+=2,3!==r||s!==X.secp256r1)throw new Error("Unsupported ECDHE curve from server");const i=e.readUInt8(t);t+=1;const a=e.slice(t,t+i);t+=i,this.#Je=a;const o=e.slice(0,t);t+=2;const c=e.readUInt16BE(t);t+=2;const h=e.slice(t,t+c),d=Buffer.concat([this.#Ve,this.#We,o]),l=this.#zt(this.#Ze);if(!n.verify("sha256",d,{key:l,dsaEncoding:"der"},h))throw new Error("ServerKeyExchange signature invalid")}#zt(e){return new n.X509Certificate(e).publicKey}#Ht(){const{clientKey:e,serverKey:t,clientIV:r,serverIV:s}=function(e,t,r){const s=he(e,"key expansion",Buffer.concat([r,t]),40);let i=0;return{clientKey:s.slice(i,i+=16),serverKey:s.slice(i,i+=16),clientIV:s.slice(i,i+=4),serverIV:s.slice(i,i+=4)}}(this.#Qe,this.#Ve,this.#We);this.role===pe.CLIENT?(this.#$e=new fe(e,r),this.#je=new fe(t,s)):(this.#$e=new fe(t,s),this.#je=new fe(e,r))}#Ft(e){const t=he(this.#Qe,e,this.#wt(),12),r=this.#Ge++,s=ce(z.FINISHED,r,t);this.#tt.push(s),this.#Et(j.HANDSHAKE,s)}#Pt(e,t){const r=he(this.#Qe,t,this.#wt(),12);if(!n.timingSafeEqual(e,r))throw new Error("Peer Finished verify_data mismatch")}#_t(){this.#ot||(this.#ot=!0,this.#gt(),this.state=Ee.CONNECTED,this.emit("connect"))}send(e){if(this.state!==Ee.CONNECTED)throw new Error("DTLS connection not established");this.#Et(j.APPLICATION_DATA,e)}close(){if(this.state!==Ee.CLOSED&&this.state!==Ee.FAILED){try{this.#ze&&this.#Et(j.ALERT,Buffer.from([V.WARNING,W.CLOSE_NOTIFY]))}catch(e){}this.#gt(),this.state=Ee.CLOSED,this.emit("close")}}#It(e){this.state!==Ee.FAILED&&this.state!==Ee.CLOSED&&(this.#gt(),this.state=Ee.FAILED,this.emit("error",e))}getRemoteCertificate(){return this.#Ze}}const ge=Object.freeze({DATA:0,INIT:1,INIT_ACK:2,SACK:3,HEARTBEAT:4,HEARTBEAT_ACK:5,ABORT:6,SHUTDOWN:7,SHUTDOWN_ACK:8,ERROR:9,COOKIE_ECHO:10,COOKIE_ACK:11,SHUTDOWN_COMPLETE:14,FORWARD_TSN:192}),Ie=Object.freeze({HEARTBEAT_INFO:1,STATE_COOKIE:7,UNRECOGNIZED_PARAM:8,COOKIE_PRESERVATIVE:9,SUPPORTED_ADDR_TYPES:11,FORWARD_TSN_SUPPORTED:49152,SUPPORTED_EXTENSIONS:32776}),Ce=Object.freeze({DCEP:50,STRING:51,BINARY:53,STRING_EMPTY:56,BINARY_EMPTY:57,STRING_PARTIAL:54,BINARY_PARTIAL:52});function Te(e){return e+3&-4}function Se(e,t,r){const s=4+r.length,i=Buffer.alloc(Te(s));return i.writeUInt8(e,0),i.writeUInt8(t,1),i.writeUInt16BE(s,2),r.copy(i,4),i}function ye(e,t){const r=4+t.length,s=Buffer.alloc(Te(r));return s.writeUInt16BE(e,0),s.writeUInt16BE(r,2),t.copy(s,4),s}function Ae(e){const t=[];let r=0;for(;r+4<=e.length;){const s=e.readUInt16BE(r),i=e.readUInt16BE(r+2);if(i<4||r+i>e.length)break;t.push({type:s,length:i,value:e.slice(r+4,r+i)}),r+=Te(i)}return t}function Re({initiateTag:e,a_rwnd:t,outStreams:r,inStreams:s,initialTSN:i}){const n=Buffer.alloc(16);return n.writeUInt32BE(e>>>0,0),n.writeUInt32BE(t>>>0,4),n.writeUInt16BE(r,8),n.writeUInt16BE(s,10),n.writeUInt32BE(i>>>0,12),n}function Be(e){return{initiateTag:e.readUInt32BE(0),a_rwnd:e.readUInt32BE(4),outStreams:e.readUInt16BE(8),inStreams:e.readUInt16BE(10),initialTSN:e.readUInt32BE(12),params:Ae(e.slice(16))}}function we({tsn:e,streamId:t,streamSeq:r,ppid:s,userData:i,unordered:n=!1,beginning:a=!0,ending:o=!0}){const c=Buffer.alloc(12);c.writeUInt32BE(e>>>0,0),c.writeUInt16BE(t,4),c.writeUInt16BE(r,6),c.writeUInt32BE(s>>>0,8);let h=0;return o&&(h|=1),a&&(h|=2),n&&(h|=4),{flags:h,body:Buffer.concat([c,i])}}const Ne=(()=>{const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)r=1&r?2197175160^r>>>1:r>>>1;e[t]=r>>>0}return e})();function be(e){let t=4294967295;for(let r=0;r<e.length;r++)t=Ne[255&(t^e[r])]^t>>>8;return(4294967295^t)>>>0}const Oe=1048576,De=Object.freeze({CLOSED:"closed",COOKIE_WAIT:"cookie-wait",COOKIE_ECHOED:"cookie-echoed",ESTABLISHED:"established"});function Ue(e,t){return(e-t&4294967295)>2147483648}function ve(e,t){return e===t||Ue(e,t)}class ke extends t.EventEmitter{isClient;state;#Vt;#Wt;#Yt;#Xt;#Qt;#Zt;#Jt;#er;#tr;#rr;#sr;#ct;constructor(e={}){super(),this.isClient=!!e.isClient,this.state=De.CLOSED,this.#Vt=5e3,this.#Wt=5e3,this.#Yt=n.randomBytes(4).readUInt32BE(0)>>>0||1,this.#Xt=0,this.#Qt=n.randomBytes(4).readUInt32BE(0)>>>0,this.#Zt=new Map,this.#Jt=new Map,this.#er=null,this.#tr=new Map,this.#rr=new Map,this.#sr=null}start(){this.state===De.CLOSED&&this.isClient&&(this.#ir(),this.state=De.COOKIE_WAIT)}#nr(e,t){const r=function(e,t,r){const s=Buffer.alloc(12);return s.writeUInt16BE(e,0),s.writeUInt16BE(t,2),s.writeUInt32BE(r>>>0,4),s.writeUInt32BE(0,8),s}(this.#Vt,this.#Wt,e),s=Buffer.concat([r,...t]);!function(e){e.writeUInt32LE(0,8);const t=be(e);e.writeUInt32LE(t,8)}(s),this.emit("output",s)}receivePacket(e){if(e.length<12)return;if(!function(e){const t=e.readUInt32LE(8);e.writeUInt32LE(0,8);const r=be(e);return e.writeUInt32LE(t,8),r===t}(e))return;const t=function(e){return{srcPort:e.readUInt16BE(0),dstPort:e.readUInt16BE(2),verificationTag:e.readUInt32BE(4),checksum:e.readUInt32LE(8)}}(e),r=function(e){const t=[];let r=12;for(;r+4<=e.length;){const s=e.readUInt8(r),i=e.readUInt8(r+1),n=e.readUInt16BE(r+2);if(n<4||r+n>e.length)break;const a=e.slice(r+4,r+n);t.push({type:s,flags:i,length:n,body:a}),r+=Te(n)}return t}(e);for(const e of r)this.#ar(e,t)}#ar(e,t){switch(e.type){case ge.INIT:this.#or(e);break;case ge.INIT_ACK:this.#cr(e);break;case ge.COOKIE_ECHO:this.#hr(e);break;case ge.COOKIE_ACK:this.#dr();break;case ge.DATA:this.#lr(e);break;case ge.SACK:this.#ur(e);break;case ge.HEARTBEAT:this.#fr(e);break;case ge.ABORT:this.#pr("peer sent ABORT");break;case ge.SHUTDOWN:this.#Er()}}#mr(){return[ye(Ie.FORWARD_TSN_SUPPORTED,Buffer.alloc(0))]}#ir(){const e=Re({initiateTag:this.#Yt,a_rwnd:Oe,outStreams:65535,inStreams:65535,initialTSN:this.#Qt}),t=Se(ge.INIT,0,Buffer.concat([e,...this.#mr()]));this.#nr(0,[t]),this.#gr([t])}#gr(e){this.#Ir();let t=500,r=0;const s=()=>{this.state!==De.ESTABLISHED&&this.state!==De.CLOSED&&(r>=8?this.#pr("SCTP setup timed out"):(r++,this.#nr(this.state===De.COOKIE_ECHOED?this.#Xt:0,e),t=Math.min(2*t,5e3),this.#sr=setTimeout(s,t),this.#sr.unref&&this.#sr.unref()))};this.#sr=setTimeout(s,t),this.#sr.unref&&this.#sr.unref()}#Ir(){this.#sr&&(clearTimeout(this.#sr),this.#sr=null)}#or(e){const t=Be(e.body);this.#Xt=t.initiateTag,this.#er=t.initialTSN-1>>>0,this.#ct||(this.#ct=n.randomBytes(32));const r=Buffer.alloc(16);r.writeUInt32BE(this.#Yt,0),r.writeUInt32BE(this.#Xt,4),r.writeUInt32BE(this.#Qt,8),r.writeUInt32BE(t.initialTSN,12);const s=n.createHmac("sha256",this.#ct).update(r).digest(),i=Buffer.concat([r,s]),a=Re({initiateTag:this.#Yt,a_rwnd:Oe,outStreams:65535,inStreams:65535,initialTSN:this.#Qt}),o=Buffer.concat([ye(Ie.STATE_COOKIE,i),...this.#mr()]),c=Se(ge.INIT_ACK,0,Buffer.concat([a,o]));this.#nr(this.#Xt,[c])}#cr(e){if(this.state!==De.COOKIE_WAIT)return;this.#Ir();const t=Be(e.body);this.#Xt=t.initiateTag,this.#er=t.initialTSN-1>>>0;const r=t.params.find(e=>e.type===Ie.STATE_COOKIE);if(!r)return void this.#pr("INIT_ACK missing state cookie");const s=Se(ge.COOKIE_ECHO,0,r.value);this.state=De.COOKIE_ECHOED,this.#nr(this.#Xt,[s]),this.#gr([s])}#hr(e){const t=e.body;if(t.length>=48&&this.#ct){const e=t.slice(0,16),r=t.slice(16,48),s=n.createHmac("sha256",this.#ct).update(e).digest();if(!n.timingSafeEqual(r,s))return}const r=Se(ge.COOKIE_ACK,0,Buffer.alloc(0));this.#nr(this.#Xt,[r]),this.#Cr()}#dr(){this.state===De.COOKIE_ECHOED&&(this.#Ir(),this.#Cr())}#Cr(){this.state!==De.ESTABLISHED&&(this.state=De.ESTABLISHED,this.emit("established"))}sendData(e,t,r,s={}){if(this.state!==De.ESTABLISHED)throw new Error("SCTP association not established");const i=!!s.unordered;let n=0;i||(n=this.#Zt.get(e)||0,this.#Zt.set(e,n+1&65535));const a=r.length;let o=0;const c=[];do{const s=r.slice(o,o+1200),h=0===o,d=o+s.length>=a,l=this.#Qt;this.#Qt=this.#Qt+1>>>0;const{flags:u,body:f}=we({tsn:l,streamId:e,streamSeq:n,ppid:t,userData:s,unordered:i,beginning:h,ending:d}),p=Se(ge.DATA,u,f);this.#Jt.set(l,{chunk:p}),c.push(p),o+=s.length}while(o<a);for(const e of c)this.#nr(this.#Xt,[e])}#lr(e){const t={unordered:!!(4&(r=e.flags)),beginning:!!(2&r),ending:!!(1&r),tsn:(s=e.body).readUInt32BE(0),streamId:s.readUInt16BE(4),streamSeq:s.readUInt16BE(6),ppid:s.readUInt32BE(8),userData:s.slice(12)};var r,s;this.#Tr(t),this.#Sr()}#Tr(e){const t=this.#er+1>>>0;if(!Ue(e.tsn,t))if(e.tsn===t){this.#er=e.tsn,this.#yr(e);let t=this.#er+1>>>0;for(;this.#tr.has(t);){const e=this.#tr.get(t);this.#tr.delete(t),this.#er=t,this.#yr(e),t=this.#er+1>>>0}}else this.#tr.has(e.tsn)||this.#tr.set(e.tsn,e)}#yr(e){const t=`${e.streamId}:${e.unordered?"u":"o"}`;if(e.beginning&&e.ending)return void this.emit("message",{streamId:e.streamId,ppid:e.ppid,data:e.userData});let r=this.#rr.get(t);if(e.beginning)r={ppid:e.ppid,parts:[e.userData]},this.#rr.set(t,r);else{if(!r)return;r.parts.push(e.userData)}e.ending&&r&&(this.#rr.delete(t),this.emit("message",{streamId:e.streamId,ppid:r.ppid,data:Buffer.concat(r.parts)}))}#Sr(){const e=[];if(this.#tr.size>0){const t=[...this.#tr.keys()].sort((e,t)=>Ue(e,t)?-1:1),r=this.#er+1>>>0;let s=null,i=null;for(const n of t)null!==s?n!==i+1>>>0?(e.push([1+(s-r&65535),1+(i-r&65535)]),s=n,i=n):i=n:(s=n,i=n);null!==s&&e.push([1+(s-r&65535),1+(i-r&65535)])}const t=function({cumulativeTSNAck:e,a_rwnd:t,gapBlocks:r=[],dupTSNs:s=[]}){const i=Buffer.alloc(12+4*r.length+4*s.length);i.writeUInt32BE(e>>>0,0),i.writeUInt32BE(t>>>0,4),i.writeUInt16BE(r.length,8),i.writeUInt16BE(s.length,10);let n=12;for(const[e,t]of r)i.writeUInt16BE(e,n),i.writeUInt16BE(t,n+2),n+=4;for(const e of s)i.writeUInt32BE(e>>>0,n),n+=4;return i}({cumulativeTSNAck:this.#er>>>0,a_rwnd:Oe,gapBlocks:e}),r=Se(ge.SACK,0,t);this.#nr(this.#Xt,[r])}#ur(e){const t=function(e){const t=e.readUInt32BE(0),r=e.readUInt32BE(4),s=e.readUInt16BE(8),i=e.readUInt16BE(10),n=[];let a=12;for(let t=0;t<s;t++)n.push([e.readUInt16BE(a),e.readUInt16BE(a+2)]),a+=4;const o=[];for(let t=0;t<i;t++)o.push(e.readUInt32BE(a)),a+=4;return{cumulativeTSNAck:t,a_rwnd:r,gapBlocks:n,dupTSNs:o}}(e.body);for(const e of[...this.#Jt.keys()])ve(e,t.cumulativeTSNAck)&&this.#Jt.delete(e);const r=t.cumulativeTSNAck+1>>>0;for(const[e,s]of t.gapBlocks)for(let t=e;t<=s;t++)this.#Jt.delete(r+t-1>>>0)}#fr(e){const t=Se(ge.HEARTBEAT_ACK,0,e.body);this.#nr(this.#Xt,[t])}#Er(){const e=Se(ge.SHUTDOWN_ACK,0,Buffer.alloc(0));this.#nr(this.#Xt,[e]),this.#Ar()}#pr(e){this.#Ir(),this.state!==De.CLOSED&&(this.state=De.CLOSED,this.emit("error",new Error(e||"SCTP abort")),this.emit("close"))}shutdown(){if(this.state!==De.ESTABLISHED)return void this.#Ar();const e=Se(ge.SHUTDOWN,0,(()=>{const e=Buffer.alloc(4);return e.writeUInt32BE(this.#er>>>0,0),e})());this.#nr(this.#Xt,[e]),this.#Ar()}#Ar(){this.#Ir(),this.state!==De.CLOSED&&(this.state=De.CLOSED,this.emit("close"))}}const Le=Object.freeze({DATA_CHANNEL_ACK:2,DATA_CHANNEL_OPEN:3}),Pe=Object.freeze({RELIABLE:0,RELIABLE_UNORDERED:128,PARTIAL_RELIABLE_REXMIT:1,PARTIAL_RELIABLE_REXMIT_UNORDERED:129,PARTIAL_RELIABLE_TIMED:2,PARTIAL_RELIABLE_TIMED_UNORDERED:130});class _e extends t.EventEmitter{#Rr;#Br;#wr;constructor(e,t){super(),this.#Rr=e,this.#Br=new Map,this.#wr=t?0:1,this.#Rr.on("message",e=>this.#Nr(e))}openChannel(e,t={}){let r=e.id;if(null==r&&(r=this.#br(),e.emit(w.SET_ID,r)),this.#Br.set(r,{channel:e,acked:!1}),this.#Or(e,r,t),e.negotiated)this.#Br.get(r).acked=!0,e.emit(w.OPEN);else{const s=function({channelType:e,priority:t=0,reliabilityParameter:r=0,label:s="",protocol:i=""}){const n=Buffer.from(s,"utf8"),a=Buffer.from(i,"utf8"),o=Buffer.alloc(12+n.length+a.length);return o.writeUInt8(Le.DATA_CHANNEL_OPEN,0),o.writeUInt8(e,1),o.writeUInt16BE(t,2),o.writeUInt32BE(r>>>0,4),o.writeUInt16BE(n.length,8),o.writeUInt16BE(a.length,10),n.copy(o,12),a.copy(o,12+n.length),o}({channelType:this.#Dr(t),priority:0,reliabilityParameter:this.#Ur(t),label:e.label,protocol:t.protocol||e.protocol||""});this.#Rr.sendData(r,Ce.DCEP,s)}}#br(){let e=this.#wr;for(;this.#Br.has(e);)e+=2;return this.#wr=e+2,e}#Dr(e){const t=!1===e.ordered;return null!=e.maxRetransmits?t?Pe.PARTIAL_RELIABLE_REXMIT_UNORDERED:Pe.PARTIAL_RELIABLE_REXMIT:null!=e.maxPacketLifeTime?t?Pe.PARTIAL_RELIABLE_TIMED_UNORDERED:Pe.PARTIAL_RELIABLE_TIMED:t?Pe.RELIABLE_UNORDERED:Pe.RELIABLE}#Ur(e){return null!=e.maxRetransmits?e.maxRetransmits>>>0:null!=e.maxPacketLifeTime?e.maxPacketLifeTime>>>0:0}#Or(e,t,r){const s=!1===r.ordered;e.on(w.SEND,(e,r)=>{let i;i=r?0===e.length?Ce.BINARY_EMPTY:Ce.BINARY:0===e.length?Ce.STRING_EMPTY:Ce.STRING;const n=0===e.length?Buffer.from([0]):e;this.#Rr.sendData(t,i,n,{unordered:s})})}#Nr(e){if(e.ppid===Ce.DCEP)return void this.#vr(e);const t=this.#Br.get(e.streamId);if(!t)return;const r=e.ppid===Ce.BINARY||e.ppid===Ce.BINARY_EMPTY||e.ppid===Ce.BINARY_PARTIAL,s=e.ppid===Ce.STRING_EMPTY||e.ppid===Ce.BINARY_EMPTY?Buffer.alloc(0):e.data;t.channel.emit(w.RECEIVE,s,r)}#vr(e){const t=(r=e.data).length>0?r.readUInt8(0):-1;var r;if(t===Le.DATA_CHANNEL_OPEN){const t=function(e){const t=e.readUInt8(1),r=e.readUInt16BE(2),s=e.readUInt32BE(4),i=e.readUInt16BE(8),n=e.readUInt16BE(10);return{channelType:t,priority:r,reliabilityParameter:s,label:e.slice(12,12+i).toString("utf8"),protocol:e.slice(12+i,12+i+n).toString("utf8"),unordered:!!(128&t)}}(e.data);this.#Rr.sendData(e.streamId,Ce.DCEP,Buffer.from([Le.DATA_CHANNEL_ACK])),this.emit("open-request",{streamId:e.streamId,label:t.label,protocol:t.protocol,ordered:!t.unordered,channelType:t.channelType,reliabilityParameter:t.reliabilityParameter})}else if(t===Le.DATA_CHANNEL_ACK){const t=this.#Br.get(e.streamId);t&&!t.acked&&(t.acked=!0,t.channel.emit(w.OPEN))}}acceptChannel(e,t){e.emit(w.SET_ID,t.streamId),this.#Br.set(t.streamId,{channel:e,acked:!0}),this.#Or(e,t.streamId,{ordered:t.ordered}),e.emit(w.OPEN)}}class xe extends t.EventEmitter{#kr;ice;dtls;sctp;dcm;#Lr;constructor(e){super(),this.#kr=e,this.ice=new $({role:e.iceRole,localUfrag:e.localUfrag,localPwd:e.localPwd}),this.dtls=null,this.sctp=null,this.dcm=null,this.#Lr=!1,this.ice.on("candidate",e=>this.emit("candidate",e)),this.ice.on("error",e=>this.emit("error",e)),this.ice.on("failed",()=>this.emit("error",new Error("ICE failed"))),this.ice.on("data",e=>{this.dtls&&this.dtls.handlePacket(e)}),this.ice.on("connected",()=>{this.emit("iceconnected"),this.#Pr()})}async gather(e={}){await this.ice.gather(e)}getLocalCandidates(){return this.ice.getLocalCandidates()}setRemote(e,t){this.ice.setRemoteCredentials(e,t),this.ice.start()}addRemoteCandidate(e){this.ice.addRemoteCandidate(e)}#Pr(){this.#Lr||(this.#Lr=!0,this.dtls=new me({role:"client"===this.#kr.dtlsRole?pe.CLIENT:pe.SERVER,certDer:this.#kr.certDer,privateKey:this.#kr.privateKey,verifyFingerprint:this.#kr.verifyFingerprint,output:e=>{try{this.ice.send(e)}catch(e){this.emit("error",e)}}}),this.dtls.on("connect",()=>{this.emit("dtlsconnected"),this.#_r()}),this.dtls.on("data",e=>{this.sctp&&this.sctp.receivePacket(e)}),this.dtls.on("error",e=>this.emit("error",e)),this.dtls.on("close",()=>this.emit("close")),this.dtls.start())}#_r(){const e="client"===this.#kr.dtlsRole,t=new ke({isClient:e});this.sctp=t,t.on("output",e=>{try{this.dtls&&this.dtls.send(e)}catch(e){this.emit("error",e)}}),t.on("error",e=>this.emit("error",e)),t.on("close",()=>this.emit("close")),this.dcm=new _e(t,e),this.dcm.on("open-request",e=>this.emit("datachannel-request",e)),t.on("established",()=>{this.emit("sctpconnected"),this.emit("ready")}),t.start()}openChannel(e,t){if(!this.dcm)throw new Error("SCTP not ready");this.dcm.openChannel(e,t)}acceptChannel(e,t){if(!this.dcm)throw new Error("SCTP not ready");this.dcm.acceptChannel(e,t)}isReady(){return!!this.sctp&&"established"===this.sctp.state}close(){if(this.sctp)try{this.sctp.shutdown()}catch{}if(this.dtls)try{this.dtls.close()}catch{}if(this.ice)try{this.ice.close()}catch{}}}const He=Object.freeze({STABLE:"stable",HAVE_LOCAL_OFFER:"have-local-offer",HAVE_REMOTE_OFFER:"have-remote-offer",HAVE_LOCAL_PRANSWER:"have-local-pranswer",HAVE_REMOTE_PRANSWER:"have-remote-pranswer",CLOSED:"closed"}),Fe=Object.freeze({NEW:"new",GATHERING:"gathering",COMPLETE:"complete"}),Me=Object.freeze({NEW:"new",CONNECTING:"connecting",CONNECTED:"connected",DISCONNECTED:"disconnected",FAILED:"failed",CLOSED:"closed"});class Ke extends t.EventEmitter{#xr;#Hr;#Fr;#Mr;#Kr;#qr;#Gr;#$r;#jr;#zr;#Vr;#Wr;#Yr;#Xr;#Qr;#Br;#ue;constructor(e={}){super(),this.#xr=e,this.#Hr=He.STABLE,this.#Fr=Fe.NEW,this.#Mr=Me.NEW,this.#Kr=null,this.#qr=null,this.#Gr=null,this.#$r={usernameFragment:n.randomBytes(3).toString("base64").replace(/[^a-zA-Z0-9]/g,"").slice(0,4).padEnd(4,"x"),password:n.randomBytes(18).toString("base64").replace(/[^a-zA-Z0-9]/g,"").slice(0,24).padEnd(24,"x")},this.#jr=null,this.#zr=[],this.#Vr=null,this.#Wr=null,this.#Yr=!1,this.#Xr=!1,this.#Qr=[],this.#Br=new Set,this.#ue=[]}async#Zr(){return this.#Gr||(this.#xr.certificates&&this.#xr.certificates[0]?this.#Gr=this.#xr.certificates[0]:this.#Gr=await R.generateCertificate()),this.#Gr}#Jr(e,t){if(this.#Wr)return this.#Wr;const r=this.#Gr;if(!r)throw new Error("Certificate not initialized");const s=r.getCertificateDer();if(!s)throw new Error("Certificate has no DER encoding");const i=new xe({iceRole:e,dtlsRole:t,localUfrag:this.#$r.usernameFragment,localPwd:this.#$r.password,certDer:s,privateKey:r.getPrivateKeyObject(),verifyFingerprint:e=>this.#es(e)});return i.on("candidate",e=>{const t={candidate:e.sdp,sdpMid:"0",sdpMLineIndex:0,usernameFragment:this.#$r.usernameFragment};this.#ue.push(t),this.emit("icecandidate",{candidate:t})}),i.on("iceconnected",()=>this.#ts(Me.CONNECTING)),i.on("sctpconnected",()=>this.#ts(Me.CONNECTED)),i.on("error",e=>{this.emit("error",e),this.#ts(Me.FAILED)}),i.on("close",()=>this.#ts(Me.DISCONNECTED)),i.on("datachannel-request",e=>{const t=new N(e.label,{ordered:e.ordered,protocol:e.protocol,id:e.streamId});i.acceptChannel(t,e),this.#Br.add(t),this.emit("datachannel",{channel:t})}),i.on("ready",()=>{for(const{channel:e,init:t}of this.#Qr)i.openChannel(e,t);this.#Qr=[]}),this.#Wr=i,i}#es(e){return 0===this.#zr.length||this.#zr.some(t=>t.algorithm===e.algorithm&&t.value.toUpperCase()===e.value.toUpperCase())}createDataChannel(e,t={}){if(this.#Xr)throw new Error("RTCPeerConnection is closed");const r=new N(e,t);this.#Br.add(r);const s={ordered:!1!==t.ordered,maxRetransmits:t.maxRetransmits,maxPacketLifeTime:t.maxPacketLifeTime,protocol:t.protocol||"",negotiated:t.negotiated||!1};return this.#Wr&&this.#Wr.isReady()?this.#Wr.openChannel(r,s):this.#Qr.push({channel:r,init:s}),setImmediate(()=>{this.#Xr||this.emit("negotiationneeded")}),r}async createOffer(){if(this.#Xr)throw new Error("RTCPeerConnection is closed");await this.#Zr(),this.#Yr=!0;const e=this.#rs(),t=(r={iceUfrag:this.#$r.usernameFragment,icePwd:this.#$r.password,fingerprint:e,setup:"actpass",candidates:[]},D({...r,setup:r.setup||"actpass"}));var r;return new O({type:b.OFFER,sdp:t})}async createAnswer(){if(this.#Xr)throw new Error("RTCPeerConnection is closed");if(!this.#qr||"offer"!==this.#qr.type)throw new Error("Cannot create answer without remote offer");await this.#Zr();const e=this.#rs(),t=(r={iceUfrag:this.#$r.usernameFragment,icePwd:this.#$r.password,fingerprint:e,setup:"active",candidates:[]},D({...r,setup:r.setup||"active"}));var r;return new O({type:b.ANSWER,sdp:t})}#rs(){const e=this.#Gr;if(!e)throw new Error("Certificate not initialized");const t=e.getFingerprints();return t.find(e=>"sha-256"===e.algorithm)||t[0]}async setLocalDescription(e){if(this.#Xr)throw new Error("RTCPeerConnection is closed");const t=e||(this.#Hr===He.HAVE_REMOTE_OFFER?await this.createAnswer():await this.createOffer());await this.#Zr(),this.#Kr=new O({type:t.type??void 0,sdp:t.sdp??void 0}),"offer"===t.type?this.#Hr=He.HAVE_LOCAL_OFFER:"answer"===t.type&&(this.#Hr=He.STABLE),this.#ss(t,!0),this.#Fr=Fe.GATHERING,this.emit("icegatheringstatechange"),this.#Wr&&(await this.#Wr.gather({iceServers:this.#xr.iceServers||[],iceTransportPolicy:this.#xr.iceTransportPolicy||"all"}),this.#Fr=Fe.COMPLETE,this.emit("icegatheringstatechange"),this.emit("icecandidate",{candidate:null}),this.#is()),this.emit("signalingstatechange")}async setRemoteDescription(e){if(this.#Xr)throw new Error("RTCPeerConnection is closed");if(!e||!e.sdp)throw new Error("Invalid session description");await this.#Zr(),this.#qr=new O(e),"offer"===e.type?this.#Hr=He.HAVE_REMOTE_OFFER:"answer"===e.type&&(this.#Hr=He.STABLE),this.#jr=function(e){const t={usernameFragment:null,password:null};for(const r of e.split(/\r?\n/))r.startsWith("a=ice-ufrag:")?t.usernameFragment=r.slice(12).trim():r.startsWith("a=ice-pwd:")&&(t.password=r.slice(10).trim());return t}(e.sdp);const t=function(e){const t={role:"auto",fingerprints:[]};for(const r of e.split(/\r?\n/))if(r.startsWith("a=setup:")){const e=r.slice(8).trim();t.role="active"===e?"client":"passive"===e?"server":"actpass",t.setup=e}else if(r.startsWith("a=fingerprint:")){const e=r.slice(14).trim().split(/\s+/);2===e.length&&t.fingerprints.push({algorithm:e[0].toLowerCase(),value:e[1].toUpperCase()})}return t}(e.sdp);if(this.#zr=t.fingerprints,this.#Vr=t.setup??null,this.#ss(e,!1),this.#Wr&&this.#jr.usernameFragment){this.#Wr.setRemote(this.#jr.usernameFragment,this.#jr.password??"");for(const t of function(e){const t=[];for(const r of e.split(/\r?\n/)){if(!r.startsWith("a=candidate:"))continue;const e=U(r.slice(2));e&&t.push(e)}return t}(e.sdp))this.#Wr.addRemoteCandidate(t)}this.#is(),this.emit("signalingstatechange")}#ss(e,t){if(this.#Wr)return;const r=this.#Yr?"controlling":"controlled";let s;s=this.#Yr?"active"===this.#Vr?"server":"passive"===this.#Vr?"client":"server":"client",this.#Jr(r,s)}#is(){this.#Wr&&this.#jr&&this.#jr.usernameFragment&&this.#Wr.setRemote(this.#jr.usernameFragment,this.#jr.password??"")}async addIceCandidate(e){if(this.#Xr)throw new Error("RTCPeerConnection is closed");if(!e||"string"!=typeof e&&""===e.candidate)return;const t=U("string"==typeof e?e:e.candidate||"");t&&this.#Wr&&this.#Wr.addRemoteCandidate(t)}#ts(e){this.#Mr!==e&&(this.#Mr=e,this.emit("connectionstatechange"),this.emit("iceconnectionstatechange"))}getConfiguration(){return{...this.#xr}}setConfiguration(e){if(this.#Xr)throw new Error("RTCPeerConnection is closed");this.#xr={...e}}close(){if(!this.#Xr){this.#Xr=!0,this.#Hr=He.CLOSED;for(const e of this.#Br)try{e.close()}catch(e){}if(this.#Wr)try{this.#Wr.close()}catch(e){}this.#ts(Me.CLOSED),this.emit("signalingstatechange")}}get signalingState(){return this.#Hr}get iceGatheringState(){return this.#Fr}get iceConnectionState(){return this.#Mr===Me.CONNECTED?"connected":this.#Mr===Me.CONNECTING?"checking":this.#Mr===Me.FAILED?"failed":"new"}get connectionState(){return this.#Mr}get localDescription(){return this.#Kr}get remoteDescription(){return this.#qr}get currentLocalDescription(){return this.#Kr}get currentRemoteDescription(){return this.#qr}get pendingLocalDescription(){return this.#Hr===He.STABLE?null:this.#Kr}get pendingRemoteDescription(){return this.#Hr===He.STABLE?null:this.#qr}get canTrickleIceCandidates(){return!0}get sctp(){return this.#Wr?this.#Wr.sctp:null}}exports.ByteBufferQueue=class{#ns;#as;#os;constructor(){this.#ns=0,this.#as=[],this.#os=0}get size(){return this.#ns}get empty(){return 0===this.#ns}readInto(e){if(!Buffer.isBuffer(e))throw new TypeError("bufferOut must be a Buffer");let t=0,r=0;for(;r<e.length&&this.#as.length>0;){const s=this.#as[0],i=s.length-this.#os,n=e.length-r,a=Math.min(i,n);s.copy(e,r,this.#os,this.#os+a),t+=a,r+=a,a<i?this.#os+=a:(this.#as.shift(),this.#os=0)}return this.#ns-=t,this.#cs(),t}append(e){if(!Buffer.isBuffer(e))throw new TypeError("buffer must be a Buffer");0!==e.length&&(this.#ns+=e.length,this.#as.push(e),this.#cs())}clear(){this.#as=[],this.#os=0,this.#ns=0,this.#cs()}read(e){if(e>this.#ns)throw new RangeError(`Cannot read ${e} bytes, only ${this.#ns} available`);if(0===e)return Buffer.allocUnsafe(0);const t=Buffer.allocUnsafe(e),r=this.readInto(t);if(r!==e)throw new Error(`Internal error: read ${r} bytes, expected ${e}`);return t}peek(e=this.#ns){const t=Math.min(e,this.#ns);if(0===t)return Buffer.allocUnsafe(0);const r=Buffer.allocUnsafe(t);let s=0,i=0,n=this.#os;for(;s<t&&i<this.#as.length;){const e=this.#as[i],a=e.length-n,o=Math.min(a,t-s);e.copy(r,s,n,n+o),s+=o,i++,n=0}return r}#cs(){if("production"!==process.env.NODE_ENV){let e=0;for(const t of this.#as){if(0===t.length)throw new Error("Invariant violation: empty buffer in queue");e+=t.length}const t=e-this.#os;if(this.#ns!==t)throw new Error(`Invariant violation: size=${this.#ns}, expected=${t}`);if(0===this.#as.length){if(0!==this.#os)throw new Error("Invariant violation: offset non-zero with empty queue")}else if(this.#os>=this.#as[0].length)throw new Error("Invariant violation: offset >= front buffer size")}}},exports.RTCCertificate=R,exports.RTCDataChannel=N,exports.RTCDataChannelState=B,exports.RTCError=h,exports.RTCIceCandidate=d,exports.RTCIceGatheringState=Fe,exports.RTCPeerConnection=Ke,exports.RTCPeerConnectionState=Me,exports.RTCSdpType=b,exports.RTCSessionDescription=O,exports.RTCSignalingState=He,exports.version="2.0.5";
|
package/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as e from"crypto";import{EventEmitter as t}from"events";import*as r from"dgram";import*as s from"os";class i{#e;#t;#r;constructor(){this.#e=0,this.#t=[],this.#r=0}get size(){return this.#e}get empty(){return 0===this.#e}readInto(e){if(!Buffer.isBuffer(e))throw new TypeError("bufferOut must be a Buffer");let t=0,r=0;for(;r<e.length&&this.#t.length>0;){const s=this.#t[0],i=s.length-this.#r,n=e.length-r,a=Math.min(i,n);s.copy(e,r,this.#r,this.#r+a),t+=a,r+=a,a<i?this.#r+=a:(this.#t.shift(),this.#r=0)}return this.#e-=t,this.#s(),t}append(e){if(!Buffer.isBuffer(e))throw new TypeError("buffer must be a Buffer");0!==e.length&&(this.#e+=e.length,this.#t.push(e),this.#s())}clear(){this.#t=[],this.#r=0,this.#e=0,this.#s()}read(e){if(e>this.#e)throw new RangeError(`Cannot read ${e} bytes, only ${this.#e} available`);if(0===e)return Buffer.allocUnsafe(0);const t=Buffer.allocUnsafe(e),r=this.readInto(t);if(r!==e)throw new Error(`Internal error: read ${r} bytes, expected ${e}`);return t}peek(e=this.#e){const t=Math.min(e,this.#e);if(0===t)return Buffer.allocUnsafe(0);const r=Buffer.allocUnsafe(t);let s=0,i=0,n=this.#r;for(;s<t&&i<this.#t.length;){const e=this.#t[i],a=e.length-n,o=Math.min(a,t-s);e.copy(r,s,n,n+o),s+=o,i++,n=0}return r}#s(){if("production"!==process.env.NODE_ENV){let e=0;for(const t of this.#t){if(0===t.length)throw new Error("Invariant violation: empty buffer in queue");e+=t.length}const t=e-this.#r;if(this.#e!==t)throw new Error(`Invariant violation: size=${this.#e}, expected=${t}`);if(0===this.#t.length){if(0!==this.#r)throw new Error("Invariant violation: offset non-zero with empty queue")}else if(this.#r>=this.#t[0].length)throw new Error("Invariant violation: offset >= front buffer size")}}}const n=Object.freeze({NONE:"none",DATA_CHANNEL_FAILURE:"data-channel-failure",DTLS_FAILURE:"dtls-failure",FINGERPRINT_FAILURE:"fingerprint-failure",SCTP_FAILURE:"sctp-failure",SDP_SYNTAX_ERROR:"sdp-syntax-error",HARDWARE_ENCODER_NOT_AVAILABLE:"hardware-encoder-not-available",HARDWARE_ENCODER_ERROR:"hardware-encoder-error",INVALID_STATE:"invalid-state",INVALID_MODIFICATION:"invalid-modification",INVALID_ACCESS_ERROR:"invalid-access-error",OPERATION_ERROR:"operation-error"});class a extends Error{static DetailType=n;#i;#n;#a;#o;#c;#h;constructor(e={},t=""){super(t),this.name="RTCError",Error.captureStackTrace&&Error.captureStackTrace(this,a);const r=e.errorDetail||n.NONE;if("string"!=typeof r)throw new TypeError("errorDetail must be a string");this.#i=r,this.#n=this.#d(e.sdpLineNumber,"sdpLineNumber"),this.#a=this.#d(e.httpRequestStatusCode,"httpRequestStatusCode"),this.#o=this.#d(e.sctpCauseCode,"sctpCauseCode"),this.#c=this.#l(e.receivedAlert,"receivedAlert"),this.#h=this.#l(e.sentAlert,"sentAlert")}#d(e,t){if(null==e)return null;const r=Number(e);if(!Number.isInteger(r))throw new TypeError(`${t} must be an integer`);return r}#l(e,t){if(null==e)return null;const r=Number(e);if(!Number.isInteger(r)||r<0)throw new TypeError(`${t} must be an unsigned integer`);return r}get errorDetail(){return this.#i}get sdpLineNumber(){return this.#n}get httpRequestStatusCode(){return this.#a}get sctpCauseCode(){return this.#o}get receivedAlert(){return this.#c}get sentAlert(){return this.#h}toJSON(){const e={name:this.name,message:this.message,errorDetail:this.#i};return null!==this.#n&&(e.sdpLineNumber=this.#n),null!==this.#a&&(e.httpRequestStatusCode=this.#a),null!==this.#o&&(e.sctpCauseCode=this.#o),null!==this.#c&&(e.receivedAlert=this.#c),null!==this.#h&&(e.sentAlert=this.#h),e}static fromNative(e){const t={errorDetail:e.error_detail||n.NONE};return void 0!==e.sctp_cause_code&&(t.sctpCauseCode=e.sctp_cause_code),new a(t,e.message||"Unknown error")}}class o{#u;#f;#p;#m;#E;constructor(e={}){if(null===e.sdpMid&&null===e.sdpMLineIndex)throw new TypeError("sdpMid and sdpMLineIndex are both null");this.#u=e.candidate||"",this.#f=void 0!==e.sdpMid?e.sdpMid:null,this.#p=void 0!==e.sdpMLineIndex?e.sdpMLineIndex:null,this.#m=e.usernameFragment||null,this.#E=this.#g(this.#u)}#g(e){const t={foundation:null,component:null,protocol:null,priority:null,address:null,port:null,type:null,tcpType:null,relatedAddress:null,relatedPort:null};if(!e||!e.startsWith("candidate:"))return t;const r=e.substring(10).trim().split(/\s+/);if(r.length<8)return t;t.foundation=r[0],t.component=r[1],t.protocol=r[2].toLowerCase(),t.priority=parseInt(r[3],10),t.address=r[4],t.port=parseInt(r[5],10),"typ"===r[6]&&(t.type=r[7]);for(let e=8;e<r.length;e+=2){const s=r[e],i=r[e+1];"raddr"===s?t.relatedAddress=i:"rport"===s?t.relatedPort=parseInt(i,10):"tcptype"===s&&(t.tcpType=i)}return t}get candidate(){return this.#u}get sdpMid(){return this.#f}get sdpMLineIndex(){return this.#p}get usernameFragment(){return this.#m}get foundation(){return this.#E.foundation}get component(){return this.#E.component}get priority(){return this.#E.priority}get address(){return this.#E.address}get protocol(){return this.#E.protocol}get port(){return this.#E.port}get type(){return this.#E.type}get tcpType(){return this.#E.tcpType}get relatedAddress(){return this.#E.relatedAddress}get relatedPort(){return this.#E.relatedPort}toJSON(){const e={candidate:this.#u,sdpMid:this.#f,sdpMLineIndex:this.#p};return this.#m&&(e.usernameFragment=this.#m),e}static fromString(e,t=null,r=0){return new o({candidate:e,sdpMid:t,sdpMLineIndex:r})}static isValid(e){return!(!e||"string"!=typeof e)&&(!!e.startsWith("candidate:")&&e.substring(10).trim().split(/\s+/).length>=8)}}const c=Object.freeze({BOOLEAN:1,INTEGER:2,BIT_STRING:3,OCTET_STRING:4,NULL:5,OID:6,UTF8_STRING:12,PRINTABLE_STRING:19,IA5_STRING:22,UTC_TIME:23,GENERALIZED_TIME:24,SEQUENCE:48,SET:49});function h(e){if(e<128)return Buffer.from([e]);const t=[];let r=e;for(;r>0;)t.unshift(255&r),r>>>=8;return Buffer.from([128|t.length,...t])}function d(e,t){return Buffer.concat([Buffer.from([e]),h(t.length),t])}function l(e){let t=0;for(;t<e.length-1&&0===e[t];)t++;let r=e.slice(t);return 128&r[0]&&(r=Buffer.concat([Buffer.from([0]),r])),d(c.INTEGER,r)}function u(e){const t=[];let r=e;for(;r>0;)t.unshift(255&r),r=Math.floor(r/256);return 128&t[0]&&t.unshift(0),d(c.INTEGER,Buffer.from(t))}function f(e){const t=e.split(".").map(Number);if(t.length<2)throw new Error(`Invalid OID: ${e}`);const r=[40*t[0]+t[1]];for(let e=2;e<t.length;e++){let s=t[e];const i=[127&s];for(s=Math.floor(s/128);s>0;)i.unshift(127&s|128),s=Math.floor(s/128);r.push(...i)}return d(c.OID,Buffer.from(r))}function p(e){return d(c.SEQUENCE,Buffer.concat(e))}function m(e){const t=e.getUTCFullYear(),r=(e,t=2)=>String(e).padStart(t,"0"),s=r(e.getUTCMonth()+1),i=r(e.getUTCDate()),n=r(e.getUTCHours()),a=r(e.getUTCMinutes()),o=r(e.getUTCSeconds());if(t<2050){const e=r(t%100);return d(c.UTC_TIME,Buffer.from(`${e}${s}${i}${n}${a}${o}Z`,"ascii"))}return d(c.GENERALIZED_TIME,Buffer.from(`${t}${s}${i}${n}${a}${o}Z`,"ascii"))}const E=Object.freeze({ecPublicKey:"1.2.840.10045.2.1",prime256v1:"1.2.840.10045.3.1.7",ecdsaWithSHA256:"1.2.840.10045.4.3.2",commonName:"2.5.4.3"});function g(){return p([f(E.ecdsaWithSHA256)])}function I(t,r="sha-256"){const s=r.replace("-","").toLowerCase();return e.createHash(s).update(t).digest("hex").toUpperCase().match(/.{2}/g).join(":")}function T(t={}){const{name:r,days:s=30}=t,{certDer:i,privateKey:n,publicKey:a,notAfter:o}=function(t={}){const r=t.commonName||`WebRTC-${e.randomBytes(8).toString("hex")}`,s=t.days||30,{publicKey:i,privateKey:n}=e.generateKeyPairSync("ec",{namedCurve:"prime256v1"}),a=i.export({type:"spki",format:"der"}),o=t.notBefore||new Date(Date.now()-864e5),h=new Date(o.getTime()+24*s*60*60*1e3),I=e.randomBytes(20);I[0]&=127,0===I[0]&&(I[0]=1);const T=function(e){const t=p([f(E.commonName),(r=e,d(c.UTF8_STRING,Buffer.from(r,"utf8")))]);var r,s;return p([(s=[t],d(c.SET,Buffer.concat(s)))])}(r),C=p([(S=u(2),d(160,S)),l(I),g(),T,p([m(o),m(h)]),T,a]);var S;const y=e.sign("sha256",C,n);var A;return{certDer:p([C,g(),(A=y,d(c.BIT_STRING,Buffer.concat([Buffer.from([0]),A])))]),privateKey:n,publicKey:i,notBefore:o,notAfter:h}}({commonName:r,days:s});return{certDer:i,privateKey:n,publicKey:a,expires:o.getTime(),hash:"sha256"}}function C(e,t="sha-256"){return I(e,t)}class S{#I;#T;#C;#S;#y;constructor(e){this.#I=e.certDer||null,this.#T=e.privateKey,this.#C=e.publicKey,this.#S=e.expires,this.#y=null}getCertificateDer(){return this.#I}get expires(){return this.#S}getFingerprints(){if(!this.#I)throw new Error("Certificate has no DER encoding; cannot compute fingerprint");if(!this.#y){const e=this.#I,t=["sha-256","sha-384","sha-512"];this.#y=t.map(t=>({algorithm:t,value:C(e,t)}))}return this.#y.map(e=>({...e}))}getPrivateKeyObject(){return this.#A(this.#T,"private")}#A(t,r){return t&&"object"==typeof t&&t.type?t:"private"===r?e.createPrivateKey(t):e.createPublicKey(t)}getPrivateKey(){return this.#A(this.#T,"private").export({type:"pkcs8",format:"pem"})}getPublicKey(){return this.#A(this.#C,"public").export({type:"spki",format:"pem"})}toPEM(){const e=this.#I?`-----BEGIN CERTIFICATE-----\n${this.#I.toString("base64").match(/.{1,64}/g).join("\n")}\n-----END CERTIFICATE-----\n`:this.getPublicKey();return{pemPrivateKey:this.getPrivateKey(),pemCertificate:e}}isExpired(){return Date.now()>this.#S}static async generateCertificate(e={}){return new Promise((t,r)=>{try{let s;if(e.expires)s=e.expires;else{const t=e.days||30;s=Date.now()+24*t*60*60*1e3}setImmediate(()=>{try{const r=T({name:e.name||"webrtc",days:Math.ceil((s-Date.now())/864e5),hash:e.hash||"sha256"});r.expires=s;const i=new S(r);t(i)}catch(e){r(e)}})}catch(e){r(e)}})}static fromPEM(t,r,s){if("string"!=typeof t||0===t.length)throw new TypeError("pemPrivateKey must be a non-empty string");if("string"!=typeof r||0===r.length)throw new TypeError("pemCertificate must be a non-empty string");const i=s||Date.now()+2592e6;let n=null,a=r;const o=r.match(/-----BEGIN CERTIFICATE-----([\s\S]+?)-----END CERTIFICATE-----/);return o&&(n=Buffer.from(o[1].replace(/\s/g,""),"base64"),a=e.createPublicKey(e.createPrivateKey(t))),new S({certDer:n,privateKey:t,publicKey:a,expires:i,hash:"sha256"})}static isSupportedKeyParams(e){if(!e||"object"!=typeof e)return!1;if("RSA"===e.type){const t=e.rsaModulusLength||2048;return t>=1024&&t<=4096}if("ECDSA"===e.type){const t=e.namedCurve;return["P-256","P-384","P-521"].includes(t)}return!1}}const y=Object.freeze({CONNECTING:"connecting",OPEN:"open",CLOSING:"closing",CLOSED:"closed"}),A=Object.freeze({SEND:Symbol("rtcdatachannel:send"),RECEIVE:Symbol("rtcdatachannel:receive"),OPEN:Symbol("rtcdatachannel:open"),SET_ID:Symbol("rtcdatachannel:setId")});class B extends t{#B;#R;#w;#N;#b;#O;#U;#D;#L;#k;#v;#_;constructor(e,t={}){if(super(),"string"!=typeof e)throw new TypeError("label must be a string");this.#B=e,this.#R=void 0===t.ordered||t.ordered,this.#w=t.maxPacketLifeTime||null,this.#N=t.maxRetransmits||null,this.#b=t.protocol||"",this.#O=t.negotiated||!1,this.#U=void 0!==t.id?t.id:null,this.#D=y.CONNECTING,this.#L=0,this.#k=0,this.#v="arraybuffer",this.#_=!1,this.on(A.SET_ID,e=>{this.#U=e}),this.on(A.OPEN,()=>{this.#_=!0,this.#P(y.OPEN)}),this.on(A.RECEIVE,(e,t)=>{this.#H(e,t)})}get label(){return this.#B}get ordered(){return this.#R}get maxPacketLifeTime(){return this.#w}get maxRetransmits(){return this.#N}get protocol(){return this.#b}get negotiated(){return this.#O}get id(){return this.#U}get readyState(){return this.#D}get bufferedAmount(){return this.#L}get bufferedAmountLowThreshold(){return this.#k}set bufferedAmountLowThreshold(e){this.#k=e}get binaryType(){return this.#v}set binaryType(e){if("arraybuffer"!==e&&"blob"!==e)throw new TypeError('binaryType must be "arraybuffer" or "blob"');this.#v=e}get reliable(){return this.#R&&null===this.#w&&null===this.#N}send(e){if(this.#D!==y.OPEN)throw new Error('RTCDataChannel.readyState is not "open"');let t,r,s=0;if("string"==typeof e)t=Buffer.from(e,"utf8"),s=t.length,r=!1;else if(e instanceof ArrayBuffer)t=Buffer.from(e),s=e.byteLength,r=!0;else if(ArrayBuffer.isView(e))t=Buffer.from(e.buffer,e.byteOffset,e.byteLength),s=e.byteLength,r=!0;else{if(!Buffer.isBuffer(e))throw e&&"function"==typeof e.arrayBuffer?new Error("Blob sending not yet implemented"):new TypeError("Invalid data type");t=e,s=e.length,r=!0}if(!this.#_)throw new Error("Data channel not connected to a transport");this.#L+=s;try{this.emit(A.SEND,t,r),this.#L=Math.max(0,this.#L-s),this.#x()}catch(e){throw this.#L=Math.max(0,this.#L-s),this.emit("error",e),e}}#x(){this.#L<=this.#k&&this.emit("bufferedamountlow")}close(){this.#D!==y.CLOSING&&this.#D!==y.CLOSED&&(this.#P(y.CLOSING),setImmediate(()=>{this.#D===y.CLOSING&&this.#P(y.CLOSED)}))}#P(e){this.#D!==e&&(this.#D=e,e===y.OPEN?this.emit("open"):e===y.CLOSING?this.emit("closing"):e===y.CLOSED&&this.emit("close"))}#H(e,t){let r;r=t?"arraybuffer"===this.#v?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):e:e.toString("utf8"),this.emit("message",{data:r})}}const R=Object.freeze({OFFER:"offer",PRANSWER:"pranswer",ANSWER:"answer",ROLLBACK:"rollback"});class w{#F;#M;constructor(e={}){if(this.#F=e.type||null,this.#M=e.sdp||null,this.#F&&!Object.values(R).includes(this.#F))throw new TypeError(`Invalid SDP type: ${this.#F}`)}get type(){return this.#F}set type(e){if(e&&!Object.values(R).includes(e))throw new TypeError(`Invalid SDP type: ${e}`);this.#F=e}get sdp(){return this.#M}set sdp(e){this.#M=e}toJSON(){return{type:this.#F,sdp:this.#M}}}function N(t){const{iceUfrag:r,icePwd:s,fingerprint:i,setup:n="actpass",candidates:a=[],sctpPort:o=5e3,maxMessageSize:c=262144}=t,h=[];h.push("v=0");const d=e.randomBytes(4).readUInt32BE(0);h.push(`o=- ${d} 2 IN IP4 127.0.0.1`),h.push("s=-"),h.push("t=0 0"),h.push("a=group:BUNDLE 0"),h.push("a=msid-semantic: WMS"),h.push("m=application 9 UDP/DTLS/SCTP webrtc-datachannel"),h.push("c=IN IP4 0.0.0.0"),h.push("a=ice-ufrag:"+r),h.push("a=ice-pwd:"+s),h.push("a=ice-options:trickle"),i&&h.push(`a=fingerprint:${i.algorithm} ${i.value}`),h.push(`a=setup:${n}`),h.push("a=mid:0"),h.push("a=sctp-port:"+o),h.push("a=max-message-size:"+c);for(const e of a){const t=e.sdp||e.candidate;t&&h.push("a="+(t.startsWith("candidate:")?t:"candidate:"+t))}return h.join("\r\n")+"\r\n"}function b(e){const t=(e.startsWith("candidate:")?e.slice(10):e).split(/\s+/);return t.length<8?null:{candidate:e.startsWith("candidate:")?e:"candidate:"+e,foundation:t[0],component:parseInt(t[1],10),protocol:t[2].toLowerCase(),priority:parseInt(t[3],10)>>>0,address:t[4],port:parseInt(t[5],10),type:t[7]}}const O=554869826,U=Object.freeze({BINDING_REQUEST:1,BINDING_SUCCESS:257,BINDING_ERROR:273}),D=Object.freeze({MAPPED_ADDRESS:1,USERNAME:6,MESSAGE_INTEGRITY:8,ERROR_CODE:9,XOR_MAPPED_ADDRESS:32,PRIORITY:36,USE_CANDIDATE:37,FINGERPRINT:32808,ICE_CONTROLLED:32809,ICE_CONTROLLING:32810});function L(e){return e+3&-4}const k=(()=>{const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)r=1&r?3988292384^r>>>1:r>>>1;e[t]=r>>>0}return e})();class v{type;transactionId;attrs;constructor(t,r){this.type=t,this.transactionId=r||e.randomBytes(12),this.attrs=[]}addAttr(e,t){return this.attrs.push({type:e,value:t}),this}addUsername(e){return this.addAttr(D.USERNAME,Buffer.from(e,"utf8"))}addPriority(e){const t=Buffer.alloc(4);return t.writeUInt32BE(e>>>0,0),this.addAttr(D.PRIORITY,t)}addIceControlling(e){return this.addAttr(D.ICE_CONTROLLING,e)}addIceControlled(e){return this.addAttr(D.ICE_CONTROLLED,e)}addUseCandidate(){return this.addAttr(D.USE_CANDIDATE,Buffer.alloc(0))}addXorMappedAddress(e,t){return this.addAttr(D.XOR_MAPPED_ADDRESS,function(e,t){const r=Buffer.alloc(8);r.writeUInt8(0,0),r.writeUInt8(1,1),r.writeUInt16BE(8466^t,2);const s=e.split(".").map(Number),i=(s[0]<<24|s[1]<<16|s[2]<<8|s[3])>>>0;return r.writeUInt32BE((i^O)>>>0,4),r}(e,t,this.transactionId))}#K(){const e=[];for(const t of this.attrs){const r=Buffer.alloc(4);r.writeUInt16BE(t.type,0),r.writeUInt16BE(t.value.length,2);const s=Buffer.alloc(L(t.value.length));t.value.copy(s,0),e.push(r,s)}return Buffer.concat(e)}#G(e){const t=Buffer.alloc(20);return t.writeUInt16BE(this.type,0),t.writeUInt16BE(e,2),t.writeUInt32BE(O,4),this.transactionId.copy(t,8),t}build(t){let r=this.#K();if(t){const s=r.length+24,i=this.#G(s),n=e.createHmac("sha1",Buffer.from(t,"utf8")).update(Buffer.concat([i,r])).digest(),a=Buffer.alloc(4);a.writeUInt16BE(D.MESSAGE_INTEGRITY,0),a.writeUInt16BE(20,2),r=Buffer.concat([r,a,n])}const s=r.length+8,i=this.#G(s),n=(1398035790^function(e){let t=4294967295;for(let r=0;r<e.length;r++)t=k[255&(t^e[r])]^t>>>8;return(4294967295^t)>>>0}(Buffer.concat([i,r])))>>>0,a=Buffer.alloc(8);return a.writeUInt16BE(D.FINGERPRINT,0),a.writeUInt16BE(4,2),a.writeUInt32BE(n,4),r=Buffer.concat([r,a]),Buffer.concat([this.#G(r.length),r])}}const _=554869826;class P extends t{#q;#$;#z;#j;#V;#W;#Y;#X;constructor(e){super(),this.#q=e.server,this.#$=e.port,this.#z=e.username,this.#j=e.credential,this.#V=null,this.#W=new Map,this.#Y=null,this.#X=null}async connect(){if(!this.#V)return new Promise((e,t)=>{const s=r.createSocket("udp4");this.#V=s,s.on("message",(e,t)=>{this.#Q(e,t)}),s.on("error",e=>{console.error("STUN socket error:",e),t(e)}),s.bind(()=>{e()})})}async getReflexiveAddress(){await this.connect();const t=e.randomBytes(12),r=this.#Z(t);return new Promise((e,s)=>{const i=setTimeout(()=>{this.#W.delete(t.toString("hex")),s(new Error("STUN request timeout"))},5e3);this.#W.set(t.toString("hex"),{resolve:t=>{clearTimeout(i),e(t)},reject:e=>{clearTimeout(i),s(e)}}),this.#V.send(r,this.#$,this.#q,e=>{e&&(clearTimeout(i),this.#W.delete(t.toString("hex")),s(e))})})}async allocateRelay(t=600){if(!this.#z||!this.#j)throw new Error("TURN requires username and credential");await this.connect();let r=e.randomBytes(12),s=this.#J(r,t);try{return await this.#ee(s,r,"allocate")}catch(i){if(i instanceof Error&&i.message.includes("401")&&this.#Y&&this.#X)return r=e.randomBytes(12),s=this.#J(r,t,!0),await this.#ee(s,r,"allocate");throw i}}async refreshAllocation(t=600){if(!this.#z||!this.#j)throw new Error("TURN requires username and credential");return this.#te("refresh",()=>{const r=e.randomBytes(12);return{transactionId:r,request:this.#re(r,t)}})}async#te(e,t){const r=t();try{return await this.#ee(r.request,r.transactionId,e)}catch(r){if(r instanceof Error&&r.message.includes("401")&&this.#Y&&this.#X){const r=t();return this.#ee(r.request,r.transactionId,e)}throw r}}async createPermission(t){if(!this.#z||!this.#j)throw new Error("TURN requires username and credential");await this.#te("createPermission",()=>{const r=e.randomBytes(12);return{transactionId:r,request:this.#se(r,t)}})}async sendIndication(t,r,s){if(!this.#z||!this.#j)throw new Error("TURN requires username and credential");const i=e.randomBytes(12),n=this.#ie(i,t,r,s);return new Promise((e,t)=>{this.#V.send(n,this.#$,this.#q,r=>{r?t(r):e()})})}#ee(e,t,r){return new Promise((s,i)=>{const n=setTimeout(()=>{this.#W.delete(t.toString("hex")),i(new Error(`${r} request timeout`))},5e3);this.#W.set(t.toString("hex"),{type:r,resolve:e=>{clearTimeout(n),s(e)},reject:e=>{clearTimeout(n),i(e)}}),this.#V.send(e,this.#$,this.#q,e=>{e&&(clearTimeout(n),this.#W.delete(t.toString("hex")),i(e))})})}#Z(e){const t=Buffer.alloc(20);return t.writeUInt16BE(1,0),t.writeUInt16BE(0,2),t.writeUInt32BE(_,4),e.copy(t,8),t}#J(e,t,r=!1){const s=[],i=Buffer.alloc(8);i.writeUInt16BE(25,0),i.writeUInt16BE(4,2),i.writeUInt8(17,4),s.push(i);const n=Buffer.alloc(8);if(n.writeUInt16BE(13,0),n.writeUInt16BE(4,2),n.writeUInt32BE(t,4),s.push(n),r&&this.#Y&&this.#X){const e=this.#ne(6,this.#z);s.push(e);const t=this.#ne(20,this.#Y);s.push(t);const r=this.#ne(21,this.#X);s.push(r)}return this.#ae(3,e,s,r)}#se(e,t){const r=[],s=this.#oe(t,0,e);return r.push(s),this.#Y&&this.#X&&(r.push(this.#ne(6,this.#z)),r.push(this.#ne(20,this.#Y)),r.push(this.#ne(21,this.#X))),this.#ae(8,e,r,!0)}#ie(e,t,r,s){const i=[],n=this.#oe(t,r,e);i.push(n);const a=Buffer.alloc(4+s.length+(4-s.length%4)%4);return a.writeUInt16BE(19,0),a.writeUInt16BE(s.length,2),s.copy(a,4),i.push(a),this.#ae(22,e,i,!1)}#oe(e,t,r){const s=Buffer.alloc(12);s.writeUInt16BE(18,0),s.writeUInt16BE(8,2),s.writeUInt8(0,4),s.writeUInt8(1,5);const i=8466^t;s.writeUInt16BE(i,6);const n=e.split(".").map(Number),a=(n[0]<<24|n[1]<<16|n[2]<<8|n[3])^_;return s.writeUInt32BE(a>>>0,8),s}#re(e,t){const r=[],s=Buffer.alloc(8);s.writeUInt16BE(13,0),s.writeUInt16BE(4,2),s.writeUInt32BE(t,4),r.push(s);const i=this.#ne(6,this.#z);if(r.push(i),this.#Y){const e=this.#ne(20,this.#Y);r.push(e)}if(this.#X){const e=this.#ne(21,this.#X);r.push(e)}return this.#ae(4,e,r,!0)}#ae(t,r,s,i=!1){let n=Buffer.concat(s);if(i&&this.#j){const s=Buffer.alloc(20);s.writeUInt16BE(t,0),s.writeUInt16BE(n.length+24,2),s.writeUInt32BE(_,4),r.copy(s,8);const i=Buffer.concat([s,n]);let a=this.#j;if(this.#z&&this.#Y){const t=`${this.#z}:${this.#Y}:${this.#j}`;a=e.createHash("md5").update(t).digest()}const o=e.createHmac("sha1",a);o.update(i);const c=o.digest(),h=Buffer.alloc(4+c.length);h.writeUInt16BE(8,0),h.writeUInt16BE(c.length,2),c.copy(h,4),n=Buffer.concat([n,h])}const a=Buffer.alloc(20);return a.writeUInt16BE(t,0),a.writeUInt16BE(n.length,2),a.writeUInt32BE(_,4),r.copy(a,8),Buffer.concat([a,n])}#ne(e,t){const r=Buffer.from(t,"utf8"),s=r.length,i=(4-s%4)%4,n=Buffer.alloc(4+s+i);return n.writeUInt16BE(e,0),n.writeUInt16BE(s,2),r.copy(n,4),n}#Q(e,t){if(e.length<20)return;const r=e.readUInt16BE(0),s=e.readUInt16BE(2),i=e.readUInt32BE(4),n=e.slice(8,20);if(i!==_)return;if(23===r){const t=this.#ce(e.slice(20,20+s),n);if(t.xorPeerAddress&&t.data){const e={address:t.xorPeerAddress.address,port:t.xorPeerAddress.port,family:t.xorPeerAddress.family||"IPv4"};this.emit("data",t.data,e)}return}const a=n.toString("hex"),o=this.#W.get(a);if(!o)return;const c=this.#ce(e.slice(20,20+s),n);if(257===r)c.xorMappedAddress?o.resolve({address:c.xorMappedAddress.address,port:c.xorMappedAddress.port,family:c.xorMappedAddress.family}):c.mappedAddress?o.resolve({address:c.mappedAddress.address,port:c.mappedAddress.port,family:c.mappedAddress.family}):o.reject(new Error("No mapped address in STUN response")),this.#W.delete(a);else if(259===r)c.xorRelayedAddress?o.resolve({relayedAddress:c.xorRelayedAddress.address,relayedPort:c.xorRelayedAddress.port,lifetime:c.lifetime||600,type:"relay"}):o.reject(new Error("No relayed address in ALLOCATE response")),this.#W.delete(a);else if(260===r)o.resolve({lifetime:c.lifetime||600}),this.#W.delete(a);else if(264===r||265===r)o.resolve({ok:!0}),this.#W.delete(a);else if(!(272&~r)){c.realm&&(this.#Y=c.realm),c.nonce&&(this.#X=c.nonce);const e=c.errorCode||"Unknown error";o.reject(new Error(`STUN error: ${e}`)),this.#W.delete(a)}}#ce(e,t){const r={};let s=0;for(;s<e.length&&!(s+4>e.length);){const i=e.readUInt16BE(s),n=e.readUInt16BE(s+2);if(s+=4,s+n>e.length)break;const a=e.slice(s,s+n);switch(i){case 32:r.xorMappedAddress=this.#he(a,t);break;case 22:r.xorRelayedAddress=this.#he(a,t);break;case 18:r.xorPeerAddress=this.#he(a,t);break;case 19:r.data=a;break;case 1:r.mappedAddress=this.#de(a);break;case 13:r.lifetime=a.readUInt32BE(0);break;case 9:r.errorCode=this.#le(a);break;case 20:r.realm=a.toString("utf8"),this.#Y=r.realm;break;case 21:r.nonce=a.toString("utf8"),this.#X=r.nonce}s+=n,s+=(4-n%4)%4}return r}#he(e,t){const r=e.readUInt8(1),s=8466^e.readUInt16BE(2);if(1===r){const t=e.readUInt32BE(4)^_;return{family:"IPv4",port:s,address:[t>>24&255,t>>16&255,t>>8&255,255&t].join(".")}}return null}#de(e){const t=e.readUInt8(1),r=e.readUInt16BE(2);if(1===t){const t=e.slice(4,8);return{family:"IPv4",port:r,address:Array.from(t).join(".")}}return null}#le(e){return`${100*(7&e.readUInt8(2))+e.readUInt8(3)} ${e.slice(4).toString("utf8")}`}close(){this.#V&&(this.#V.close(),this.#V=null),this.#W.clear()}}const H={host:126,srflx:100,prflx:110,relay:0};function x(e){const t=e.match(/^(stuns?|turns?):\/?\/?([^:?]+):?(\d+)?(?:\?(.+))?$/);if(!t)return null;const r=t[1],s=t[2],i={};if(t[4])for(const e of t[4].split("&")){if(!e)continue;const t=e.indexOf("=");-1===t?i[e]=!0:i[e.slice(0,t)]=e.slice(t+1)}const n="turns"===r||"stuns"===r?5349:3478;return{scheme:r,protocol:r,host:s,port:parseInt(t[3]||String(n),10),transport:"string"==typeof i.transport?i.transport:"udp",params:i}}class F{kind;#V;onMessage;constructor(e){this.kind="host",this.#V=e,this.onMessage=null,e.on("message",(e,t)=>{this.onMessage&&this.onMessage(e,{address:t.address,port:t.port})})}send(e,t,r){this.#V.send(e,r,t)}close(){try{this.#V.close()}catch(e){}}}class M{kind;#ue;onMessage;#fe;constructor(e){this.kind="relay",this.#ue=e,this.onMessage=null,this.#fe=new Set,e.on("data",(e,t)=>{this.onMessage&&this.onMessage(e,{address:t.address,port:t.port})})}send(e,t,r){const s=`${t}:${r}`;this.#fe.has(s)?this.#ue.sendIndication(t,r,e).catch(()=>{}):(this.#fe.add(s),this.#ue.createPermission(t).then(()=>this.#ue.sendIndication(t,r,e)).catch(()=>{}))}close(){try{this.#ue.close()}catch(e){}}}class K extends t{role;localUfrag;localPwd;remoteUfrag;remotePwd;#pe;#me;#Ee;#ge;#Ie;#Te;#Ce;#Se;#ye;#_;#Ae;constructor(t){super(),this.role=t.role,this.localUfrag=t.localUfrag,this.localPwd=t.localPwd,this.remoteUfrag=null,this.remotePwd=null,this.#pe=e.randomBytes(8),this.#me=[],this.#Ee=[],this.#ge=[],this.#Ie=[],this.#Te=null,this.#Ce=!1,this.#Se=null,this.#ye=null,this.#_=!1,this.#Ae=new Map}async gather(e={}){const t=e.iceServers||[],r="relay"===e.iceTransportPolicy,s=await this.#Be();for(const e of t){const t=Array.isArray(e.urls)?e.urls:[e.urls];for(const i of t){const t=x(i);if(t&&"udp"===t.transport)try{"stun"!==t.scheme||r?"turn"!==t.scheme&&"turns"!==t.scheme||await this.#Re(t,e):await this.#we(t,s[0])}catch(e){this.emit("gathererror",{url:i,error:e instanceof Error?e.message:String(e)})}}}r&&(this.#Ee=this.#Ee.filter(e=>"relay"===e.type)),this.emit("gatheringcomplete")}async#Be(){const e=s.networkInterfaces(),t=[];for(const r of Object.values(e))if(r)for(const e of r)"IPv4"!==e.family||e.internal||t.push(e.address);0===t.length&&t.push("127.0.0.1");const r=[];for(const e of t)r.push(await this.#Ne(e));return r}#Ne(e){return new Promise((t,s)=>{const i=r.createSocket("udp4");i.on("error",e=>this.emit("error",e)),i.bind(0,e,()=>{const{port:r}=i.address(),s=new F(i);s.onMessage=(e,t)=>this.#be(s,e,t),this.#me.push(s);const n=this.#Oe("host",e,r,s);t({socket:i,address:e,port:r,transport:s,candidate:n})})})}async#we(e,t){if(!t)return;const r=new P({server:e.host,port:e.port});try{const e=await r.getReflexiveAddress();this.#Oe("srflx",e.address,e.port,t.transport,{relatedAddress:t.address,relatedPort:t.port})}finally{r.close()}}async#Re(e,t){if(!t.username||!t.credential)throw new Error("TURN server requires username and credential");const r=new P({server:e.host,port:e.port,username:t.username,credential:t.credential,transport:e.transport}),s=await r.allocateRelay(600),i=new M(r);i.onMessage=(e,t)=>this.#be(i,e,t),this.#me.push(i),this.#Oe("relay",s.relayedAddress,s.relayedPort,i,{relatedAddress:e.host,relatedPort:e.port})}#Oe(t,r,s,i,n={}){const a=e.createHash("md5").update(`${t}:${r}:${i.kind}`).digest("hex").slice(0,8),o=function(e,t=65535,r=1){return(H[e]<<24)+(t<<8)+(256-r)>>>0}(t);let c=`candidate:${a} 1 udp ${o} ${r} ${s} typ ${t}`;n.relatedAddress&&(c+=` raddr ${n.relatedAddress} rport ${n.relatedPort}`);const h={foundation:a,component:1,protocol:"udp",priority:o,address:r,port:s,type:t,transport:i,sdp:c};return this.#Ee.push(h),this.emit("candidate",h),h}getLocalCandidates(){return this.#Ee.slice()}setRemoteCredentials(e,t){this.remoteUfrag=e,this.remotePwd=t}addRemoteCandidate(e){e&&e.address&&e.port&&("string"==typeof e.address&&e.address.endsWith(".local")||(this.#ge.push(e),this.#Ue(),!this.#Se&&this.remotePwd&&this.#De()))}start(){this.remotePwd&&this.#ge.length>0&&this.#De()}#Ue(){for(const e of this.#Ee)for(const t of this.#ge){const r=`${e.type}:${e.address}:${e.port}->${t.address}:${t.port}`;this.#Ie.find(e=>e.key===r)||this.#Ie.push({key:r,local:e,remote:t,state:"frozen",nominated:!1})}}#De(){this.#Se||this.#Ce||(this.#Se=setInterval(()=>this.#Le(),50),this.#Se.unref&&this.#Se.unref(),this.#ye=setTimeout(()=>{this.#_||this.emit("failed"),this.#ke()},1e4),this.#ye.unref&&this.#ye.unref(),this.#Le())}#ke(){this.#Se&&(clearInterval(this.#Se),this.#Se=null),this.#ye&&(clearTimeout(this.#ye),this.#ye=null)}#Le(){if(!this.#Ce)for(const e of this.#Ie)"succeeded"!==e.state&&this.#ve(e)}#ve(t){const r=e.randomBytes(12),s=`${this.remoteUfrag}:${this.localUfrag}`,i=new v(U.BINDING_REQUEST,r).addUsername(s).addPriority(t.local.priority);"controlling"===this.role?(i.addIceControlling(this.#pe),i.addUseCandidate()):i.addIceControlled(this.#pe);const n=i.build(this.remotePwd??void 0);this.#Ae.set(r.toString("hex"),t),t.state="in-progress",t.local.transport.send(n,t.remote.address,t.remote.port)}#be(e,t,r){0!==t.length&&(t[0]<=3?this.#_e(e,t,r):this.emit("data",t,{transport:e,address:r.address,port:r.port}))}#_e(e,t,r){const s=function(e){if(e.length<20)return null;if(e.readUInt32BE(4)!==O)return null;const t=e.readUInt16BE(0),r=e.readUInt16BE(2);if(20+r>e.length)return null;const s=e.slice(8,20),i=new Map;let n=20;const a=20+r;for(;n+4<=a;){const t=e.readUInt16BE(n),r=e.readUInt16BE(n+2);if(n+=4,n+r>a)break;i.set(t,e.slice(n,n+r)),n+=L(r)}return{type:t,transactionId:s,attrs:i,raw:e}}(t);s&&(s.type===U.BINDING_REQUEST?this.#Pe(e,s,r):s.type===U.BINDING_SUCCESS&&this.#He(e,s,r))}#Pe(t,r,s){if(this.localPwd&&!function(t,r){let s=20;const i=20+t.readUInt16BE(2);let n=-1;for(;s+4<=i;){const e=t.readUInt16BE(s),r=t.readUInt16BE(s+2);if(e===D.MESSAGE_INTEGRITY){n=s;break}s+=4+L(r)}if(n<0)return!1;const a=t.slice(n+4,n+4+20),o=n+24-20,c=Buffer.from(t.slice(0,20));c.writeUInt16BE(o,2);const h=e.createHmac("sha1",Buffer.from(r,"utf8")).update(Buffer.concat([c,t.slice(20,n)])).digest();return a.length===h.length&&e.timingSafeEqual(a,h)}(r.raw,this.localPwd))return;const i=new v(U.BINDING_SUCCESS,r.transactionId).addXorMappedAddress(s.address,s.port).build(this.localPwd);t.send(i,s.address,s.port),this.#ge.find(e=>e.address===s.address&&e.port===s.port)||this.addRemoteCandidate({address:s.address,port:s.port,type:"prflx",priority:0});const n=r.attrs.has(D.USE_CANDIDATE),a=this.#xe(t,s);n&&"controlled"===this.role&&this.#Fe(a||this.#Me(t,s))}#He(e,t,r){const s=this.#Ae.get(t.transactionId.toString("hex"));s&&(this.#Ae.delete(t.transactionId.toString("hex")),s.state="succeeded","controlling"===this.role&&this.#Fe(s))}#xe(e,t){return this.#Ie.find(r=>r.remote.address===t.address&&r.remote.port===t.port&&r.local.transport===e)}#Me(e,t){return{local:{transport:e},remote:{address:t.address,port:t.port}}}#Fe(e){!this.#Te&&e&&(this.#Te=e,this.#_=!0,this.#ke(),this.emit("selected",{transport:e.local.transport,candidateType:e.local.type,remoteAddress:e.remote.address,remotePort:e.remote.port}),this.emit("connected"))}send(e){if(!this.#Te)throw new Error("ICE not connected");this.#Te.local.transport.send(e,this.#Te.remote.address,this.#Te.remote.port)}getSelectedPair(){return this.#Te}getSelectedCandidateType(){return this.#Te?this.#Te.local.type:null}close(){if(!this.#Ce){this.#Ce=!0,this.#ke();for(const e of this.#me)try{e.close()}catch(e){}this.#me=[],this.emit("closed")}}}const G=Object.freeze({CHANGE_CIPHER_SPEC:20,ALERT:21,HANDSHAKE:22,APPLICATION_DATA:23}),q=Object.freeze({HELLO_REQUEST:0,CLIENT_HELLO:1,SERVER_HELLO:2,HELLO_VERIFY_REQUEST:3,CERTIFICATE:11,SERVER_KEY_EXCHANGE:12,CERTIFICATE_REQUEST:13,SERVER_HELLO_DONE:14,CERTIFICATE_VERIFY:15,CLIENT_KEY_EXCHANGE:16,FINISHED:20}),$=Object.freeze({WARNING:1,FATAL:2}),z=Object.freeze({CLOSE_NOTIFY:0,HANDSHAKE_FAILURE:40,BAD_CERTIFICATE:42,DECRYPT_ERROR:51,INTERNAL_ERROR:80}),j=49195,V=Object.freeze({secp256r1:23}),W=Object.freeze({uncompressed:0}),Y=Object.freeze({sha256:4,sha384:5,sha512:6}),X=Object.freeze({rsa:1,ecdsa:3}),Q=Object.freeze({ecdsa_sign:64,rsa_sign:1}),Z=Object.freeze({SUPPORTED_GROUPS:10,EC_POINT_FORMATS:11,SIGNATURE_ALGORITHMS:13,EXTENDED_MASTER_SECRET:23,RENEGOTIATION_INFO:65281}),J=Object.freeze({CLIENT:"client finished",SERVER:"server finished"});function ee(e){return Buffer.from([e>>16&255,e>>8&255,255&e])}function te(e,t){return e[t]<<16|e[t+1]<<8|e[t+2]}function re(e){return Buffer.concat([Buffer.from([e.length]),e])}function se(e){const t=Buffer.alloc(2);return t.writeUInt16BE(e.length,0),Buffer.concat([t,e])}function ie(e){return Buffer.concat([ee(e.length),e])}function ne(e,t,r){const s=Buffer.alloc(12);return s.writeUInt8(e,0),ee(r.length).copy(s,1),s.writeUInt16BE(t,4),ee(0).copy(s,6),ee(r.length).copy(s,9),Buffer.concat([s,r])}function ae(t,r,s,i){return function(t,r,s,i){const n=[];let a=0,o=s;for(;a<i;){o=e.createHmac(t,r).update(o).digest();const i=e.createHmac(t,r).update(Buffer.concat([o,s])).digest();n.push(i),a+=i.length}return Buffer.concat(n).slice(0,i)}("sha256",t,Buffer.concat([Buffer.from(r,"ascii"),s]),i)}function oe(e,t,r){return ae(e,"master secret",Buffer.concat([t,r]),48)}function ce(e,t){return ae(e,"extended master secret",t,48)}function he(e,t,r,s,i){const n=Buffer.alloc(13);return n.writeUInt16BE(e,0),n.writeUIntBE(t,2,6),n.writeUInt8(r,8),n.writeUInt16BE(s,9),n.writeUInt16BE(i,11),n}class de{#Ke;#Ge;constructor(e,t){this.#Ke=e,this.#Ge=t}encrypt(t,r,s,i,n){const a=Buffer.alloc(8);a.writeUInt16BE(t,0),a.writeUIntBE(r,2,6);const o=Buffer.concat([this.#Ge,a]),c=he(t,r,s,i,n.length),h=e.createCipheriv("aes-128-gcm",this.#Ke,o);h.setAAD(c);const d=Buffer.concat([h.update(n),h.final()]),l=h.getAuthTag();return Buffer.concat([a,d,l])}decrypt(t,r,s,i,n){const a=n.slice(0,8),o=n.slice(n.length-16),c=n.slice(8,n.length-16),h=Buffer.concat([this.#Ge,a]),d=he(t,r,s,i,c.length),l=e.createDecipheriv("aes-128-gcm",this.#Ke,h);return l.setAAD(d),l.setAuthTag(o),Buffer.concat([l.update(c),l.final()])}}const le=Object.freeze({CLIENT:"client",SERVER:"server"}),ue=Object.freeze({NEW:"new",HANDSHAKING:"handshaking",CONNECTED:"connected",CLOSED:"closed",FAILED:"failed"});class fe extends t{role;state;#I;#T;#qe;#$e;#ze;#je;#Ve;#We;#Ye;#Xe;#Qe;#Ze;#Je;#et;#tt;#rt;#st;#it;#nt;#at;#ot;#ct;#ht;#dt;#lt;#ut;#ft;constructor(e){super(),this.role=e.role,this.#I=e.certDer,this.#T=e.privateKey,this.#qe=e.verifyFingerprint||null,this.#$e=e.output,this.state=ue.NEW,this.#ze=0,this.#je=0,this.#Ve=0,this.#We=null,this.#Ye=null,this.#Xe=!1,this.#Qe=null,this.#Ze=null,this.#Je=Buffer.alloc(0),this.#et=null,this.#tt=null,this.#rt=null,this.#st=null,this.#it=!1,this.#nt=[],this.#at=new Map,this.#ot=0,this.#ct=[],this.#ht=null,this.#dt=0,this.#lt=!1}start(){this.state===ue.NEW&&(this.state=ue.HANDSHAKING,this.role===le.CLIENT&&(this.#Qe=this.#pt(),this.#mt()))}#pt(){const t=e.randomBytes(32);return t.writeUInt32BE(Math.floor(Date.now()/1e3),0),t}#Et(e){const t=[];for(const r of e){const e=this.#Ve++,s=ne(r.type,e,r.body);this.#nt.push(s);const i=r.body.length;let n=0;do{const s=r.body.slice(n,n+1200),a=Buffer.alloc(12);a.writeUInt8(r.type,0),ee(i).copy(a,1),a.writeUInt16BE(e,4),ee(n).copy(a,6),ee(s.length).copy(a,9);const o=Buffer.concat([a,s]);t.push({type:G.HANDSHAKE,payload:o}),n+=s.length}while(n<i)}this.#ct=t,this.#dt=0,this.#gt(),this.#It()}#gt(){for(const e of this.#ct)this.#Tt(e.type,e.payload)}#Ct(){this.#Tt(G.CHANGE_CIPHER_SPEC,Buffer.from([1])),this.#ze=1,this.#je=0,this.#Xe=!0}#Tt(e,t){let r=t;const s=this.#je++;this.#Xe&&this.#We&&(r=this.#We.encrypt(this.#ze,s,e,65277,t));const i=function(e,t,r,s,i=65277){const n=Buffer.alloc(13);return n.writeUInt8(e,0),n.writeUInt16BE(i,1),n.writeUInt16BE(t,3),n.writeUIntBE(r,5,6),n.writeUInt16BE(s.length,11),Buffer.concat([n,s])}(e,this.#ze,s,r,65277);this.#$e(i)}#It(){this.#St(),this.#ht=setTimeout(()=>{this.#lt||this.state!==ue.HANDSHAKING||(this.#dt>=10?this.#yt(new Error("DTLS handshake timed out")):(this.#dt++,this.#gt(),this.#It()))},1e3*Math.pow(2,this.#dt)),this.#ht.unref&&this.#ht.unref()}#St(){this.#ht&&(clearTimeout(this.#ht),this.#ht=null)}handlePacket(e){if(this.state===ue.CLOSED||this.state===ue.FAILED)return;let t;try{t=function(e){const t=[];let r=0;for(;r+13<=e.length;){const s=e.readUInt8(r),i=e.readUInt16BE(r+1),n=e.readUInt16BE(r+3),a=e.readUIntBE(r+5,6),o=e.readUInt16BE(r+11),c=r+13;if(c+o>e.length)break;t.push({type:s,version:i,epoch:n,seq:a,fragment:e.slice(c,c+o)}),r=c+o}return t}(e)}catch(e){return}for(const e of t)try{this.#At(e)}catch(e){return void this.#yt(e instanceof Error?e:new Error(String(e)))}}#At(e){let t=e.fragment;if(e.epoch>=1){if(!this.#Ye)return;t=this.#Ye.decrypt(e.epoch,e.seq,e.type,e.version,e.fragment)}switch(e.type){case G.HANDSHAKE:this.#Bt(t);break;case G.CHANGE_CIPHER_SPEC:break;case G.APPLICATION_DATA:this.state===ue.CONNECTED&&this.emit("data",t);break;case G.ALERT:this.#Rt(t)}}#Rt(e){if(e.length<2)return;const t=e[0],r=e[1];r===z.CLOSE_NOTIFY?this.close():t===$.FATAL&&this.#yt(new Error(`DTLS fatal alert: ${r}`))}#Bt(e){const t=function(e){const t=e.readUInt8(0),r=te(e,1),s=e.readUInt16BE(4),i=te(e,6),n=te(e,9);return{msgType:t,length:r,messageSeq:s,fragmentOffset:i,fragmentLength:n,body:e.slice(12,12+n)}}(e);let r=this.#at.get(t.messageSeq);for(r||(r={type:t.msgType,length:t.length,data:Buffer.alloc(t.length),received:0,ranges:[]},this.#at.set(t.messageSeq,r)),t.body.copy(r.data,t.fragmentOffset),r.received=Math.max(r.received,t.fragmentOffset+t.fragmentLength);;){const e=this.#at.get(this.#ot);if(!e||e.received<e.length)break;this.#at.delete(this.#ot),this.#ot++,this.#wt(e.type,e.data)}}#Nt(e,t){const r=this.#ot-1;this.#nt.push(ne(e,r,t))}#wt(e,t){this.role===le.CLIENT?this.#bt(e,t):this.#Ot(e,t)}#Ut(){const t=e.createHash("sha256");for(const e of this.#nt)t.update(e);return t.digest()}#Dt(){return Buffer.concat(this.#nt)}#mt(){const e=this.#Lt();if(0===this.#Je.length){const t=this.#Ve++,r=ne(q.CLIENT_HELLO,t,e);this.#ct=[{type:G.HANDSHAKE,payload:r}],this.#gt(),this.#It()}else{const t=this.#Ve++,r=ne(q.CLIENT_HELLO,t,e);this.#nt.push(r),this.#ct=[{type:G.HANDSHAKE,payload:r}],this.#dt=0,this.#gt(),this.#It()}}#Lt(){const e=[];e.push(Buffer.from([254,253])),e.push(this.#Qe),e.push(re(Buffer.alloc(0))),e.push(re(this.#Je));const t=Buffer.alloc(2);return t.writeUInt16BE(j,0),e.push(se(t)),e.push(re(Buffer.from([0]))),e.push(se(this.#kt())),Buffer.concat(e)}#kt(){const e=[],t=Buffer.alloc(2);t.writeUInt16BE(V.secp256r1,0),e.push(this.#vt(Z.SUPPORTED_GROUPS,se(t))),e.push(this.#vt(Z.EC_POINT_FORMATS,re(Buffer.from([W.uncompressed]))));const r=Buffer.from([Y.sha256,X.ecdsa]);return e.push(this.#vt(Z.SIGNATURE_ALGORITHMS,se(r))),e.push(this.#vt(Z.EXTENDED_MASTER_SECRET,Buffer.alloc(0))),Buffer.concat(e)}#vt(e,t){const r=Buffer.alloc(4);return r.writeUInt16BE(e,0),r.writeUInt16BE(t.length,2),Buffer.concat([r,t])}#bt(e,t){switch(e){case q.HELLO_VERIFY_REQUEST:{const e=t.readUInt8(2);this.#Je=t.slice(3,3+e),this.#St(),this.#mt();break}case q.SERVER_HELLO:this.#Nt(e,t),this.#_t(t);break;case q.CERTIFICATE:this.#Nt(e,t),this.#rt=this.#Pt(t);break;case q.SERVER_KEY_EXCHANGE:this.#Nt(e,t),this.#Ht(t);break;case q.CERTIFICATE_REQUEST:this.#Nt(e,t);break;case q.SERVER_HELLO_DONE:this.#Nt(e,t),this.#St(),this.#xt();break;case q.FINISHED:this.#Ft(t,J.SERVER),this.#Nt(e,t),this.#Mt()}}#_t(e){let t=2;this.#Ze=e.slice(t,t+32),t+=32,t+=1+e.readUInt8(t);const r=e.readUInt16BE(t);if(t+=2,r!==j)throw new Error(`Server chose unsupported cipher suite 0x${r.toString(16)}`);if(t+=1,t+2<=e.length){const r=e.readUInt16BE(t);t+=2;const s=t+r;for(;t+4<=s;){const r=e.readUInt16BE(t),s=e.readUInt16BE(t+2);t+=4,r===Z.EXTENDED_MASTER_SECRET&&(this.#it=!0),t+=s}}}#xt(){this.#et=e.createECDH("prime256v1"),this.#et.generateKeys();const t=this.#et.getPublicKey(),r=this.#et.computeSecret(this.#st),s=this.#Kt(),i=re(t),n=this.#Ve,a=n+1,o=ne(q.CERTIFICATE,n,s),c=ne(q.CLIENT_KEY_EXCHANGE,a,i);if(this.#it){const t=e.createHash("sha256");for(const e of this.#nt)t.update(e);t.update(o),t.update(c);const s=t.digest();this.#tt=ce(r,s)}else this.#tt=oe(r,this.#Qe,this.#Ze);this.#Gt();const h=Buffer.concat([...this.#nt,o,c]),d=e.sign("sha256",h,{key:this.#T,dsaEncoding:"der"}),l=Buffer.concat([Buffer.from([Y.sha256,X.ecdsa]),se(d)]);this.#Et([{type:q.CERTIFICATE,body:s},{type:q.CLIENT_KEY_EXCHANGE,body:i},{type:q.CERTIFICATE_VERIFY,body:l}]),this.#Ct(),this.#qt(J.CLIENT)}#Ot(e,t){switch(e){case q.CLIENT_HELLO:this.#$t(t);break;case q.CERTIFICATE:this.#Nt(e,t),this.#rt=this.#Pt(t);break;case q.CLIENT_KEY_EXCHANGE:{this.#Nt(e,t);const r=t.readUInt8(0);this.#st=t.slice(1,1+r);const s=this.#et.computeSecret(this.#st);this.#it?this.#tt=ce(s,this.#Ut()):this.#tt=oe(s,this.#Qe,this.#Ze),this.#Gt();break}case q.CERTIFICATE_VERIFY:this.#zt(t),this.#Nt(e,t);break;case q.FINISHED:this.#Ft(t,J.CLIENT),this.#Nt(e,t),this.#Ct(),this.#qt(J.SERVER),this.#Mt()}}#$t(e){let t=2;const r=e.slice(t,t+32);t+=32,t+=1+e.readUInt8(t);const s=e.readUInt8(t),i=e.slice(t+1,t+1+s);t+=1+s;const n=e.readUInt16BE(t),a=e.slice(t+2,t+2+n);t+=2+n,t+=1+e.readUInt8(t);let o=!1,c=!1;for(let e=0;e+1<a.length;e+=2)255===a.readUInt16BE(e)&&(c=!0);if(t+2<=e.length){const r=e.readUInt16BE(t);t+=2;const s=t+r;for(;t+4<=s;){const r=e.readUInt16BE(t),s=e.readUInt16BE(t+2);t+=4,r===Z.EXTENDED_MASTER_SECRET&&(o=!0),r===Z.RENEGOTIATION_INFO&&(c=!0),t+=s}}if(this.#ft=c,0===i.length)return this.#Qe=r,this.#jt(this.#Vt(r)),this.#at.clear(),void(this.#ot=1);const h=this.#Vt(r);if(!i.equals(h))return this.#jt(h),this.#at.clear(),void(this.#ot=1);this.#Qe=r,this.#it=o,this.#Nt(q.CLIENT_HELLO,e),this.#Wt()}#Vt(t){return this.#ut||(this.#ut=e.randomBytes(32)),e.createHmac("sha256",this.#ut).update(t).digest().slice(0,20)}#jt(e){const t=Buffer.concat([Buffer.from([254,255]),re(e)]),r=ne(q.HELLO_VERIFY_REQUEST,0,t);this.#Tt(G.HANDSHAKE,r),this.#Ve=1}#Wt(){this.#Ze=this.#pt(),this.#et=e.createECDH("prime256v1"),this.#et.generateKeys();const t=this.#et.getPublicKey(),r=this.#Yt(),s=this.#Kt(),i=Buffer.concat([Buffer.from([3]),(()=>{const e=Buffer.alloc(2);return e.writeUInt16BE(V.secp256r1,0),e})(),re(t)]),n=Buffer.concat([this.#Qe,this.#Ze,i]),a=e.sign("sha256",n,{key:this.#T,dsaEncoding:"der"}),o=Buffer.concat([i,Buffer.from([Y.sha256,X.ecdsa]),se(a)]),c=re(Buffer.from([Q.ecdsa_sign,Q.rsa_sign])),h=se(Buffer.from([Y.sha256,X.ecdsa])),d=se(Buffer.alloc(0)),l=Buffer.concat([c,h,d]),u=Buffer.alloc(0);this.#Et([{type:q.SERVER_HELLO,body:r},{type:q.CERTIFICATE,body:s},{type:q.SERVER_KEY_EXCHANGE,body:o},{type:q.CERTIFICATE_REQUEST,body:l},{type:q.SERVER_HELLO_DONE,body:u}])}#Yt(){const e=[];e.push(Buffer.from([254,253])),e.push(this.#Ze),e.push(re(Buffer.alloc(0)));const t=Buffer.alloc(2);t.writeUInt16BE(j,0),e.push(t),e.push(Buffer.from([0]));const r=[];return this.#it&&r.push(this.#vt(Z.EXTENDED_MASTER_SECRET,Buffer.alloc(0))),r.push(this.#vt(Z.EC_POINT_FORMATS,re(Buffer.from([W.uncompressed])))),this.#ft&&r.push(this.#vt(Z.RENEGOTIATION_INFO,re(Buffer.alloc(0)))),e.push(se(Buffer.concat(r))),Buffer.concat(e)}#zt(t){const r=t.readUInt16BE(2),s=t.slice(4,4+r),i=this.#Dt(),n=this.#Xt(this.#rt);if(!e.verify("sha256",i,{key:n,dsaEncoding:"der"},s))throw new Error("Client CertificateVerify signature invalid")}#Kt(){const e=ie(this.#I);return ie(e)}#Pt(e){let t=3;if(t+3>3+te(e,0))return null;const r=te(e,t);t+=3;const s=e.slice(t,t+r);if(this.#qe){const e={algorithm:"sha-256",value:I(s,"sha-256")};if(!this.#qe(e,s))throw new Error("Remote certificate fingerprint mismatch")}return s}#Ht(t){let r=0;const s=t.readUInt8(r);r+=1;const i=t.readUInt16BE(r);if(r+=2,3!==s||i!==V.secp256r1)throw new Error("Unsupported ECDHE curve from server");const n=t.readUInt8(r);r+=1;const a=t.slice(r,r+n);r+=n,this.#st=a;const o=t.slice(0,r);r+=2;const c=t.readUInt16BE(r);r+=2;const h=t.slice(r,r+c),d=Buffer.concat([this.#Qe,this.#Ze,o]),l=this.#Xt(this.#rt);if(!e.verify("sha256",d,{key:l,dsaEncoding:"der"},h))throw new Error("ServerKeyExchange signature invalid")}#Xt(t){return new e.X509Certificate(t).publicKey}#Gt(){const{clientKey:e,serverKey:t,clientIV:r,serverIV:s}=function(e,t,r){const s=ae(e,"key expansion",Buffer.concat([r,t]),40);let i=0;return{clientKey:s.slice(i,i+=16),serverKey:s.slice(i,i+=16),clientIV:s.slice(i,i+=4),serverIV:s.slice(i,i+=4)}}(this.#tt,this.#Qe,this.#Ze);this.role===le.CLIENT?(this.#We=new de(e,r),this.#Ye=new de(t,s)):(this.#We=new de(t,s),this.#Ye=new de(e,r))}#qt(e){const t=ae(this.#tt,e,this.#Ut(),12),r=this.#Ve++,s=ne(q.FINISHED,r,t);this.#nt.push(s),this.#Tt(G.HANDSHAKE,s)}#Ft(t,r){const s=ae(this.#tt,r,this.#Ut(),12);if(!e.timingSafeEqual(t,s))throw new Error("Peer Finished verify_data mismatch")}#Mt(){this.#lt||(this.#lt=!0,this.#St(),this.state=ue.CONNECTED,this.emit("connect"))}send(e){if(this.state!==ue.CONNECTED)throw new Error("DTLS connection not established");this.#Tt(G.APPLICATION_DATA,e)}close(){if(this.state!==ue.CLOSED&&this.state!==ue.FAILED){try{this.#Xe&&this.#Tt(G.ALERT,Buffer.from([$.WARNING,z.CLOSE_NOTIFY]))}catch(e){}this.#St(),this.state=ue.CLOSED,this.emit("close")}}#yt(e){this.state!==ue.FAILED&&this.state!==ue.CLOSED&&(this.#St(),this.state=ue.FAILED,this.emit("error",e))}getRemoteCertificate(){return this.#rt}}const pe=Object.freeze({DATA:0,INIT:1,INIT_ACK:2,SACK:3,HEARTBEAT:4,HEARTBEAT_ACK:5,ABORT:6,SHUTDOWN:7,SHUTDOWN_ACK:8,ERROR:9,COOKIE_ECHO:10,COOKIE_ACK:11,SHUTDOWN_COMPLETE:14,FORWARD_TSN:192}),me=Object.freeze({HEARTBEAT_INFO:1,STATE_COOKIE:7,UNRECOGNIZED_PARAM:8,COOKIE_PRESERVATIVE:9,SUPPORTED_ADDR_TYPES:11,FORWARD_TSN_SUPPORTED:49152,SUPPORTED_EXTENSIONS:32776}),Ee=Object.freeze({DCEP:50,STRING:51,BINARY:53,STRING_EMPTY:56,BINARY_EMPTY:57,STRING_PARTIAL:54,BINARY_PARTIAL:52});function ge(e){return e+3&-4}function Ie(e,t,r){const s=4+r.length,i=Buffer.alloc(ge(s));return i.writeUInt8(e,0),i.writeUInt8(t,1),i.writeUInt16BE(s,2),r.copy(i,4),i}function Te(e,t){const r=4+t.length,s=Buffer.alloc(ge(r));return s.writeUInt16BE(e,0),s.writeUInt16BE(r,2),t.copy(s,4),s}function Ce(e){const t=[];let r=0;for(;r+4<=e.length;){const s=e.readUInt16BE(r),i=e.readUInt16BE(r+2);if(i<4||r+i>e.length)break;t.push({type:s,length:i,value:e.slice(r+4,r+i)}),r+=ge(i)}return t}function Se({initiateTag:e,a_rwnd:t,outStreams:r,inStreams:s,initialTSN:i}){const n=Buffer.alloc(16);return n.writeUInt32BE(e>>>0,0),n.writeUInt32BE(t>>>0,4),n.writeUInt16BE(r,8),n.writeUInt16BE(s,10),n.writeUInt32BE(i>>>0,12),n}function ye(e){return{initiateTag:e.readUInt32BE(0),a_rwnd:e.readUInt32BE(4),outStreams:e.readUInt16BE(8),inStreams:e.readUInt16BE(10),initialTSN:e.readUInt32BE(12),params:Ce(e.slice(16))}}function Ae({tsn:e,streamId:t,streamSeq:r,ppid:s,userData:i,unordered:n=!1,beginning:a=!0,ending:o=!0}){const c=Buffer.alloc(12);c.writeUInt32BE(e>>>0,0),c.writeUInt16BE(t,4),c.writeUInt16BE(r,6),c.writeUInt32BE(s>>>0,8);let h=0;return o&&(h|=1),a&&(h|=2),n&&(h|=4),{flags:h,body:Buffer.concat([c,i])}}const Be=(()=>{const e=new Uint32Array(256);for(let t=0;t<256;t++){let r=t;for(let e=0;e<8;e++)r=1&r?2197175160^r>>>1:r>>>1;e[t]=r>>>0}return e})();function Re(e){let t=4294967295;for(let r=0;r<e.length;r++)t=Be[255&(t^e[r])]^t>>>8;return(4294967295^t)>>>0}const we=1048576,Ne=Object.freeze({CLOSED:"closed",COOKIE_WAIT:"cookie-wait",COOKIE_ECHOED:"cookie-echoed",ESTABLISHED:"established"});function be(e,t){return(e-t&4294967295)>2147483648}function Oe(e,t){return e===t||be(e,t)}class Ue extends t{isClient;state;#Qt;#Zt;#Jt;#er;#tr;#rr;#sr;#ir;#nr;#ar;#or;#ut;constructor(t={}){super(),this.isClient=!!t.isClient,this.state=Ne.CLOSED,this.#Qt=5e3,this.#Zt=5e3,this.#Jt=e.randomBytes(4).readUInt32BE(0)>>>0||1,this.#er=0,this.#tr=e.randomBytes(4).readUInt32BE(0)>>>0,this.#rr=new Map,this.#sr=new Map,this.#ir=null,this.#nr=new Map,this.#ar=new Map,this.#or=null}start(){this.state===Ne.CLOSED&&this.isClient&&(this.#cr(),this.state=Ne.COOKIE_WAIT)}#hr(e,t){const r=function(e,t,r){const s=Buffer.alloc(12);return s.writeUInt16BE(e,0),s.writeUInt16BE(t,2),s.writeUInt32BE(r>>>0,4),s.writeUInt32BE(0,8),s}(this.#Qt,this.#Zt,e),s=Buffer.concat([r,...t]);!function(e){e.writeUInt32LE(0,8);const t=Re(e);e.writeUInt32LE(t,8)}(s),this.emit("output",s)}receivePacket(e){if(e.length<12)return;if(!function(e){const t=e.readUInt32LE(8);e.writeUInt32LE(0,8);const r=Re(e);return e.writeUInt32LE(t,8),r===t}(e))return;const t=function(e){return{srcPort:e.readUInt16BE(0),dstPort:e.readUInt16BE(2),verificationTag:e.readUInt32BE(4),checksum:e.readUInt32LE(8)}}(e),r=function(e){const t=[];let r=12;for(;r+4<=e.length;){const s=e.readUInt8(r),i=e.readUInt8(r+1),n=e.readUInt16BE(r+2);if(n<4||r+n>e.length)break;const a=e.slice(r+4,r+n);t.push({type:s,flags:i,length:n,body:a}),r+=ge(n)}return t}(e);for(const e of r)this.#dr(e,t)}#dr(e,t){switch(e.type){case pe.INIT:this.#lr(e);break;case pe.INIT_ACK:this.#ur(e);break;case pe.COOKIE_ECHO:this.#fr(e);break;case pe.COOKIE_ACK:this.#pr();break;case pe.DATA:this.#mr(e);break;case pe.SACK:this.#Er(e);break;case pe.HEARTBEAT:this.#gr(e);break;case pe.ABORT:this.#Ir("peer sent ABORT");break;case pe.SHUTDOWN:this.#Tr()}}#Cr(){return[Te(me.FORWARD_TSN_SUPPORTED,Buffer.alloc(0))]}#cr(){const e=Se({initiateTag:this.#Jt,a_rwnd:we,outStreams:65535,inStreams:65535,initialTSN:this.#tr}),t=Ie(pe.INIT,0,Buffer.concat([e,...this.#Cr()]));this.#hr(0,[t]),this.#Sr([t])}#Sr(e){this.#yr();let t=500,r=0;const s=()=>{this.state!==Ne.ESTABLISHED&&this.state!==Ne.CLOSED&&(r>=8?this.#Ir("SCTP setup timed out"):(r++,this.#hr(this.state===Ne.COOKIE_ECHOED?this.#er:0,e),t=Math.min(2*t,5e3),this.#or=setTimeout(s,t),this.#or.unref&&this.#or.unref()))};this.#or=setTimeout(s,t),this.#or.unref&&this.#or.unref()}#yr(){this.#or&&(clearTimeout(this.#or),this.#or=null)}#lr(t){const r=ye(t.body);this.#er=r.initiateTag,this.#ir=r.initialTSN-1>>>0,this.#ut||(this.#ut=e.randomBytes(32));const s=Buffer.alloc(16);s.writeUInt32BE(this.#Jt,0),s.writeUInt32BE(this.#er,4),s.writeUInt32BE(this.#tr,8),s.writeUInt32BE(r.initialTSN,12);const i=e.createHmac("sha256",this.#ut).update(s).digest(),n=Buffer.concat([s,i]),a=Se({initiateTag:this.#Jt,a_rwnd:we,outStreams:65535,inStreams:65535,initialTSN:this.#tr}),o=Buffer.concat([Te(me.STATE_COOKIE,n),...this.#Cr()]),c=Ie(pe.INIT_ACK,0,Buffer.concat([a,o]));this.#hr(this.#er,[c])}#ur(e){if(this.state!==Ne.COOKIE_WAIT)return;this.#yr();const t=ye(e.body);this.#er=t.initiateTag,this.#ir=t.initialTSN-1>>>0;const r=t.params.find(e=>e.type===me.STATE_COOKIE);if(!r)return void this.#Ir("INIT_ACK missing state cookie");const s=Ie(pe.COOKIE_ECHO,0,r.value);this.state=Ne.COOKIE_ECHOED,this.#hr(this.#er,[s]),this.#Sr([s])}#fr(t){const r=t.body;if(r.length>=48&&this.#ut){const t=r.slice(0,16),s=r.slice(16,48),i=e.createHmac("sha256",this.#ut).update(t).digest();if(!e.timingSafeEqual(s,i))return}const s=Ie(pe.COOKIE_ACK,0,Buffer.alloc(0));this.#hr(this.#er,[s]),this.#Ar()}#pr(){this.state===Ne.COOKIE_ECHOED&&(this.#yr(),this.#Ar())}#Ar(){this.state!==Ne.ESTABLISHED&&(this.state=Ne.ESTABLISHED,this.emit("established"))}sendData(e,t,r,s={}){if(this.state!==Ne.ESTABLISHED)throw new Error("SCTP association not established");const i=!!s.unordered;let n=0;i||(n=this.#rr.get(e)||0,this.#rr.set(e,n+1&65535));const a=r.length;let o=0;const c=[];do{const s=r.slice(o,o+1200),h=0===o,d=o+s.length>=a,l=this.#tr;this.#tr=this.#tr+1>>>0;const{flags:u,body:f}=Ae({tsn:l,streamId:e,streamSeq:n,ppid:t,userData:s,unordered:i,beginning:h,ending:d}),p=Ie(pe.DATA,u,f);this.#sr.set(l,{chunk:p}),c.push(p),o+=s.length}while(o<a);for(const e of c)this.#hr(this.#er,[e])}#mr(e){const t={unordered:!!(4&(r=e.flags)),beginning:!!(2&r),ending:!!(1&r),tsn:(s=e.body).readUInt32BE(0),streamId:s.readUInt16BE(4),streamSeq:s.readUInt16BE(6),ppid:s.readUInt32BE(8),userData:s.slice(12)};var r,s;this.#Br(t),this.#Rr()}#Br(e){const t=this.#ir+1>>>0;if(!be(e.tsn,t))if(e.tsn===t){this.#ir=e.tsn,this.#wr(e);let t=this.#ir+1>>>0;for(;this.#nr.has(t);){const e=this.#nr.get(t);this.#nr.delete(t),this.#ir=t,this.#wr(e),t=this.#ir+1>>>0}}else this.#nr.has(e.tsn)||this.#nr.set(e.tsn,e)}#wr(e){const t=`${e.streamId}:${e.unordered?"u":"o"}`;if(e.beginning&&e.ending)return void this.emit("message",{streamId:e.streamId,ppid:e.ppid,data:e.userData});let r=this.#ar.get(t);if(e.beginning)r={ppid:e.ppid,parts:[e.userData]},this.#ar.set(t,r);else{if(!r)return;r.parts.push(e.userData)}e.ending&&r&&(this.#ar.delete(t),this.emit("message",{streamId:e.streamId,ppid:r.ppid,data:Buffer.concat(r.parts)}))}#Rr(){const e=[];if(this.#nr.size>0){const t=[...this.#nr.keys()].sort((e,t)=>be(e,t)?-1:1),r=this.#ir+1>>>0;let s=null,i=null;for(const n of t)null!==s?n!==i+1>>>0?(e.push([1+(s-r&65535),1+(i-r&65535)]),s=n,i=n):i=n:(s=n,i=n);null!==s&&e.push([1+(s-r&65535),1+(i-r&65535)])}const t=function({cumulativeTSNAck:e,a_rwnd:t,gapBlocks:r=[],dupTSNs:s=[]}){const i=Buffer.alloc(12+4*r.length+4*s.length);i.writeUInt32BE(e>>>0,0),i.writeUInt32BE(t>>>0,4),i.writeUInt16BE(r.length,8),i.writeUInt16BE(s.length,10);let n=12;for(const[e,t]of r)i.writeUInt16BE(e,n),i.writeUInt16BE(t,n+2),n+=4;for(const e of s)i.writeUInt32BE(e>>>0,n),n+=4;return i}({cumulativeTSNAck:this.#ir>>>0,a_rwnd:we,gapBlocks:e}),r=Ie(pe.SACK,0,t);this.#hr(this.#er,[r])}#Er(e){const t=function(e){const t=e.readUInt32BE(0),r=e.readUInt32BE(4),s=e.readUInt16BE(8),i=e.readUInt16BE(10),n=[];let a=12;for(let t=0;t<s;t++)n.push([e.readUInt16BE(a),e.readUInt16BE(a+2)]),a+=4;const o=[];for(let t=0;t<i;t++)o.push(e.readUInt32BE(a)),a+=4;return{cumulativeTSNAck:t,a_rwnd:r,gapBlocks:n,dupTSNs:o}}(e.body);for(const e of[...this.#sr.keys()])Oe(e,t.cumulativeTSNAck)&&this.#sr.delete(e);const r=t.cumulativeTSNAck+1>>>0;for(const[e,s]of t.gapBlocks)for(let t=e;t<=s;t++)this.#sr.delete(r+t-1>>>0)}#gr(e){const t=Ie(pe.HEARTBEAT_ACK,0,e.body);this.#hr(this.#er,[t])}#Tr(){const e=Ie(pe.SHUTDOWN_ACK,0,Buffer.alloc(0));this.#hr(this.#er,[e]),this.#Nr()}#Ir(e){this.#yr(),this.state!==Ne.CLOSED&&(this.state=Ne.CLOSED,this.emit("error",new Error(e||"SCTP abort")),this.emit("close"))}shutdown(){if(this.state!==Ne.ESTABLISHED)return void this.#Nr();const e=Ie(pe.SHUTDOWN,0,(()=>{const e=Buffer.alloc(4);return e.writeUInt32BE(this.#ir>>>0,0),e})());this.#hr(this.#er,[e]),this.#Nr()}#Nr(){this.#yr(),this.state!==Ne.CLOSED&&(this.state=Ne.CLOSED,this.emit("close"))}}const De=Object.freeze({DATA_CHANNEL_ACK:2,DATA_CHANNEL_OPEN:3}),Le=Object.freeze({RELIABLE:0,RELIABLE_UNORDERED:128,PARTIAL_RELIABLE_REXMIT:1,PARTIAL_RELIABLE_REXMIT_UNORDERED:129,PARTIAL_RELIABLE_TIMED:2,PARTIAL_RELIABLE_TIMED_UNORDERED:130});class ke extends t{#br;#Or;#Ur;constructor(e,t){super(),this.#br=e,this.#Or=new Map,this.#Ur=t?0:1,this.#br.on("message",e=>this.#Dr(e))}openChannel(e,t={}){let r=e.id;if(null==r&&(r=this.#Lr(),e.emit(A.SET_ID,r)),this.#Or.set(r,{channel:e,acked:!1}),this.#kr(e,r,t),e.negotiated)this.#Or.get(r).acked=!0,e.emit(A.OPEN);else{const s=function({channelType:e,priority:t=0,reliabilityParameter:r=0,label:s="",protocol:i=""}){const n=Buffer.from(s,"utf8"),a=Buffer.from(i,"utf8"),o=Buffer.alloc(12+n.length+a.length);return o.writeUInt8(De.DATA_CHANNEL_OPEN,0),o.writeUInt8(e,1),o.writeUInt16BE(t,2),o.writeUInt32BE(r>>>0,4),o.writeUInt16BE(n.length,8),o.writeUInt16BE(a.length,10),n.copy(o,12),a.copy(o,12+n.length),o}({channelType:this.#vr(t),priority:0,reliabilityParameter:this.#_r(t),label:e.label,protocol:t.protocol||e.protocol||""});this.#br.sendData(r,Ee.DCEP,s)}}#Lr(){let e=this.#Ur;for(;this.#Or.has(e);)e+=2;return this.#Ur=e+2,e}#vr(e){const t=!1===e.ordered;return null!=e.maxRetransmits?t?Le.PARTIAL_RELIABLE_REXMIT_UNORDERED:Le.PARTIAL_RELIABLE_REXMIT:null!=e.maxPacketLifeTime?t?Le.PARTIAL_RELIABLE_TIMED_UNORDERED:Le.PARTIAL_RELIABLE_TIMED:t?Le.RELIABLE_UNORDERED:Le.RELIABLE}#_r(e){return null!=e.maxRetransmits?e.maxRetransmits>>>0:null!=e.maxPacketLifeTime?e.maxPacketLifeTime>>>0:0}#kr(e,t,r){const s=!1===r.ordered;e.on(A.SEND,(e,r)=>{let i;i=r?0===e.length?Ee.BINARY_EMPTY:Ee.BINARY:0===e.length?Ee.STRING_EMPTY:Ee.STRING;const n=0===e.length?Buffer.from([0]):e;this.#br.sendData(t,i,n,{unordered:s})})}#Dr(e){if(e.ppid===Ee.DCEP)return void this.#Pr(e);const t=this.#Or.get(e.streamId);if(!t)return;const r=e.ppid===Ee.BINARY||e.ppid===Ee.BINARY_EMPTY||e.ppid===Ee.BINARY_PARTIAL,s=e.ppid===Ee.STRING_EMPTY||e.ppid===Ee.BINARY_EMPTY?Buffer.alloc(0):e.data;t.channel.emit(A.RECEIVE,s,r)}#Pr(e){const t=(r=e.data).length>0?r.readUInt8(0):-1;var r;if(t===De.DATA_CHANNEL_OPEN){const t=function(e){const t=e.readUInt8(1),r=e.readUInt16BE(2),s=e.readUInt32BE(4),i=e.readUInt16BE(8),n=e.readUInt16BE(10);return{channelType:t,priority:r,reliabilityParameter:s,label:e.slice(12,12+i).toString("utf8"),protocol:e.slice(12+i,12+i+n).toString("utf8"),unordered:!!(128&t)}}(e.data);this.#br.sendData(e.streamId,Ee.DCEP,Buffer.from([De.DATA_CHANNEL_ACK])),this.emit("open-request",{streamId:e.streamId,label:t.label,protocol:t.protocol,ordered:!t.unordered,channelType:t.channelType,reliabilityParameter:t.reliabilityParameter})}else if(t===De.DATA_CHANNEL_ACK){const t=this.#Or.get(e.streamId);t&&!t.acked&&(t.acked=!0,t.channel.emit(A.OPEN))}}acceptChannel(e,t){e.emit(A.SET_ID,t.streamId),this.#Or.set(t.streamId,{channel:e,acked:!0}),this.#kr(e,t.streamId,{ordered:t.ordered}),e.emit(A.OPEN)}}class ve extends t{#Hr;ice;dtls;sctp;dcm;#xr;constructor(e){super(),this.#Hr=e,this.ice=new K({role:e.iceRole,localUfrag:e.localUfrag,localPwd:e.localPwd}),this.dtls=null,this.sctp=null,this.dcm=null,this.#xr=!1,this.ice.on("candidate",e=>this.emit("candidate",e)),this.ice.on("error",e=>this.emit("error",e)),this.ice.on("failed",()=>this.emit("error",new Error("ICE failed"))),this.ice.on("data",e=>{this.dtls&&this.dtls.handlePacket(e)}),this.ice.on("connected",()=>{this.emit("iceconnected"),this.#Fr()})}async gather(e={}){await this.ice.gather(e)}getLocalCandidates(){return this.ice.getLocalCandidates()}setRemote(e,t){this.ice.setRemoteCredentials(e,t),this.ice.start()}addRemoteCandidate(e){this.ice.addRemoteCandidate(e)}#Fr(){this.#xr||(this.#xr=!0,this.dtls=new fe({role:"client"===this.#Hr.dtlsRole?le.CLIENT:le.SERVER,certDer:this.#Hr.certDer,privateKey:this.#Hr.privateKey,verifyFingerprint:this.#Hr.verifyFingerprint,output:e=>{try{this.ice.send(e)}catch(e){this.emit("error",e)}}}),this.dtls.on("connect",()=>{this.emit("dtlsconnected"),this.#Mr()}),this.dtls.on("data",e=>{this.sctp&&this.sctp.receivePacket(e)}),this.dtls.on("error",e=>this.emit("error",e)),this.dtls.on("close",()=>this.emit("close")),this.dtls.start())}#Mr(){const e="client"===this.#Hr.dtlsRole,t=new Ue({isClient:e});this.sctp=t,t.on("output",e=>{try{this.dtls&&this.dtls.send(e)}catch(e){this.emit("error",e)}}),t.on("error",e=>this.emit("error",e)),t.on("close",()=>this.emit("close")),this.dcm=new ke(t,e),this.dcm.on("open-request",e=>this.emit("datachannel-request",e)),t.on("established",()=>{this.emit("sctpconnected"),this.emit("ready")}),t.start()}openChannel(e,t){if(!this.dcm)throw new Error("SCTP not ready");this.dcm.openChannel(e,t)}acceptChannel(e,t){if(!this.dcm)throw new Error("SCTP not ready");this.dcm.acceptChannel(e,t)}isReady(){return!!this.sctp&&"established"===this.sctp.state}close(){if(this.sctp)try{this.sctp.shutdown()}catch{}if(this.dtls)try{this.dtls.close()}catch{}if(this.ice)try{this.ice.close()}catch{}}}const _e=Object.freeze({STABLE:"stable",HAVE_LOCAL_OFFER:"have-local-offer",HAVE_REMOTE_OFFER:"have-remote-offer",HAVE_LOCAL_PRANSWER:"have-local-pranswer",HAVE_REMOTE_PRANSWER:"have-remote-pranswer",CLOSED:"closed"}),Pe=Object.freeze({NEW:"new",GATHERING:"gathering",COMPLETE:"complete"}),He=Object.freeze({NEW:"new",CONNECTING:"connecting",CONNECTED:"connected",DISCONNECTED:"disconnected",FAILED:"failed",CLOSED:"closed"});class xe extends t{#Kr;#Gr;#qr;#$r;#zr;#jr;#Vr;#Wr;#Yr;#Xr;#Qr;#Zr;#Jr;#es;#ts;#Or;#Ee;constructor(t={}){super(),this.#Kr=t,this.#Gr=_e.STABLE,this.#qr=Pe.NEW,this.#$r=He.NEW,this.#zr=null,this.#jr=null,this.#Vr=null,this.#Wr={usernameFragment:e.randomBytes(3).toString("base64").replace(/[^a-zA-Z0-9]/g,"").slice(0,4).padEnd(4,"x"),password:e.randomBytes(18).toString("base64").replace(/[^a-zA-Z0-9]/g,"").slice(0,24).padEnd(24,"x")},this.#Yr=null,this.#Xr=[],this.#Qr=null,this.#Zr=null,this.#Jr=!1,this.#es=!1,this.#ts=[],this.#Or=new Set,this.#Ee=[]}async#rs(){return this.#Vr||(this.#Kr.certificates&&this.#Kr.certificates[0]?this.#Vr=this.#Kr.certificates[0]:this.#Vr=await S.generateCertificate()),this.#Vr}#ss(e,t){if(this.#Zr)return this.#Zr;const r=this.#Vr;if(!r)throw new Error("Certificate not initialized");const s=r.getCertificateDer();if(!s)throw new Error("Certificate has no DER encoding");const i=new ve({iceRole:e,dtlsRole:t,localUfrag:this.#Wr.usernameFragment,localPwd:this.#Wr.password,certDer:s,privateKey:r.getPrivateKeyObject(),verifyFingerprint:e=>this.#is(e)});return i.on("candidate",e=>{const t={candidate:e.sdp,sdpMid:"0",sdpMLineIndex:0,usernameFragment:this.#Wr.usernameFragment};this.#Ee.push(t),this.emit("icecandidate",{candidate:t})}),i.on("iceconnected",()=>this.#ns(He.CONNECTING)),i.on("sctpconnected",()=>this.#ns(He.CONNECTED)),i.on("error",e=>{this.emit("error",e),this.#ns(He.FAILED)}),i.on("close",()=>this.#ns(He.DISCONNECTED)),i.on("datachannel-request",e=>{const t=new B(e.label,{ordered:e.ordered,protocol:e.protocol,id:e.streamId});i.acceptChannel(t,e),this.#Or.add(t),this.emit("datachannel",{channel:t})}),i.on("ready",()=>{for(const{channel:e,init:t}of this.#ts)i.openChannel(e,t);this.#ts=[]}),this.#Zr=i,i}#is(e){return 0===this.#Xr.length||this.#Xr.some(t=>t.algorithm===e.algorithm&&t.value.toUpperCase()===e.value.toUpperCase())}createDataChannel(e,t={}){if(this.#es)throw new Error("RTCPeerConnection is closed");const r=new B(e,t);this.#Or.add(r);const s={ordered:!1!==t.ordered,maxRetransmits:t.maxRetransmits,maxPacketLifeTime:t.maxPacketLifeTime,protocol:t.protocol||"",negotiated:t.negotiated||!1};return this.#Zr&&this.#Zr.isReady()?this.#Zr.openChannel(r,s):this.#ts.push({channel:r,init:s}),setImmediate(()=>{this.#es||this.emit("negotiationneeded")}),r}async createOffer(){if(this.#es)throw new Error("RTCPeerConnection is closed");await this.#rs(),this.#Jr=!0;const e=this.#as(),t=(r={iceUfrag:this.#Wr.usernameFragment,icePwd:this.#Wr.password,fingerprint:e,setup:"actpass",candidates:[]},N({...r,setup:r.setup||"actpass"}));var r;return new w({type:R.OFFER,sdp:t})}async createAnswer(){if(this.#es)throw new Error("RTCPeerConnection is closed");if(!this.#jr||"offer"!==this.#jr.type)throw new Error("Cannot create answer without remote offer");await this.#rs();const e=this.#as(),t=(r={iceUfrag:this.#Wr.usernameFragment,icePwd:this.#Wr.password,fingerprint:e,setup:"active",candidates:[]},N({...r,setup:r.setup||"active"}));var r;return new w({type:R.ANSWER,sdp:t})}#as(){const e=this.#Vr;if(!e)throw new Error("Certificate not initialized");const t=e.getFingerprints();return t.find(e=>"sha-256"===e.algorithm)||t[0]}async setLocalDescription(e){if(this.#es)throw new Error("RTCPeerConnection is closed");const t=e||(this.#Gr===_e.HAVE_REMOTE_OFFER?await this.createAnswer():await this.createOffer());await this.#rs(),this.#zr=new w({type:t.type??void 0,sdp:t.sdp??void 0}),"offer"===t.type?this.#Gr=_e.HAVE_LOCAL_OFFER:"answer"===t.type&&(this.#Gr=_e.STABLE),this.#os(t,!0),this.#qr=Pe.GATHERING,this.emit("icegatheringstatechange"),this.#Zr&&(await this.#Zr.gather({iceServers:this.#Kr.iceServers||[],iceTransportPolicy:this.#Kr.iceTransportPolicy||"all"}),this.#qr=Pe.COMPLETE,this.emit("icegatheringstatechange"),this.emit("icecandidate",{candidate:null}),this.#cs()),this.emit("signalingstatechange")}async setRemoteDescription(e){if(this.#es)throw new Error("RTCPeerConnection is closed");if(!e||!e.sdp)throw new Error("Invalid session description");await this.#rs(),this.#jr=new w(e),"offer"===e.type?this.#Gr=_e.HAVE_REMOTE_OFFER:"answer"===e.type&&(this.#Gr=_e.STABLE),this.#Yr=function(e){const t={usernameFragment:null,password:null};for(const r of e.split(/\r?\n/))r.startsWith("a=ice-ufrag:")?t.usernameFragment=r.slice(12).trim():r.startsWith("a=ice-pwd:")&&(t.password=r.slice(10).trim());return t}(e.sdp);const t=function(e){const t={role:"auto",fingerprints:[]};for(const r of e.split(/\r?\n/))if(r.startsWith("a=setup:")){const e=r.slice(8).trim();t.role="active"===e?"client":"passive"===e?"server":"actpass",t.setup=e}else if(r.startsWith("a=fingerprint:")){const e=r.slice(14).trim().split(/\s+/);2===e.length&&t.fingerprints.push({algorithm:e[0].toLowerCase(),value:e[1].toUpperCase()})}return t}(e.sdp);if(this.#Xr=t.fingerprints,this.#Qr=t.setup??null,this.#os(e,!1),this.#Zr&&this.#Yr.usernameFragment){this.#Zr.setRemote(this.#Yr.usernameFragment,this.#Yr.password??"");for(const t of function(e){const t=[];for(const r of e.split(/\r?\n/)){if(!r.startsWith("a=candidate:"))continue;const e=b(r.slice(2));e&&t.push(e)}return t}(e.sdp))this.#Zr.addRemoteCandidate(t)}this.#cs(),this.emit("signalingstatechange")}#os(e,t){if(this.#Zr)return;const r=this.#Jr?"controlling":"controlled";let s;s=this.#Jr?"active"===this.#Qr?"server":"passive"===this.#Qr?"client":"server":"client",this.#ss(r,s)}#cs(){this.#Zr&&this.#Yr&&this.#Yr.usernameFragment&&this.#Zr.setRemote(this.#Yr.usernameFragment,this.#Yr.password??"")}async addIceCandidate(e){if(this.#es)throw new Error("RTCPeerConnection is closed");if(!e||"string"!=typeof e&&""===e.candidate)return;const t=b("string"==typeof e?e:e.candidate||"");t&&this.#Zr&&this.#Zr.addRemoteCandidate(t)}#ns(e){this.#$r!==e&&(this.#$r=e,this.emit("connectionstatechange"),this.emit("iceconnectionstatechange"))}getConfiguration(){return{...this.#Kr}}setConfiguration(e){if(this.#es)throw new Error("RTCPeerConnection is closed");this.#Kr={...e}}close(){if(!this.#es){this.#es=!0,this.#Gr=_e.CLOSED;for(const e of this.#Or)try{e.close()}catch(e){}if(this.#Zr)try{this.#Zr.close()}catch(e){}this.#ns(He.CLOSED),this.emit("signalingstatechange")}}get signalingState(){return this.#Gr}get iceGatheringState(){return this.#qr}get iceConnectionState(){return this.#$r===He.CONNECTED?"connected":this.#$r===He.CONNECTING?"checking":this.#$r===He.FAILED?"failed":"new"}get connectionState(){return this.#$r}get localDescription(){return this.#zr}get remoteDescription(){return this.#jr}get currentLocalDescription(){return this.#zr}get currentRemoteDescription(){return this.#jr}get pendingLocalDescription(){return this.#Gr===_e.STABLE?null:this.#zr}get pendingRemoteDescription(){return this.#Gr===_e.STABLE?null:this.#jr}get canTrickleIceCandidates(){return!0}get sctp(){return this.#Zr?this.#Zr.sctp:null}}const Fe="2.0.5";export{i as ByteBufferQueue,S as RTCCertificate,B as RTCDataChannel,y as RTCDataChannelState,a as RTCError,o as RTCIceCandidate,Pe as RTCIceGatheringState,xe as RTCPeerConnection,He as RTCPeerConnectionState,R as RTCSdpType,w as RTCSessionDescription,_e as RTCSignalingState,Fe as version};
|