suunto_nautic: skip foreign frames on a contended link instead of erroring - #2
Merged
Merged
Conversation
…oring The BLE link is shared by one central at a time, but another client can still hold a session: when the official Suunto app keeps a live logbook subscription, its Whiteboard 0x07 subscribe-result frames leak onto the link on a different handle. Both fetch loops capped skips at 8 and then returned DC_STATUS_DATAFORMAT, so a burst of that foreign traffic aborted the download with a misleading data-format error and the user got zero dives. Distinguish foreign-but-well-formed frames (0xA5 magic, not our DATA/handle) from genuinely malformed ones. Skip the former freely (bounded only against an unbounded loop) and keep the tight cap for the latter. When our DATA never gets a turn on a saturated link, the iostream read now times out first, so the failure surfaces as a clean DC_STATUS_TIMEOUT rather than DATAFORMAT. This does not make a contended download succeed -- the user still has to close the app holding the subscription -- but it turns a corrupt-data error into an honest "couldn't read the device" outcome and never truncates a good download on a brief foreign burst. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016pyeZodmZ5cTDJysokDsCb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The Nautic/Ocean BLE link is single-central, but another client can still hold a session on it. When a user leaves the official Suunto app running with a live logbook subscription, that subscription's Whiteboard
0x07subscribe-result frames leak onto the shared link (on a different handle from our fetch).Both fetch loops (
suunto_nautic_device_paginated_fetchandsuunto_nautic_short_fetch_frame) skipped non-DATA frames but capped skips at 8, then returnedDC_STATUS_DATAFORMAT. A burst of that foreign traffic blows through the cap immediately, so the download aborts with a misleading data-format error and the user gets zero dives.Confirmed mechanism (decompiled
libmds.so):0x07routes throughWhiteboard::handleClientResultwith(type & 0xe) == 6, i.e. it is the Suunto app's subscription traffic, not a response to our request. Field-confirmed with multiple paying users on production; every case clears once the Suunto app is fully closed.Change
0xA5magic, but not our0x05/handle) from genuinely malformed/truncated ones.MAX_FOREIGN_SKIPSto guard against an unbounded loop); keep the tightMAX_MALFORMED_SKIPS = 8cap for malformed frames →DATAFORMAT.dc_iostream_readtimes out first, so the failure now surfaces as a cleanDC_STATUS_TIMEOUTinstead ofDATAFORMAT.suunto_nautic_frame_wellformed()/suunto_nautic_frame_is_our_data()helpers used by both loops.What this does and does not do
Downstream note
The terminal status for the pure-contention case changes
DATAFORMAT→TIMEOUT. Any consumer keying a "close the Suunto app" hint offDATAFORMAT + no divesshould broaden it to includeTIMEOUT(tracked on our side as a Currents follow-up to DEE-45).Testing
swift buildclean; existingswift testsuite green (25 tests, 1 skipped).