private-octopus / picoquic

Minimal implementation of the QUIC protocol
MIT License
523 stars 153 forks source link

Ability to create back pressure on a stream from the receiver side #1625

Open samkearney opened 5 months ago

samkearney commented 5 months ago

Hi, thanks for the great QUIC implementation and please close this issue if there is something in the API I haven't seen. I'm wondering if there's a way for the receiving side of a stream to manually create backpressure on that stream, for example, by not receiving data for some amount of time. It is useful for applications that receive data into fixed size buffers, and want the data to naturally back up and block the sending side of the stream if they can't process it fast enough.

From what I can tell, if I am using picoquic_packet_loop(), the library will give me a callback with picoquic_callback_stream_data every time it has received data to deliver on a stream, and after this callback is done it will unconditionally consider that data to be consumed by the application. Ideally there would be some way for the application to say "I wasn't able to process all this data" and it would remain unprocessed in the QUIC receive queue.

For an example of what I mean, MsQuic also uses a callback-oriented model to deliver received data, but it provides a way for the callback to signal back that it did not consume all of the data.

huitema commented 5 months ago

That's not easy. It would require adding a data queue to the stream structure, but that in itself will not create back pressure -- the peer could just keep sending as long as there are credits available. (Creating the queue in the app is just as easy as creating it in the transport stack, and there are some benefits, for example if app and stack are running in different threads.)

Applying the back-pressure requires retaining the flow control credits so the peer will quickly starve and stop sending. The stack is currently programmed to send these credits automatically when it sees that they might be needed. We would need a way for the application to signal that it want to restrict these credits. I suppose we could do something like that, independently of whether the queue is in the app or in the transport.

Any idea on how to draw an API to do that?