Skip to content

Drop queued packets from a previous connection on reconnect - #20

Open
ps2 wants to merge 1 commit into
LoopKit:mainfrom
ps2:drain-stale-inputs-on-reconnect
Open

ps2 wants to merge 1 commit into
LoopKit:mainfrom
ps2:drain-stale-inputs-on-reconnect

Conversation

@ps2

@ps2 ps2 commented Oct 2, 2026

Copy link
Copy Markdown

When the phone reconnects, packets still queued in cmdInput, dataInput and messageInput from the old connection get consumed by the session negotiated on the new one. This drains those queues in the CentralConnected handler, before the new connection's first command is read.

The crash this fixes

The phone connected twice four seconds apart while the sim was re-establishing a session:

20:00:40  ** New connection from: 46:79:19:94:e0:78
20:00:40  ReadMessage interrupted by a new connection
20:00:40  pkg pod; new connection — re-establishing session
20:00:40  pkg pod; Listening for commands
20:00:44  ** New connection from: 46:79:19:94:e0:78
20:00:44  pkg pod; got first command: as string: 06010417aeea04
20:00:45  handling CMD notifications on new connection ...
          ... EAP-AKA challenge parsed, response sent ...
20:00:45  pkg pod; success? 2b971c90b9dfc439b54eb55e222b8bd3f0ff78d67ce36e308d01ca5a5af7c3
FATA      pkg pod; error parsing the EAP-AKA Success packet: error parsing eap message: invalid eap code: 43 ...

The "success" payload is 31 bytes of ciphertext: an encrypted command left in the queue, read where EapAka() expected the plaintext EAP-Success. The first command was also consumed before the new connection's notifications were set up, so it too came from the earlier connection. On a clean connection a minute earlier the same phone sent the expected success? 03000004 and the session came up normally, so the phone side is fine.

Change

  • drainInputs() does a non-blocking drain of the three input channels.
  • Called from CentralConnected after the message loop is stopped and connGen is bumped. With LnxMaxConnections(1) the previous central is gone by then, so anything left in the queues belongs to it.

Testing

  • GOOS=linux GOARCH=arm64 go build ./... and go vet ./pkg/bluetooth/ ./pkg/pod/ pass.
  • Installed on a Raspberry Pi; not yet run against a reproduction of the double reconnect.

Not addressed here

  • EapAka(), StartActivation() and the pairing path read with ReadMessage(), which doesn't watch reconnected, so a reconnect in the middle of a handshake can still leave them blocked.
  • Parse failures in the handshake still log.Fatalf. Restarting the session instead of exiting would make the sim recover from bad input on its own.

When the phone reconnects, packets still queued in cmdInput, dataInput
and messageInput from the old connection were consumed by the session
negotiated on the new one. In one case a stale encrypted command was
read as the EAP-AKA Success, which failed to parse ("invalid eap code:
43") and killed the simulator with log.Fatalf.

Drain those queues in the CentralConnected handler, before the new
connection's first command is read.
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.

1 participant