Skip to content

Commit 7845931

Browse files
committed
Merge pull request #125 from SloMR/feat/ImproveStableConnection
Client: Improves WebRTC connection stability
2 parents a857200 + 3c0fb81 commit 7845931

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

client/src/app/core/services/communication/webrtc-signaling.service.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,17 @@ export class WebRTCSignalingService {
331331
return;
332332
}
333333

334+
// Check and close existing connection first to prevent memory leaks
335+
const existingConnection = this.peerConnections.get(targetUser);
336+
if (existingConnection) {
337+
this.logger.warn(
338+
'createPeerConnection',
339+
`Peer connection already exists for ${targetUser}, closing old one`
340+
);
341+
existingConnection.close();
342+
this.peerConnections.delete(targetUser);
343+
}
344+
334345
const peerConnection = new RTCPeerConnection(RTC_CONFIGURATION);
335346

336347
let iceGatheringTimeout: ReturnType<typeof setTimeout> | null = null;
@@ -635,10 +646,14 @@ export class WebRTCSignalingService {
635646
}
636647
}
637648

649+
// Set lock while processing offer to prevent concurrent connection attempts
650+
this.connectionLocks.add(targetUser);
651+
638652
const peerConnection = this.createPeerConnection(targetUser);
639653

640654
if (!peerConnection) {
641655
this.logger.error('handleOffer', `PeerConnection missing for ${targetUser}`);
656+
this.connectionLocks.delete(targetUser);
642657
return;
643658
}
644659

@@ -651,6 +666,8 @@ export class WebRTCSignalingService {
651666
return peerConnection.setLocalDescription(answer);
652667
})
653668
.then(() => {
669+
// Release lock after answer is sent
670+
this.connectionLocks.delete(targetUser);
654671
const response: SignalMessage = {
655672
type: SignalMessageType.ANSWER,
656673
data: peerConnection.localDescription,
@@ -661,6 +678,8 @@ export class WebRTCSignalingService {
661678
this.processCandidateQueue(targetUser);
662679
})
663680
.catch((error) => {
681+
// Release lock on error
682+
this.connectionLocks.delete(targetUser);
664683
this.logger.error('handleOffer', `Error handling offer: ${error}`);
665684
if (this.wsService.isConnected()) {
666685
this.toaster.warning(
@@ -741,6 +760,17 @@ export class WebRTCSignalingService {
741760
clearTimeout(existingTimeout);
742761
}
743762

763+
// Clear reconnection timeout to prevent collision with state mismatch recovery
764+
const reconnectionTimeout = this.reconnectionTimeouts.get(targetUser);
765+
if (reconnectionTimeout) {
766+
clearTimeout(reconnectionTimeout);
767+
this.reconnectionTimeouts.delete(targetUser);
768+
this.logger.debug(
769+
'handleStateMismatch',
770+
`Cleared reconnection timeout for ${targetUser} to prevent collision`
771+
);
772+
}
773+
744774
const timeoutId = setTimeout(() => {
745775
this.stateMismatchTimeouts.delete(targetUser);
746776
this.initiateConnection(targetUser);

client/src/app/features/chat/chat.component.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,10 +1667,26 @@ export class ChatComponent implements OnInit, OnDestroy, AfterViewInit {
16671667
this.connectionInitTimeouts = [];
16681668

16691669
this.logger.info('initiateConnectionsWithMembers', 'Initiating connections with other members');
1670-
const otherMembers = this.members.filter((m) => m !== this.userService.user);
1670+
1671+
// Filter out self AND already connected/connecting peers
1672+
const otherMembers = this.members.filter((m) => {
1673+
if (m === this.userService.user) {
1674+
return false;
1675+
}
1676+
1677+
// Skip if already connected or connecting
1678+
const isConnectedOrConnecting = this.webrtcService.isConnectedOrConnecting(m);
1679+
if (isConnectedOrConnecting) {
1680+
this.logger.debug(
1681+
'initiateConnectionsWithMembers',
1682+
`Skipping ${m} - already connected/connecting`
1683+
);
1684+
}
1685+
return !isConnectedOrConnecting;
1686+
});
16711687

16721688
if (otherMembers.length === 0) {
1673-
this.logger.warn('initiateConnectionsWithMembers', 'No other members to connect to');
1689+
this.logger.info('initiateConnectionsWithMembers', 'No new members to connect to');
16741690
return;
16751691
}
16761692

@@ -1680,9 +1696,9 @@ export class ChatComponent implements OnInit, OnDestroy, AfterViewInit {
16801696
// Determine if we should be the caller for this member
16811697
const shouldInitiate = this.userService.user.localeCompare(member) < 0;
16821698

1683-
// Callers start at 1000ms, callees wait an additional 800ms
1699+
// Callers start at 1000ms, callees wait an additional 500ms
16841700
const baseDelay = 1000;
1685-
const staggerDelay = shouldInitiate ? 0 : 800;
1701+
const staggerDelay = shouldInitiate ? 0 : 500;
16861702
const indexDelay = index * 100; // Small delay between multiple members
16871703

16881704
const timeoutId = setTimeout(

0 commit comments

Comments
 (0)