Repository navigation
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aged noq reports the handshake complete before the client's last flight has left: congestion control and pacing can hold part of it back, so a worker stopped the moment the dial resolved stranded the server. The driver now hands the connection over only once noq has no handshake data left to send, and a dial whose worker stopped fails instead of pending forever. Needs Connection::has_pending_handshake_data from moq-noq-proto, which is not released yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
Author
|
Closing: the maintainer abandoned this quest. If a worker stops, its connection dies anyway, and the peer times out either way (on the handshake instead of idle). That doesn't justify a new noq method and noq's first tagged release. #4064 deletes the quest. (written by Opus 5.5) |
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.
Draft, blocked: this needs
Connection::has_pending_handshake_data()inmoq-noq-proto. That method is not in 1.3.0, so CI will fail to compile until the fork ships it and the pin moves.Implements quest/m1/uring-handshake-flush.md.
Problem
An io_uring dial resolved on noq's
Event::Connected. That event fires when the client's handshake completes locally, before its final flight has been sent. When congestion control or pacing holds back part of that flight, a worker stopped as soon as the dial resolves never sends the rest. The server then times out while the client holds a connection that looks established.Reproduced on Linux 7.0 (loopback): a client with a ~20 KB mTLS certificate dialed 20 times, dropping its worker as each dial resolved. The server completed 0/20 handshakes before this change and 20/20 after it. With a small single-datagram final flight, it completes 20/20 either way. The window only opens when the flight is split: a multi-datagram client chain, a slow link where the pacer's burst is one MTU, or a flight bigger than the initial congestion window. On the relay, that means mTLS cluster dials.
Fix
Connectedthe driver only records that the handshake completed. After each flush it hands the connection over once noq has no Initial or Handshake crypto left to send, which means the whole flight has been staged on the socket. Worker teardown already submits staged sends (tests/teardown.rs). Accepted connections go through the same path, but their flight is always empty by then.establishfails withError::Ioif the worker has been dropped, so the dial errors instead of pending forever.Why noq needs a change
None of noq's public signals says when the last handshake flight has left:
poll_transmitreturningNonemeans either "nothing queued" or "blocked by cwnd or pacing".stats().frame_tx.cryptocounts frames, not the flight.HandshakeConfirmedis exact but adds a full RTT to every dial.So the fork needs this accessor (validated locally by patching a copy of
moq-noq-proto1.3.0 with it):A noq-proto unit test can pin it: set
max_outgoing_bytes_per_second(Some(12_000))on the client, and with no time passing the ClientHello uses up the pacer's only burst. After the server's flight, the client is connected andhas_pending_handshake_data()is true. It turns false afterpair.drive().Tests
New
rs/moq-uring/tests/handshake.rs, kernel-gated like the other moq-uring tests:a_stopped_dial_sends_all_of_a_split_final_flight: 20 one-shot dials with a 20 KB client chain, under Loss and Delay congestion control. Fails without the fix (server accepts 0).a_worker_stopped_mid_dial_fails_it: drops the worker mid-handshake, and the dial returnsError::Io. Fails without the fix (it stays pending).a_stopped_dial_finishes_the_server_handshake: normal dials still resolve promptly, and every one completes on the server.just checkwas run with the local noq patch. Only the temporary[patch]line inCargo.tomlfailed formatting, and it is not committed.cargo clippy -p moq-uring --all-targets --all-features -D warningsand the fullcargo test -p moq-uringpass.Impact
Endpoint::connectandclient::connectnow say when the dial resolves.Decisions taken unattended
HandshakeConfirmed: it costs no extra RTT. Header parsing was rejected because it is unsound under congestion blocking.moq-noq-proto, bump the pin, then mark this PR ready and delete the quest in it.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code