Fix reconnection with a cached base token#107
Conversation
When a previously obtained base token is passed to `create_apns_connection`, reconnection would hang or crash due to two issues: 1. The ConnectAck filter required `ack.token == cached_token`, but the server may return a different token or omit the token field entirely (when it accepts the cached one). This caused `_receive` to block forever. 2. `base_token` property skipped `_connected.wait()` when `_base_token` was pre-set, allowing callers to send commands before the TCP connection and APNs handshake were actually established. 3. When the server accepts a cached token, ConnectAck does not include a token field (item 0x03 is absent), causing `ack.token` to be None. The old code would crash on the `assert ack.token == self._base_token`. Changes: - Accept any ConnectAck regardless of token value - Always await `_connected` event before exposing `base_token` - Handle all token scenarios: None (accepted), same, changed, or new This matches real `apsd` behavior where the daemon persists the base token to `com.apple.apsd.plist` and reuses it across device reboots.
Have you actually observed the server behaving in this manner? I don't recall encountering this during testing (I must admit it was a long time ago though).
It appears that If you can send a log proving that you encountered the above issue and it wasn't just an AI hallucinating it, then I can probably accept this PR. |
|
Alright, LGTM. |

Summary
_receivehanging forever when reconnecting with a pre-cachedbase_token, caused by theConnectAckfilter requiring an exact token matchConnectAck(ack.tokenisNone)base_tokenproperty returned before the TCP connection was establishedBackground
When the
tokenparameter is passed tocreate_apns_connection(e.g. restoring a previously persisted token), three things go wrong:The
ConnectAckreceive filter checksc.token == self._base_token. But the server may return a different token, or omit the token field entirely (item0x03absent) when it accepts the cached one. This causes_receiveto wait forever.The
base_tokenproperty skips_connected.wait()when_base_tokenis already set, so callers can attempt to send commands before_connis initialized.assert ack.token == self._base_tokencrashes whenack.token is None.This matches real
apsdbehavior: the daemon persists the base token tocom.apple.apsd.plistand sends it on reconnect (e.g. after a device reboot). The server typically accepts it silently.