mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 14:25:20 +00:00
Keep timeout-restore queues parked through the same-generation ready path
The deferral-buffer rework routes quarantine restores through a same-generation ready transition that no longer rebuilds capability state — but it drained both outbound queues unconditionally there, bypassing the pending-convergence gate. Honor the restore reason in that branch too: retrying deferred inbound ciphertext stays (it is receive-side and safe under restored keys), while queue drains wait for the convergence retry's establishment exactly as on the new-generation path. Terminal restores keep draining immediately. Also pre-drain the establishment's serialized forced announce in the terminal-restore test so the tap only observes restore-driven traffic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4892,8 +4892,23 @@ extension BLEService {
|
||||
// A quarantined transport restored the same cryptographic
|
||||
// generation. Its capability proof and announce state never
|
||||
// became stale; only work queued while outbound keys were paused
|
||||
// needs one idempotent ready transition.
|
||||
// needs one idempotent ready transition. Retrying the bounded
|
||||
// early-ciphertext queue is receive-side and therefore always
|
||||
// safe under the restored keys.
|
||||
noisePacketHandler.handleSessionAuthenticated(normalizedPeerID)
|
||||
#if DEBUG
|
||||
_test_onPrivateMediaSessionReconciled?(normalizedPeerID)
|
||||
#endif
|
||||
if deferOutboundUntilConvergence {
|
||||
// Timeout-restore: the counterpart may have completed the
|
||||
// replacement handshake and discarded these keys, so
|
||||
// encrypting the parked queues here would lose them silently.
|
||||
// The restore's mandatory convergence retry — or any later
|
||||
// handshake the reconnect policy initiates — re-enters this
|
||||
// transition with a fresh generation and drains them under
|
||||
// keys both sides hold.
|
||||
return
|
||||
}
|
||||
sendPendingMessagesAfterHandshake(for: normalizedPeerID)
|
||||
sendPendingNoisePayloadsAfterHandshake(for: normalizedPeerID)
|
||||
return
|
||||
|
||||
@@ -666,6 +666,10 @@ struct BLEServiceCoreTests {
|
||||
)
|
||||
await ble._test_drainNoiseMessagePipeline()
|
||||
#expect(ble.canDeliverSecurely(to: alicePeerID))
|
||||
// The establishment transition enqueues its forced announce as a
|
||||
// separate serialized phase; drain again so it lands before the tap
|
||||
// and cannot masquerade as restore-driven announce traffic below.
|
||||
await ble._test_drainNoiseMessagePipeline()
|
||||
|
||||
let outbound = OutboundPacketTap()
|
||||
ble._test_onOutboundPacket = outbound.record
|
||||
|
||||
Reference in New Issue
Block a user