fix: remove untracked disconnect timer
CodeQL Analysis / Analyze CodeQL (push) Has been cancelled
Deploy Application / deploy (push) Has been cancelled
Mirror to Codeberg / mirror (push) Has been cancelled
Mirror to PrivacyGuides / mirror (push) Has been cancelled

This commit is contained in:
lockbitchat
2026-05-17 23:16:14 -04:00
parent 86a96b0121
commit f2a4276b31
2 changed files with 56 additions and 3 deletions
@@ -11735,9 +11735,6 @@ async processMessage(data) {
this.intentionalDisconnect = true; this.intentionalDisconnect = true;
window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect'); window.EnhancedSecureCryptoUtils.secureLog.log('info', 'Starting intentional disconnect');
this.sendDisconnectNotification(); this.sendDisconnectNotification();
setTimeout(() => {
this.sendDisconnectNotification();
}, 100);
// Stop every timer-backed subsystem first. // Stop every timer-backed subsystem first.
this._stopAllTimers(); this._stopAllTimers();
+56
View File
@@ -114,6 +114,62 @@ try {
assert.equal(scheduled[0].cleared, true); assert.equal(scheduled[0].cleared, true);
assert.equal(disconnectCalls, 0); assert.equal(disconnectCalls, 0);
} }
// Intentional disconnect performs notification before teardown without leaving a delayed retry timer behind.
{
let notifications = 0;
const manager = {
_sessionAlive: true,
_activeTimers: new Set(),
intentionalDisconnect: false,
fileTransferSystem: null,
dataChannel: null,
heartbeatChannel: null,
peerConnection: null,
decoyTimers: new Map(),
decoyChannels: new Map(),
packetBuffer: new Map(),
chunkQueue: [],
processedMessageIds: new Set(),
messageCounter: 0,
keyVersions: new Map(),
oldKeys: new Map(),
currentKeyVersion: 0,
lastKeyRotation: 0,
sequenceNumber: 0,
expectedSequenceNumber: 0,
replayWindow: new Set(),
messageQueue: [],
_heartbeatConfig: {},
_secureLog() {},
_stopAllTimers: EnhancedSecureWebRTCManager.prototype._stopAllTimers,
stopHeartbeat() {},
stopFakeTrafficGeneration() {},
_wipeEphemeralKeys() {},
_hardWipeOldKeys() {},
_secureCleanupCryptographicMaterials() {},
_clearVerificationStates() {},
_secureWipeMemory() {},
_forceGarbageCollection() { return Promise.resolve(); },
sendDisconnectNotification() { notifications += 1; },
onStatusChange() {},
onKeyExchange() {},
onVerificationRequired() {}
};
const timersBeforeDisconnect = timers.length;
EnhancedSecureWebRTCManager.prototype.disconnect.call(manager);
assert.equal(notifications, 1);
assert.equal(manager._activeTimers.size, 0);
assert.equal(timers.length, timersBeforeDisconnect);
// A second disconnect/reconnect-style cycle still does not accumulate deferred timers.
manager._sessionAlive = true;
EnhancedSecureWebRTCManager.prototype.disconnect.call(manager);
assert.equal(notifications, 2);
assert.equal(manager._activeTimers.size, 0);
assert.equal(timers.length, timersBeforeDisconnect);
}
} finally { } finally {
globalThis.setTimeout = realSetTimeout; globalThis.setTimeout = realSetTimeout;
globalThis.clearTimeout = realClearTimeout; globalThis.clearTimeout = realClearTimeout;