Skip to content

fix: make magic peripheral handoff resilient (+ consistency cleanups)#56

Closed
MegaManSec wants to merge 2 commits into
mainfrom
fix/peripheral-handoff-resilient
Closed

fix: make magic peripheral handoff resilient (+ consistency cleanups)#56
MegaManSec wants to merge 2 commits into
mainfrom
fix/peripheral-handoff-resilient

Conversation

@MegaManSec

Copy link
Copy Markdown
Owner

Summary

Cherry-picks upstream iFurySt/magic-switch@270c1e5 ("fix: make magic peripheral handoff resilient"), original author preserved, plus follow-up cleanups so the new code matches this repo's conventions.

What the upstream fix does

  • Take-from-peer now refreshes a stale local pairing. A peripheral can sit at paired=true while openConnection() fails; the old path gave up and left it connectable on neither Mac. It now -removes the stale bond and re-pairs.
  • CONNECT_ALL / CONNECT_ONE receivers ack the real connect result instead of "command received", so a failed handoff is actually rolled back / reclaimed by the sender.
  • Auto-accepts pairing confirmation; surfaces a "Pairing Failed" notification.
  • Raises the handoff timeouts so the connection survives until the real ack.

Cleanups in this PR (2nd commit — no behavior change)

  • Extract the duplicated 75 body-timeout literal into a named NetworkDeviceStore.handoffBodyTimeout, documenting the cross-file invariant (must exceed the 60s pair watchdog and stay <= IncomingConnection.idleTimeout).
  • Document why idleTimeout was raised 30s -> 75s.
  • Comment the post--remove Thread.sleep (settles the async unbond; only blocks the background bluetoothQueue, never the UI).

Cherry-pick adaptations (folded into the 1st commit)

  • Conflict in BluetoothPeripheralStore: this fork hoisted reconnectInFlight.remove(id) to the top of reclaimIfPeerIsFree's else-block, so I dropped upstream's duplicate and kept the new connectPeripheral(...) signature.
  • continueAdoption (this fork's "adopt when the peer vanishes" feature, which upstream never saw) called the now-removed 2-arg connectPeripheral. Adapted to the new signature with refreshPairingBeforeConnect: false, preserving current behavior.

Open question

continueAdoption is itself a take-from-peer path, so arguably it should pass refreshPairingBeforeConnect: true to get the same stale-pairing fix. Left false to avoid changing behavior beyond the cherry-pick — say the word to flip it.

Verification

xcodebuild -scheme "Magic Switch" -configuration Debug -> BUILD SUCCEEDED.

iFurySt and others added 2 commits June 18, 2026 19:40
Follow-up cleanups on the cherry-picked handoff-resilience fix so the new
code matches the surrounding conventions. No behavior change.

- Extract the duplicated `75` body-timeout literal (CONNECT_ALL /
  CONNECT_ONE) into a named `NetworkDeviceStore.handoffBodyTimeout`, and
  document the cross-file invariant: it must exceed the receiver's pair
  watchdog (60s) and stay <= IncomingConnection.idleTimeout, so neither
  side gives up before the receiver acks the real connect result.
- Explain on IncomingConnection.idleTimeout why it was raised 30s -> 75s.
- Add a rationale comment to the post-`-remove` Thread.sleep: it lets the
  async unbond settle, and only stalls the background bluetoothQueue, never
  the UI.
@MegaManSec MegaManSec closed this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants