node-rtc-connection 1.0.12 → 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.
@@ -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;