Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions quest/m1/lite06-requests-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# [S] A moq-lite-06 session's auth requests end when its peer leaves

## Goal

On a moq-lite-06 session, the server's `Request::requests()` stream ends once

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requests() is on server::Handshake (rs/moq-net/src/server.rs:1143), returning auth::Requests; auth::Request is the per-token type and has no such method. Handshake::requests() (or just "the server's requests() stream") keeps the pointer accurate.

the client cancels or the connection closes, as it does on lite-07 and
moq-transport. A server loop draining it then ends instead of holding a task,
and its session, for each departed lite-06 client.

## Plan

Decided 2026-11-11 (maintainer, /quest-complete pick of
[moq-dev/moq#8516](https://github.com/moq-dev/moq/pull/8516)): βœ… plan this in
m1 (rejected: m3; ignoring it).

Found while iterating #8516: in `rs/moq-ffi/src/test.rs`,
`a_credential_without_auth_is_unsupported` dials a `token_server("moq-lite-06")`
whose task drains `request.requests()` in a `while let`. After the client's
`session.cancel(0)`, that loop never ends, so the test calls
`serving.abort()` (the test lands with that PR). The queue behind
`requests()` closes only through `auth::Handle::close`, which every moq-lite
version reaches from `Driver::end` or `Driver`'s `Drop` in
`rs/moq-net/src/lite/session.rs`. So suspect the lite-06 driver not ending
Comment on lines +21 to +23

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The queue has a second closer, and it is the one a departed peer should trigger: Supervisor::poll in rs/moq-net/src/session.rs:734 calls auth.close(...) as soon as the transport reports closed, on every protocol. Since Handle::close closes the app's Acceptor::App queue, saying the lite drivers are the only path leaves out the code that should already have ended this stream on lite-06, which changes what the implementer instruments first.

Technical details
# The supervisor also closes the auth queue

## Affected sites
- `quest/m1/lite06-requests-end.md:21-23` β€” says every moq-lite version reaches `Handle::close` only from `Driver::end` or `Driver`'s `Drop` in `rs/moq-net/src/lite/session.rs`.
- `rs/moq-net/src/session.rs:734` β€” `Supervisor::poll`, on `closed_watch.poll_closed`, calls `self.auth.close(err.clone())` before the protocol is polled (`rs/moq-net/src/driver.rs` polls the supervisor first).
- `rs/moq-net/src/auth.rs:1448` β€” `Handle::close` β†’ `State::abort` returns the `Acceptor::App(queue)` β†’ `Pending::close`, so `Requests::poll_next` yields `None`.

## Required outcome
- The plan names the supervisor's close-on-transport-close as the path that should end the stream when a peer leaves, and asks why it never fired for lite-06, rather than treating `Driver::end` as the only closer.

## Suggested approach (optional)
- Reword to name both, e.g. `Driver::end`/`Driver`'s `Drop` plus the session supervisor's close watch, and add "or its supervisor never saw the transport close" to the suspects.

(check what it watches to see the peer leave; see `has_setup_stream`) or the
server keeping it alive, rather than the stream itself.

- Reproduce in moq-net or moq-tokio with a lite-06 pair: the client cancels,
and the server's `requests()` must yield `None` within the test's timeout.
Check lite-07 and moq-transport the same way.
- Fix the root cause, then drop `serving.abort()` from that test so it
asserts the server task ends on its own.

Public API: none expected. Wire: none.