Repository navigation
fix(iOS): arm TLS before connectToHost so connect is never announced pre-handshake - #238
Open
MidnightCoke wants to merge 1 commit into
Open
MidnightCoke wants to merge 1 commit into
MidnightCoke wants to merge 1 commit into
Conversation
…pre-handshake `connect:` called `startTLS:` after `connectToHost:`, and `startTLS:` set `_tls` only at its end, after building the TLS settings. With client-certificate auth that build imports a PKCS#12 and touches the keychain, which can outlast a LAN connect. `didConnectToHost:` runs on the delegate queue (the main queue) and is gated on `if (!_tls)`, so a connect that completed first announced a plain `connect` for a socket whose handshake had not begun. `connectTLS` wires `secureConnect` to that event, so callers were told the socket was secure and anything written from the callback went out ahead of the TLS packet. Build the settings and set `_tls` before `connectToHost:`, then queue `startTLS:` on the socket right behind the connect; GCDAsyncSocket starts the handshake once connected. `_tls` is cleared again if the connect never started. Also clear `_connecting` on the plain-connect path, from Rapsssito#217: without it a later `new TLSSocket(socket)` upgrade announces a second `connect` from `socketDidSecure`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Fixes #237.
The bug
connect:armed TLS after starting the connect:startTLS:sets_tls = trueonly once the settings dictionary is built, and for client-certificate auth that build imports a PKCS#12 and touches the keychain.didConnectToHost:runs on the delegate queue (dispatch_get_main_queue()) and is gated onif (!_tls), so a connect that finished first announced a plainconnectfor a socket whose handshake had not begun.connectTLSwiressecureConnectto that event (src/index.js:49), so callers were told the socket was secure before the handshake and writes from the callback went out ahead of the TLS packet.The change
startTLS:intotlsSettingsForOptions:, declared in the class extension so the header is untouched. The body is unchanged; only the last two lines becomereturn settings;.connect:, build the settings and set_tlsbeforeconnectToHost:, then queue[_tcpSocket startTLS:settings]right behind the connect. CocoaAsyncSocket queues it as a write packet and starts the handshake once connected, so there is no ordering left fordidConnectToHost:to lose: it can never observe_tls == falsefor a TLS connect._tlsis cleared again when the connect never started._connectingon the plain-connect path indidConnectToHost:. This line is taken from fix(iOS): defer startTLS until didConnectToHost #217 and fixes a second bug: without it a laternew TLSSocket(existingSocket)upgrade announces a duplicateconnectfromsocketDidSecure.The keychain work stays on the module queue rather than moving to the main queue.
Testing
connectbefore any handshake byte.:8002) and LG webOS (:3001). Before it, the prematureconnectwas read as a socket that never completed its handshake and torn down in a retry loop; in one release the median connect time went from 517 ms to 5589 ms. After it,connectis unconditionally a secure connect._connectingline is reviewed but not exercised by our app, which only usesconnectTLS. It carries fix(iOS): defer startTLS until didConnectToHost #217's own testing, not ours.Relationship to #217
#217 found the same race first and fixes it by deferring
startTLS:intodidConnectToHost:. Credit to @manoaxcend. Two reasons this PR takes the other direction:_tlsOptionsPendingis assigned afterconnectToHost:returns, on a different queue from the one that reads it, so the window is narrowed rather than closed. Setting_tlsbefore the connect is dispatched removes it entirely.Happy to close this in favour of #217 plus a one-line suggestion if you prefer that shape.
🤖 Generated with Claude Code