mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-26 20:05:22 +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
|
// A quarantined transport restored the same cryptographic
|
||||||
// generation. Its capability proof and announce state never
|
// generation. Its capability proof and announce state never
|
||||||
// became stale; only work queued while outbound keys were paused
|
// 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)
|
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)
|
sendPendingMessagesAfterHandshake(for: normalizedPeerID)
|
||||||
sendPendingNoisePayloadsAfterHandshake(for: normalizedPeerID)
|
sendPendingNoisePayloadsAfterHandshake(for: normalizedPeerID)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -666,6 +666,10 @@ struct BLEServiceCoreTests {
|
|||||||
)
|
)
|
||||||
await ble._test_drainNoiseMessagePipeline()
|
await ble._test_drainNoiseMessagePipeline()
|
||||||
#expect(ble.canDeliverSecurely(to: alicePeerID))
|
#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()
|
let outbound = OutboundPacketTap()
|
||||||
ble._test_onOutboundPacket = outbound.record
|
ble._test_onOutboundPacket = outbound.record
|
||||||
|
|||||||
Reference in New Issue
Block a user