Dhurgh commited on
Commit
2ebfe6c
·
1 Parent(s): 950282a

Stabilize ICE recovery loop and default relay mode for calls (v2.6.9)

Browse files
Files changed (4) hide show
  1. client.js +31 -5
  2. index.html +2 -2
  3. package.json +1 -1
  4. server.js +2 -1
client.js CHANGED
@@ -30,6 +30,7 @@ let rtcConfigLoaded = false;
30
  let activeIceServers = [];
31
  let callIceFailureCount = 0;
32
  let forceRelayOnly = false;
 
33
  let hasUserInteractedWithPage = false;
34
  let activeRoomSubscription = null;
35
  let roomMessages = JSON.parse(localStorage.getItem('roomMessages') || '{}');
@@ -6288,9 +6289,6 @@ function createPeerConnection(peerId) {
6288
  }
6289
  if (peerConnection.connectionState === 'connecting') {
6290
  showToast('📞 Connecting call...', 'info');
6291
- } else if (peerConnection.connectionState === 'disconnected') {
6292
- showCallWarningThrottled('⚠️ Connection unstable, trying to reconnect...');
6293
- attemptIceRecovery(peerId);
6294
  } else if (peerConnection.connectionState === 'connected') {
6295
  callIceFailureCount = 0;
6296
  showToast('📞 Call connected!', 'success');
@@ -6323,10 +6321,34 @@ function createPeerConnection(peerId) {
6323
 
6324
  if (peerConnection.iceConnectionState === 'connected' || peerConnection.iceConnectionState === 'completed') {
6325
  callIceFailureCount = 0;
 
 
 
 
6326
  return;
6327
  }
6328
 
6329
- if (peerConnection.iceConnectionState === 'failed' || peerConnection.iceConnectionState === 'disconnected') {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6330
  attemptIceRecovery(peerId);
6331
  }
6332
  };
@@ -6397,7 +6419,7 @@ async function startCallSession(peerName, peerId, isCaller) {
6397
  currentCallPeerId = peerId;
6398
  currentCallPeerName = peerName;
6399
  callIceFailureCount = 0;
6400
- forceRelayOnly = false;
6401
 
6402
  openCallDialog(peerName);
6403
  await ensureRtcConfigLoaded();
@@ -6579,6 +6601,10 @@ function cleanupCallSession(keepDialogOpen = false) {
6579
  callIceFailureCount = 0;
6580
  forceRelayOnly = false;
6581
  activeIceServers = [];
 
 
 
 
6582
 
6583
  if (localCallStream) {
6584
  localCallStream.getTracks().forEach((track) => track.stop());
 
30
  let activeIceServers = [];
31
  let callIceFailureCount = 0;
32
  let forceRelayOnly = false;
33
+ let pendingIceRecoveryTimer = null;
34
  let hasUserInteractedWithPage = false;
35
  let activeRoomSubscription = null;
36
  let roomMessages = JSON.parse(localStorage.getItem('roomMessages') || '{}');
 
6289
  }
6290
  if (peerConnection.connectionState === 'connecting') {
6291
  showToast('📞 Connecting call...', 'info');
 
 
 
6292
  } else if (peerConnection.connectionState === 'connected') {
6293
  callIceFailureCount = 0;
6294
  showToast('📞 Call connected!', 'success');
 
6321
 
6322
  if (peerConnection.iceConnectionState === 'connected' || peerConnection.iceConnectionState === 'completed') {
6323
  callIceFailureCount = 0;
6324
+ if (pendingIceRecoveryTimer) {
6325
+ clearTimeout(pendingIceRecoveryTimer);
6326
+ pendingIceRecoveryTimer = null;
6327
+ }
6328
  return;
6329
  }
6330
 
6331
+ if (peerConnection.iceConnectionState === 'disconnected') {
6332
+ if (pendingIceRecoveryTimer) {
6333
+ clearTimeout(pendingIceRecoveryTimer);
6334
+ }
6335
+ // 'disconnected' can be temporary on mobile networks; wait before forcing ICE restart.
6336
+ pendingIceRecoveryTimer = setTimeout(() => {
6337
+ pendingIceRecoveryTimer = null;
6338
+ if (!peerConnection) return;
6339
+ if (peerConnection.iceConnectionState === 'disconnected' || peerConnection.iceConnectionState === 'failed') {
6340
+ showCallWarningThrottled('⚠️ Connection unstable, trying to reconnect...');
6341
+ attemptIceRecovery(peerId);
6342
+ }
6343
+ }, 3000);
6344
+ return;
6345
+ }
6346
+
6347
+ if (peerConnection.iceConnectionState === 'failed') {
6348
+ if (pendingIceRecoveryTimer) {
6349
+ clearTimeout(pendingIceRecoveryTimer);
6350
+ pendingIceRecoveryTimer = null;
6351
+ }
6352
  attemptIceRecovery(peerId);
6353
  }
6354
  };
 
6419
  currentCallPeerId = peerId;
6420
  currentCallPeerName = peerName;
6421
  callIceFailureCount = 0;
6422
+ forceRelayOnly = rtcRuntimeConfig?.iceTransportPolicy === 'relay';
6423
 
6424
  openCallDialog(peerName);
6425
  await ensureRtcConfigLoaded();
 
6601
  callIceFailureCount = 0;
6602
  forceRelayOnly = false;
6603
  activeIceServers = [];
6604
+ if (pendingIceRecoveryTimer) {
6605
+ clearTimeout(pendingIceRecoveryTimer);
6606
+ pendingIceRecoveryTimer = null;
6607
+ }
6608
 
6609
  if (localCallStream) {
6610
  localCallStream.getTracks().forEach((track) => track.stop());
index.html CHANGED
@@ -3048,7 +3048,7 @@
3048
  <div class="chat-header-title" id="chatTitle">💬 Select a friend to chat</div>
3049
  </div>
3050
  <div class="chat-header-actions">
3051
- <span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v2.6.8</span>
3052
  <button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
3053
  <i class="fas fa-archive"></i>
3054
  </button>
@@ -3665,7 +3665,7 @@
3665
 
3666
  <script src="/socket.io/socket.io.js"></script>
3667
  <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
3668
- <script src="client.js?v=2.6.8"></script>
3669
  </body>
3670
  </html>
3671
 
 
3048
  <div class="chat-header-title" id="chatTitle">💬 Select a friend to chat</div>
3049
  </div>
3050
  <div class="chat-header-actions">
3051
+ <span class="build-badge mobile-essential" id="buildVersionBadge" title="Frontend build version">v2.6.9</span>
3052
  <button class="header-btn mobile-essential" onclick="toggleArchiveChat()" title="Archive chat">
3053
  <i class="fas fa-archive"></i>
3054
  </button>
 
3665
 
3666
  <script src="/socket.io/socket.io.js"></script>
3667
  <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
3668
+ <script src="client.js?v=2.6.9"></script>
3669
  </body>
3670
  </html>
3671
 
package.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "discord-like-app",
3
- "version": "2.6.8",
4
  "main": "server.js",
5
  "scripts": {
6
  "dev": "nodemon server.js",
 
1
  {
2
  "name": "discord-like-app",
3
+ "version": "2.6.9",
4
  "main": "server.js",
5
  "scripts": {
6
  "dev": "nodemon server.js",
server.js CHANGED
@@ -98,7 +98,8 @@ app.get('/api/rtc-config', (req, res) => {
98
  const turnUrlsRaw = process.env.TURN_URLS || '';
99
  const turnUsername = process.env.TURN_USERNAME || '';
100
  const turnCredential = process.env.TURN_CREDENTIAL || '';
101
- const forceRelay = String(process.env.RTC_FORCE_RELAY || '').toLowerCase() === 'true';
 
102
 
103
  let iceServers = [...defaultIceServers];
104
 
 
98
  const turnUrlsRaw = process.env.TURN_URLS || '';
99
  const turnUsername = process.env.TURN_USERNAME || '';
100
  const turnCredential = process.env.TURN_CREDENTIAL || '';
101
+ const relayFlag = String(process.env.RTC_FORCE_RELAY || 'true').toLowerCase();
102
+ const forceRelay = relayFlag === 'true' || relayFlag === '1' || relayFlag === 'yes';
103
 
104
  let iceServers = [...defaultIceServers];
105