node-rtc-connection 1.0.11 → 1.0.14
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 +355 -289
- package/dist/index.cjs +4318 -3095
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +4318 -3095
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/datachannel/RTCDataChannel.js +354 -0
- package/src/dtls/RTCCertificate.js +310 -0
- package/src/dtls/RTCDtlsTransport.js +247 -0
- package/src/foundation/ByteBufferQueue.js +235 -0
- package/src/foundation/RTCError.js +226 -0
- package/src/ice/RTCIceCandidate.js +301 -0
- package/src/ice/RTCIceTransport.js +956 -0
- package/src/index.d.ts +316 -145
- package/src/index.js +78 -45
- package/src/network/network-transport.js +478 -0
- package/src/peerconnection/RTCPeerConnection.js +847 -0
- package/src/sctp/RTCSctpTransport.js +253 -0
- package/src/sdp/RTCSessionDescription.js +102 -0
- package/src/sdp/sdp-utils.js +224 -0
- package/src/stun/stun-client.js +643 -0
- package/src/ICEGatherer.js +0 -341
- package/src/NativePeerConnectionFactory.js +0 -1044
- package/src/RTCDataChannel.js +0 -346
- package/src/RTCDataChannelEvent.js +0 -50
- package/src/RTCError.js +0 -66
- package/src/RTCIceCandidate.js +0 -184
- package/src/RTCPeerConnection.js +0 -505
- package/src/RTCPeerConnectionIceEvent.js +0 -58
- package/src/RTCSessionDescription.js +0 -62
- package/src/STUNClient.js +0 -222
- package/src/SecureConnection.js +0 -298
- package/src/TURNClient.js +0 -561
- package/src/UDPTransport.js +0 -236
package/src/UDPTransport.js
DELETED
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UDP Transport with DTLS-like encryption
|
|
3
|
-
* Alternative to TCP for lower latency
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const dgram = require('dgram');
|
|
7
|
-
const { EventEmitter } = require('events');
|
|
8
|
-
const { DTLSConnection } = require('./SecureConnection');
|
|
9
|
-
|
|
10
|
-
class UDPTransport extends EventEmitter {
|
|
11
|
-
constructor(options = {}) {
|
|
12
|
-
super();
|
|
13
|
-
|
|
14
|
-
this.socket = dgram.createSocket('udp4');
|
|
15
|
-
this.localPort = options.localPort || 0;
|
|
16
|
-
this.remoteAddress = null;
|
|
17
|
-
this.remotePort = null;
|
|
18
|
-
this.dtls = null;
|
|
19
|
-
this.useEncryption = options.encrypted !== false;
|
|
20
|
-
this.channels = new Map(); // label -> channel info
|
|
21
|
-
this.messageBuffer = Buffer.alloc(0);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Start listening on local port
|
|
26
|
-
*/
|
|
27
|
-
async listen() {
|
|
28
|
-
return new Promise((resolve, reject) => {
|
|
29
|
-
this.socket.on('error', (err) => {
|
|
30
|
-
this.emit('error', err);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
this.socket.on('message', (msg, rinfo) => {
|
|
34
|
-
this._handleMessage(msg, rinfo);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
this.socket.bind(this.localPort, () => {
|
|
38
|
-
const addr = this.socket.address();
|
|
39
|
-
this.localPort = addr.port;
|
|
40
|
-
this.emit('listening', addr);
|
|
41
|
-
resolve(addr);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Connect to remote peer
|
|
48
|
-
*/
|
|
49
|
-
async connect(address, port) {
|
|
50
|
-
this.remoteAddress = address;
|
|
51
|
-
this.remotePort = port;
|
|
52
|
-
|
|
53
|
-
if (this.useEncryption) {
|
|
54
|
-
// Initialize DTLS
|
|
55
|
-
this.dtls = new DTLSConnection({ isServer: false });
|
|
56
|
-
|
|
57
|
-
await this.dtls.handshake((key) => {
|
|
58
|
-
// Send encryption key to remote
|
|
59
|
-
this._sendRaw(Buffer.concat([
|
|
60
|
-
Buffer.from([0x01]), // Key exchange message
|
|
61
|
-
key
|
|
62
|
-
]));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
await new Promise(resolve => {
|
|
66
|
-
this.dtls.once('ready', resolve);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
this.emit('connected');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Handle incoming message
|
|
75
|
-
* @private
|
|
76
|
-
*/
|
|
77
|
-
_handleMessage(msg, rinfo) {
|
|
78
|
-
// Set remote address on first message
|
|
79
|
-
if (!this.remoteAddress) {
|
|
80
|
-
this.remoteAddress = rinfo.address;
|
|
81
|
-
this.remotePort = rinfo.port;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Check if this is a key exchange message
|
|
85
|
-
if (msg[0] === 0x01 && msg.length >= 33) {
|
|
86
|
-
const key = msg.slice(1, 33);
|
|
87
|
-
|
|
88
|
-
if (!this.dtls) {
|
|
89
|
-
this.dtls = new DTLSConnection({ isServer: true });
|
|
90
|
-
|
|
91
|
-
// Send our key back
|
|
92
|
-
this._sendRaw(Buffer.concat([
|
|
93
|
-
Buffer.from([0x01]),
|
|
94
|
-
this.dtls.key
|
|
95
|
-
]));
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.dtls.setRemoteKey(key);
|
|
99
|
-
this.emit('connected');
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Decrypt if encryption is enabled
|
|
104
|
-
let data = msg;
|
|
105
|
-
if (this.useEncryption && this.dtls && this.dtls.ready) {
|
|
106
|
-
try {
|
|
107
|
-
data = this.dtls.decrypt(msg);
|
|
108
|
-
} catch (err) {
|
|
109
|
-
console.error('Decryption failed:', err.message);
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Parse the message
|
|
115
|
-
this._parseMessage(data);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Parse data channel message
|
|
120
|
-
* @private
|
|
121
|
-
*/
|
|
122
|
-
_parseMessage(data) {
|
|
123
|
-
// Message format: <length:4><label-length:2><label><data>
|
|
124
|
-
if (data.length < 6) return;
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
const totalLength = data.readUInt32BE(0);
|
|
128
|
-
const labelLength = data.readUInt16BE(4);
|
|
129
|
-
|
|
130
|
-
if (data.length < 6 + labelLength) return;
|
|
131
|
-
|
|
132
|
-
const label = data.slice(6, 6 + labelLength).toString('utf8');
|
|
133
|
-
const messageData = data.slice(6 + labelLength);
|
|
134
|
-
|
|
135
|
-
// Get or create channel
|
|
136
|
-
if (!this.channels.has(label)) {
|
|
137
|
-
this.emit('channel', { label });
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Emit message event
|
|
141
|
-
this.emit('message', { label, data: messageData });
|
|
142
|
-
|
|
143
|
-
} catch (err) {
|
|
144
|
-
console.error('Failed to parse message:', err);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Send message on a data channel
|
|
150
|
-
*/
|
|
151
|
-
send(label, data) {
|
|
152
|
-
const dataBuffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
153
|
-
const labelBuffer = Buffer.from(label, 'utf8');
|
|
154
|
-
|
|
155
|
-
const totalLength = 2 + labelBuffer.length + dataBuffer.length;
|
|
156
|
-
const message = Buffer.allocUnsafe(4 + totalLength);
|
|
157
|
-
|
|
158
|
-
message.writeUInt32BE(totalLength, 0);
|
|
159
|
-
message.writeUInt16BE(labelBuffer.length, 4);
|
|
160
|
-
labelBuffer.copy(message, 6);
|
|
161
|
-
dataBuffer.copy(message, 6 + labelBuffer.length);
|
|
162
|
-
|
|
163
|
-
this._sendRaw(message);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Send raw data (with optional encryption)
|
|
168
|
-
* @private
|
|
169
|
-
*/
|
|
170
|
-
_sendRaw(data) {
|
|
171
|
-
if (!this.remoteAddress || !this.remotePort) {
|
|
172
|
-
throw new Error('Remote address not set');
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
let sendData = data;
|
|
176
|
-
|
|
177
|
-
// Encrypt if encryption is enabled
|
|
178
|
-
if (this.useEncryption && this.dtls && this.dtls.ready) {
|
|
179
|
-
sendData = this.dtls.encrypt(data);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
this.socket.send(sendData, this.remotePort, this.remoteAddress, (err) => {
|
|
183
|
-
if (err) {
|
|
184
|
-
this.emit('error', err);
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Create a data channel
|
|
191
|
-
*/
|
|
192
|
-
createChannel(label) {
|
|
193
|
-
if (!this.channels.has(label)) {
|
|
194
|
-
this.channels.set(label, { label, created: Date.now() });
|
|
195
|
-
|
|
196
|
-
// Announce channel to remote peer
|
|
197
|
-
this.send(label, Buffer.alloc(0));
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Get local address
|
|
203
|
-
*/
|
|
204
|
-
address() {
|
|
205
|
-
return this.socket.address();
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Get fingerprint (for SDP)
|
|
210
|
-
*/
|
|
211
|
-
getFingerprint() {
|
|
212
|
-
if (this.dtls) {
|
|
213
|
-
return this.dtls.getFingerprint();
|
|
214
|
-
}
|
|
215
|
-
return 'NO:EN:CR:YP:TI:ON';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Close the transport
|
|
220
|
-
*/
|
|
221
|
-
close() {
|
|
222
|
-
if (this.dtls) {
|
|
223
|
-
this.dtls.removeAllListeners();
|
|
224
|
-
this.dtls = null;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
if (this.socket) {
|
|
228
|
-
this.socket.close();
|
|
229
|
-
this.socket = null;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
this.channels.clear();
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
module.exports = UDPTransport;
|