Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connection::stream_send() reports Err::Done for finished streams #1695

Open
bwoebi opened this issue Dec 18, 2023 · 3 comments
Open

Connection::stream_send() reports Err::Done for finished streams #1695

bwoebi opened this issue Dec 18, 2023 · 3 comments

Comments

@bwoebi
Copy link
Contributor

bwoebi commented Dec 18, 2023

This case occurs with streams closed with STOP_SENDING, then a fin bit being received too, then the data being read via Connection::stream_recv().

In high-level terms:

server opens stream - sends some data
client reads some data and writes data
server reads that data, sends STOP_SENDING, and writes some data, then sends the fin bit in a separate empty message of length 0
client sees stream as readable, then reads the data
client tries to write some data ... gets Err::Done from stream_send().

As far as I gathered from the documentation, Err::Done is supposed to be returned when no data could be written because of no capacity and Err::StreamStopped returned when the stream has been closed by the peer.

In this specific case though, the stream seems to already have been freed by quiche, thus StreamMap::get_or_create() returns Err::Done, which Connection::stream_send() simply forwards.

I would expect an Err::StreamStopped, or at least an Err::InvalidStreamState (signaling that a stream with that id could not be created, in that case, obviously, because the stream id is not matching what's allowed for the client/server).

Currently I'm working around it with an extra check of Connection::stream_writable() for Err::InvalidStreamState whenever Err::Done is reported, but that seems unnecessary/wrong to me, why would that be needed?

In case this is the expected behaviour though, I would like to ask for a note in the documentation to check stream_writable() explicitly if Err::Done is returned.

@LPardue
Copy link
Contributor

LPardue commented Dec 18, 2023

Thanks for the detailed report. Thatspecific sequence would lead to the stream being collected, and hence always get_or_create will return Done.

For stream_recv we return a InvalidStreamState if the stream doesn't exist

.ok_or(Error::InvalidStreamState(stream_id))?;

We could do similar for stream_send, capture the Done and convert it to InvalidStreamState at

let stream = self.get_or_create_stream(stream_id, true)?;
. Using StopSending for the collected streams seems like it would be confusing two different stream states.

@bwoebi
Copy link
Contributor Author

bwoebi commented Dec 18, 2023

Yes, an InvalidStreamState would be probably most appropriate here with the current architecture.

It would be great if there were a solution for #1299 too, but I suppose quiche has no mode where we can instruct it to explicitly keep streams alive until they are manually collected with a method call (Connection::stream_free()) or such.

@LPardue
Copy link
Contributor

LPardue commented Dec 18, 2023

Oh thanks for the reminder on that. I guess if we're considering g changing the API, we might want to follow through with a solution that can satisfy both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants