@xtr-dev/rondevu-client 0.21.12 → 0.21.13
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.
|
@@ -32,9 +32,9 @@ export declare class AnswererConnection extends RondevuConnection {
|
|
|
32
32
|
*/
|
|
33
33
|
initialize(): Promise<void>;
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Send buffered ICE candidates to the server in a single batch
|
|
36
36
|
*/
|
|
37
|
-
protected
|
|
37
|
+
protected sendBufferedIceCandidates(candidates: RTCIceCandidate[]): void;
|
|
38
38
|
/**
|
|
39
39
|
* Get the API instance
|
|
40
40
|
*/
|
|
@@ -51,22 +51,21 @@ export class AnswererConnection extends RondevuConnection {
|
|
|
51
51
|
this.debug('Answer sent successfully');
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* Send buffered ICE candidates to the server in a single batch
|
|
55
55
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
sendBufferedIceCandidates(candidates) {
|
|
57
|
+
if (candidates.length === 0)
|
|
58
|
+
return;
|
|
59
|
+
this.debug(`Sending ${candidates.length} ICE candidates in batch`);
|
|
58
60
|
// For answerer, we add ICE candidates to the offer
|
|
59
61
|
// The server will make them available for the offerer to poll
|
|
60
|
-
|
|
61
|
-
.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
])
|
|
68
|
-
.catch(error => {
|
|
69
|
-
this.debug('Failed to send ICE candidate:', error);
|
|
62
|
+
const apiCandidates = candidates.map(c => ({
|
|
63
|
+
candidate: c.candidate,
|
|
64
|
+
sdpMLineIndex: c.sdpMLineIndex,
|
|
65
|
+
sdpMid: c.sdpMid,
|
|
66
|
+
}));
|
|
67
|
+
this.api.addOfferIceCandidates(this.offerId, apiCandidates).catch(error => {
|
|
68
|
+
this.debug('Failed to send ICE candidates:', error);
|
|
70
69
|
});
|
|
71
70
|
}
|
|
72
71
|
/**
|
|
@@ -27,6 +27,9 @@ export declare abstract class RondevuConnection extends EventEmitter<ConnectionE
|
|
|
27
27
|
protected lastIcePollTime: number;
|
|
28
28
|
protected answerProcessed: boolean;
|
|
29
29
|
protected answerSdpFingerprint: string | null;
|
|
30
|
+
protected iceCandidateBuffer: RTCIceCandidate[];
|
|
31
|
+
protected iceCandidateFlushTimer: ReturnType<typeof setTimeout> | null;
|
|
32
|
+
protected static readonly ICE_BUFFER_DELAY_MS = 20;
|
|
30
33
|
constructor(rtcConfig?: RTCConfiguration | undefined, userConfig?: Partial<ConnectionConfig>, webrtcAdapter?: WebRTCAdapter);
|
|
31
34
|
/**
|
|
32
35
|
* Transition to a new state and emit events
|
|
@@ -42,8 +45,17 @@ export declare abstract class RondevuConnection extends EventEmitter<ConnectionE
|
|
|
42
45
|
protected setupDataChannelHandlers(dc: RTCDataChannel): void;
|
|
43
46
|
/**
|
|
44
47
|
* Handle local ICE candidate generation
|
|
48
|
+
* Buffers candidates for batched sending to reduce server requests
|
|
45
49
|
*/
|
|
46
50
|
protected handleIceCandidate(event: RTCPeerConnectionIceEvent): void;
|
|
51
|
+
/**
|
|
52
|
+
* Buffer an ICE candidate for batched sending
|
|
53
|
+
*/
|
|
54
|
+
protected bufferIceCandidate(candidate: RTCIceCandidate): void;
|
|
55
|
+
/**
|
|
56
|
+
* Flush buffered ICE candidates to the server
|
|
57
|
+
*/
|
|
58
|
+
protected flushIceCandidates(): void;
|
|
47
59
|
/**
|
|
48
60
|
* Handle ICE connection state changes (primary state driver)
|
|
49
61
|
*/
|
|
@@ -166,6 +178,6 @@ export declare abstract class RondevuConnection extends EventEmitter<ConnectionE
|
|
|
166
178
|
* Debug logging helper
|
|
167
179
|
*/
|
|
168
180
|
protected debug(...args: unknown[]): void;
|
|
169
|
-
protected abstract
|
|
181
|
+
protected abstract sendBufferedIceCandidates(candidates: RTCIceCandidate[]): void;
|
|
170
182
|
protected abstract attemptReconnect(): void;
|
|
171
183
|
}
|
package/dist/connections/base.js
CHANGED
|
@@ -32,6 +32,9 @@ export class RondevuConnection extends EventEmitter {
|
|
|
32
32
|
// Answer fingerprinting (for offerer)
|
|
33
33
|
this.answerProcessed = false;
|
|
34
34
|
this.answerSdpFingerprint = null;
|
|
35
|
+
// ICE candidate buffering for batched sending
|
|
36
|
+
this.iceCandidateBuffer = [];
|
|
37
|
+
this.iceCandidateFlushTimer = null;
|
|
35
38
|
this.config = mergeConnectionConfig(userConfig);
|
|
36
39
|
this.webrtcAdapter = webrtcAdapter || new BrowserWebRTCAdapter();
|
|
37
40
|
// Initialize message buffer if enabled
|
|
@@ -102,12 +105,45 @@ export class RondevuConnection extends EventEmitter {
|
|
|
102
105
|
}
|
|
103
106
|
/**
|
|
104
107
|
* Handle local ICE candidate generation
|
|
108
|
+
* Buffers candidates for batched sending to reduce server requests
|
|
105
109
|
*/
|
|
106
110
|
handleIceCandidate(event) {
|
|
107
111
|
this.emit('ice:candidate:local', event.candidate);
|
|
108
112
|
if (event.candidate) {
|
|
109
|
-
this.
|
|
113
|
+
this.bufferIceCandidate(event.candidate);
|
|
110
114
|
}
|
|
115
|
+
else {
|
|
116
|
+
// null candidate means ICE gathering complete - flush any remaining
|
|
117
|
+
this.flushIceCandidates();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Buffer an ICE candidate for batched sending
|
|
122
|
+
*/
|
|
123
|
+
bufferIceCandidate(candidate) {
|
|
124
|
+
this.iceCandidateBuffer.push(candidate);
|
|
125
|
+
// Reset flush timer
|
|
126
|
+
if (this.iceCandidateFlushTimer) {
|
|
127
|
+
clearTimeout(this.iceCandidateFlushTimer);
|
|
128
|
+
}
|
|
129
|
+
this.iceCandidateFlushTimer = setTimeout(() => {
|
|
130
|
+
this.flushIceCandidates();
|
|
131
|
+
}, RondevuConnection.ICE_BUFFER_DELAY_MS);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Flush buffered ICE candidates to the server
|
|
135
|
+
*/
|
|
136
|
+
flushIceCandidates() {
|
|
137
|
+
if (this.iceCandidateFlushTimer) {
|
|
138
|
+
clearTimeout(this.iceCandidateFlushTimer);
|
|
139
|
+
this.iceCandidateFlushTimer = null;
|
|
140
|
+
}
|
|
141
|
+
if (this.iceCandidateBuffer.length === 0)
|
|
142
|
+
return;
|
|
143
|
+
const candidates = [...this.iceCandidateBuffer];
|
|
144
|
+
this.iceCandidateBuffer = [];
|
|
145
|
+
this.debug(`Flushing ${candidates.length} buffered ICE candidates`);
|
|
146
|
+
this.sendBufferedIceCandidates(candidates);
|
|
111
147
|
}
|
|
112
148
|
/**
|
|
113
149
|
* Handle ICE connection state changes (primary state driver)
|
|
@@ -496,6 +532,12 @@ export class RondevuConnection extends EventEmitter {
|
|
|
496
532
|
this.cancelReconnect();
|
|
497
533
|
// Stop ICE polling
|
|
498
534
|
this.stopIcePolling();
|
|
535
|
+
// Clear ICE candidate buffer
|
|
536
|
+
if (this.iceCandidateFlushTimer) {
|
|
537
|
+
clearTimeout(this.iceCandidateFlushTimer);
|
|
538
|
+
this.iceCandidateFlushTimer = null;
|
|
539
|
+
}
|
|
540
|
+
this.iceCandidateBuffer = [];
|
|
499
541
|
// Close data channel
|
|
500
542
|
if (this.dc) {
|
|
501
543
|
this.dc.onopen = null;
|
|
@@ -533,3 +575,4 @@ export class RondevuConnection extends EventEmitter {
|
|
|
533
575
|
}
|
|
534
576
|
}
|
|
535
577
|
}
|
|
578
|
+
RondevuConnection.ICE_BUFFER_DELAY_MS = 20; // Buffer for 20ms before sending
|
|
@@ -54,9 +54,9 @@ export declare class OffererConnection extends RondevuConnection {
|
|
|
54
54
|
*/
|
|
55
55
|
private hashSdp;
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
57
|
+
* Send buffered ICE candidates to the server in a single batch
|
|
58
58
|
*/
|
|
59
|
-
protected
|
|
59
|
+
protected sendBufferedIceCandidates(candidates: RTCIceCandidate[]): void;
|
|
60
60
|
/**
|
|
61
61
|
* Get the API instance
|
|
62
62
|
*/
|
|
@@ -193,21 +193,20 @@ export class OffererConnection extends RondevuConnection {
|
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
/**
|
|
196
|
-
*
|
|
196
|
+
* Send buffered ICE candidates to the server in a single batch
|
|
197
197
|
*/
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
this.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
.
|
|
210
|
-
this.debug('Failed to send ICE candidate:', error);
|
|
198
|
+
sendBufferedIceCandidates(candidates) {
|
|
199
|
+
if (candidates.length === 0)
|
|
200
|
+
return;
|
|
201
|
+
this.debug(`Sending ${candidates.length} ICE candidates in batch`);
|
|
202
|
+
// Convert to API format and send in single request
|
|
203
|
+
const apiCandidates = candidates.map(c => ({
|
|
204
|
+
candidate: c.candidate,
|
|
205
|
+
sdpMLineIndex: c.sdpMLineIndex,
|
|
206
|
+
sdpMid: c.sdpMid,
|
|
207
|
+
}));
|
|
208
|
+
this.api.addOfferIceCandidates(this.offerId, apiCandidates).catch(error => {
|
|
209
|
+
this.debug('Failed to send ICE candidates:', error);
|
|
211
210
|
});
|
|
212
211
|
}
|
|
213
212
|
/**
|
package/package.json
CHANGED