Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,13 @@ extension SphinxOnionManager {
restoredContactInfoTracker = []
}

// NOTE: This timer is independent of the Rust CHUNK_TIMEOUT_SECS buffer timeout.
// Extending CHUNK_TIMEOUT_SECS in sphinx-ffi/src/chunk.rs alone does not extend how
// long this client waits — the timer below still fires at kMessageFetchTimeout (30s)
// and clears all fetch callbacks regardless of the server-side buffer tolerance.
// To fully benefit from a longer Rust chunk timeout, kMessageFetchTimeout must also
// be scaled accordingly — that is a separate client-side change and an explicit
// fast-follow candidate.
func startMessageFetchTimeoutTimer() {
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,25 @@ extension SphinxOnionManager {
return getMessageTag(messages: rr.msgs, isSendingMessage: isSendingMessage)
}

// MARK: - state_mp Persistence Requirement
//
// Any call that returns a RunReturn — including all fetch/chunk-bearing calls — MUST
// flow through handleRunReturn() (or at minimum updateStateMap()) before discarding
// the result. If it does not, the state_mp delta is silently dropped: any in-flight
// chunk buffer associated with that call will restart from scratch on the next
// fragment, with no error surfaced to the user.
//
// Fetch functions and their persistence status (as of 2026-07):
// • fetch_msgs_batch → exercised end-to-end via fetchMessageBlock
// (SphinxOnionManager+AccountRestoreExtension.swift)
// • fetch_msgs_batch_per_contact → exercised end-to-end via fetchMessagePerContactBlock
// (SphinxOnionManager+AccountRestoreExtension.swift)
// • fetchMsgs → NO live call site in this app's business logic;
// persistence is only theoretically covered until a
// real caller is added and wired through handleRunReturn.
// • fetchMsgsBatchOkkey → NO live call site in this app's business logic;
// persistence is only theoretically covered until a
// real caller is added and wired through handleRunReturn.
func updateStateMap(stateMap: Data?) {
if let stateMap = stateMap {
let _ = storeOnionState(inc: [UInt8](stateMap))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ class SphinxOnionManager : NSObject, @unchecked Sendable {

static let kMqttKeepAlive: UInt16 = 15
static let kConnectionTimeoutInterval: TimeInterval = 15.0
// Client-side fetch watchdog — independent of Rust CHUNK_TIMEOUT_SECS
//
// This timeout drives startMessageFetchTimeoutTimer(), which calls clearFetchCallbacks()
// and abandons an in-flight fetch/restore after 30 seconds. It is entirely independent
// of the Rust-side CHUNK_TIMEOUT_SECS buffer timeout in sphinx-ffi/src/chunk.rs.
// Increasing CHUNK_TIMEOUT_SECS on the server/FFI side (e.g. to 300s) does NOT make
// this client wait longer — this watchdog will still fire at 30s and clear callbacks,
// preventing the app from benefiting from the extended Rust buffer tolerance.
// Scaling kMessageFetchTimeout to match is a separate, out-of-scope follow-up change.
static let kMessageFetchTimeout: TimeInterval = 30.0

var reconnectionTimer: Timer? = nil
Expand Down