tor-proto: Add support for sending XON messages
This MR adds support to the DataReader
and to the circuit reactor for sending XON messages. Support for sending XOFF messages was added previously in !3094 (merged).
With XON/XOFF flow control, XON and XOFF messages are sent on a stream to indicate the rate that the other party should send data at. For example if the OP sends an XOFF to an exit, then the exit should stop sending stream data to the OP. If the OP sends an XON containing a rate to an exit, then the exit should send stream data to the OP at the given rate.
The general loop is:
- Inbound RELAY_DATA cells arrive on stream. If these cells arrive too fast and too much stream data is buffered, an XOFF is sent on the stream. (This was implemented in !3094 (merged)).
- A notification is sent to the stream reader informing it that the reactor needs a drain-rate update.
- The stream reader receives this notification, and once the stream buffer is emptied (for example by the application reading data from the SOCKS port), the stream reader sends a new drain rate to the circuit reactor.
- The circuit reactor receives the new drain rate.
- Either:
- The reactor sends an XON with the new drain rate. Then goto (1).
- Or the reactor decides that too much inbound data is buffered and it shouldn't send an XON. Then goto (2). (Note that in this entire loop, we are asynchronously sending messages between the stream reader and the circuit reactor. This means that in the time it takes for the drain rate sent in (3) to reach the circuit reactor, the circuit reactor may have received a lot of inbound RELAY_DATA cells on the stream. So that is what this case handles.)
This MR does not implement rate estimation, so for now we send XON messages with an "unlimited" rate. This means that the exit would alternate between "not sending" and "sending as fast as possible". Typically applications read from the SOCKS port faster than the network can send stream data, so XOFF messages are rare in practice.
All of this XON/XOFF functionality is effectively disabled, even when the experimental "flowctl-cc" feature is enabled. We currently never use congestion control and flow control for circuits.
The functionality here is manually tested with curl and ctrl-z. The plan for testing is in #2069.
I'm away next week, so a review can be a low priority.
/cc @gabi-250 More circuit reactor changes.