You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apply the unconnected socket requirements to added paths (#63)
Description
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:
if (QuicAddrIsWildCard(&Path->Route.RemoteAddress) && QuicAddrGetPort(&Path->Route.RemoteAddress) == 0) {
UdpConfig.RemoteAddress = &Connection->Paths[0].Route.RemoteAddress;
} else {
UdpConfig.RemoteAddress = &Path->Route.RemoteAddress;
}
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.RemoteAddress is left NULL when the parameter is set, which is what marks the binding unconnected and lets the lookup match on local port alone.
The two requirements QuicConnStart already enforces are enforced here too, before the binding is built:
A shared binding. An unconnected socket receives datagrams from any remote address, so packets are matched to a connection by connection ID alone. Returns QUIC_STATUS_INVALID_STATE.
A specific local address. 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. Returns QUIC_STATUS_INVALID_PARAMETER.
Both log through ConnError with the same wording QuicConnStart uses. The early goto Error is safe: the label only releases PathID, which is NULL at that point.
Status code change
The local address requirement now reports QUIC_STATUS_INVALID_PARAMETER rather than QUIC_STATUS_INVALID_STATE, in QuicConnStart as well. It describes an address the caller passed in, not a state the connection is in. docs/Settings.md and the existing test are updated to match.
Testing
Two tests, because ADD_PATH reaches this code by two different routes.
QuicTestUnconnectedSocketAddPathBeforeStart — before the connection is started, QuicConnAddPath configures Paths[0] and returns without opening a binding (if (!Connection->State.Connected) goto Done;), so the address it sets has to satisfy QuicConnStart'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, QuicConnAddPath runs QuicConnOpenNewPath and 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:
Requested Expected Enforced by
same local + same remote QUIC_STATUS_ADDRESS_IN_USE QuicConnAddPath's duplicate check
wildcard local + other remote QUIC_STATUS_INVALID_PARAMETER the new check in QuicConnOpenNewPath
same local + other remote success, local port unchanged UdpConfig.RemoteAddress = NULL
Both 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.
No compiler warnings.
Not covered: the !ShareBinding branch in QuicConnOpenNewPath. Setting QUIC_PARAM_CONN_UNCONNECTED_UDP_SOCKET requires a shared binding, and QUIC_PARAM_CONN_SHARE_UDP_BINDING cannot 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.md records the corrected status code and notes that each additional path opened with QUIC_PARAM_CONN_ADD_PATH needs a specific local address for the same reason.
Copy file name to clipboardExpand all lines: docs/Settings.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -229,7 +229,7 @@ By default a client connection's UDP socket is connected to the server's address
229
229
230
230
The parameter requires `QUIC_PARAM_CONN_SHARE_UDP_BINDING` to also be set: an unconnected socket receives datagrams from any remote address, so incoming packets are matched to a connection by connection ID alone, and only a shared binding gives the connection a non-zero length source connection ID. Setting it without one fails with `QUIC_STATUS_INVALID_STATE`.
231
231
232
-
It also requires a specific local address, set with `QUIC_PARAM_CONN_LOCAL_ADDRESS`. A connected socket takes its source address from the kernel when it is connected; an unconnected one does not, and the connection's first packet goes out before anything has been learned from the peer, so the address to send from has to be named. The port may be left as 0 to let the stack choose one. Starting a connection with an unconnected socket and no local address, or a wildcard one, fails the connection with `QUIC_STATUS_INVALID_STATE`.
232
+
It also requires a specific local address, set with `QUIC_PARAM_CONN_LOCAL_ADDRESS`. A connected socket takes its source address from the kernel when it is connected; an unconnected one does not, and the connection's first packet goes out before anything has been learned from the peer, so the address to send from has to be named. The port may be left as 0 to let the stack choose one. Starting a connection with an unconnected socket and no local address, or a wildcard one, fails the connection with `QUIC_STATUS_INVALID_PARAMETER`. The same applies to each additional path opened with `QUIC_PARAM_CONN_ADD_PATH`, whose local address must likewise be a specific one.
233
233
234
234
To place several connections on one local port, start the first connection, read its local address back with `QUIC_PARAM_CONN_LOCAL_ADDRESS`, and set that address on the subsequent connections along with the same two parameters.
0 commit comments