Apply the unconnected socket requirements to added paths - #63
Merged
Conversation
QUIC_PARAM_CONN_UNCONNECTED_UDP_SOCKET was only honoured on the connection's first path. QuicConnOpenNewPath, which opens the binding for every path added afterwards with QUIC_PARAM_CONN_ADD_PATH, still passed the path's remote address to QuicLibraryGetBinding, so the added path got a connected socket and a binding of its own even though the connection had asked for the opposite. Carry the parameter through, and enforce the same two requirements QuicConnStart does before doing so. A shared binding is required, since an unconnected socket is demultiplexed by connection ID alone. A specific local address is required, since an unconnected socket has no source address of its own and the path's first packet goes out before anything has been learned from the peer. The local address requirement now reports QUIC_STATUS_INVALID_PARAMETER rather than QUIC_STATUS_INVALID_STATE, in both QuicConnOpenNewPath and QuicConnStart: it describes an address the caller passed in, not a state the connection is in. Two tests cover the two ways ADD_PATH reaches this code. Before the connection is started it configures Paths[0] and defers the binding to QuicConnStart; afterwards it opens a binding of its own through QuicConnOpenNewPath. The latter checks that a wildcard local address is rejected, that the address pair already in use is not a new path, and that a path to a second server shares the local port the connection is already on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
Description
QUIC_PARAM_CONN_UNCONNECTED_UDP_SOCKETwas only honoured on the connection's first path.QuicConnOpenNewPath, which opens the binding for every path added afterwards withQUIC_PARAM_CONN_ADD_PATH, still passed the path's remote address toQuicLibraryGetBinding:So the added path got a connected socket and a binding of its own, even though the connection had asked for the opposite. A connection using the parameter to keep several destinations on one local port would silently get a second local port as soon as it added a path.
Changes
UdpConfig.RemoteAddressis leftNULLwhen the parameter is set, which is what marks the binding unconnected and lets the lookup match on local port alone.The two requirements
QuicConnStartalready enforces are enforced here too, before the binding is built:QUIC_STATUS_INVALID_STATE.QUIC_STATUS_INVALID_PARAMETER.Both log through
ConnErrorwith the same wordingQuicConnStartuses. The earlygoto Erroris safe: the label only releasesPathID, which isNULLat that point.Status code change
The local address requirement now reports
QUIC_STATUS_INVALID_PARAMETERrather thanQUIC_STATUS_INVALID_STATE, inQuicConnStartas well. It describes an address the caller passed in, not a state the connection is in.docs/Settings.mdand the existing test are updated to match.Testing
Two tests, because
ADD_PATHreaches this code by two different routes.QuicTestUnconnectedSocketAddPathBeforeStart— before the connection is started,QuicConnAddPathconfiguresPaths[0]and returns without opening a binding (if (!Connection->State.Connected) goto Done;), so the address it sets has to satisfyQuicConnStart's requirement instead. Covers a wildcard local address being rejected, and a specific one connecting on the address that was named.QuicTestUnconnectedSocketAddPathAfterStart— after the handshake,QuicConnAddPathrunsQuicConnOpenNewPathand the binding is opened there. Two listeners are used so the added path has a remote address a connected socket could not have reached. Covers:QUIC_STATUS_ADDRESS_IN_USEQuicConnAddPath's duplicate checkQUIC_STATUS_INVALID_PARAMETERQuicConnOpenNewPathUdpConfig.RemoteAddress = NULLBoth new checks were verified to be the ones failing the tests by disabling each in turn and watching the corresponding case flip to a failure.
Results:
*UnconnectedSocket*:*Path*:*Migration*:*ConnectionParam*:*Datagram*passes in full: 112 tests.*Basic*passes in full: 497 tests.Not covered: the
!ShareBindingbranch inQuicConnOpenNewPath. SettingQUIC_PARAM_CONN_UNCONNECTED_UDP_SOCKETrequires a shared binding, andQUIC_PARAM_CONN_SHARE_UDP_BINDINGcannot be changed once the connection is started, so the combination is unreachable through the API. It stays as a guard against a binding that was un-shared afterwards.Documentation
docs/Settings.mdrecords the corrected status code and notes that each additional path opened withQUIC_PARAM_CONN_ADD_PATHneeds a specific local address for the same reason.