tor_proto/stream/flow_ctrl/window/
state.rs1use tor_cell::relaycell::flow_ctrl::{Xoff, Xon, XonKbpsEwma};
4use tor_cell::relaycell::msg::{AnyRelayMsg, Sendme};
5use tor_cell::relaycell::{RelayCmd, RelayMsg, UnparsedRelayMsg};
6
7use crate::congestion::sendme::{
8 self, StreamRecvWindow, StreamSendWindow, cmd_counts_towards_windows,
9};
10use crate::stream::flow_ctrl::state::{FlowCtrlHooks, HalfStreamFlowCtrlHooks};
11use crate::stream::{RECV_WINDOW_INIT, STREAM_READER_BUFFER};
12use crate::{Error, Result};
13
14#[cfg(doc)]
15use crate::stream::flow_ctrl::state::StreamFlowCtrl;
16
17#[derive(Debug)]
19pub(crate) struct WindowFlowCtrl {
20 window: StreamSendWindow,
22}
23
24impl WindowFlowCtrl {
25 pub(crate) fn new(window: StreamSendWindow) -> Self {
30 Self { window }
31 }
32}
33
34impl FlowCtrlHooks for WindowFlowCtrl {
35 fn can_send<M: RelayMsg>(&self, msg: &M) -> bool {
36 !sendme::cmd_counts_towards_windows(msg.cmd()) || self.window.window() > 0
37 }
38
39 fn about_to_send(&mut self, msg: &AnyRelayMsg) -> Result<()> {
40 if sendme::cmd_counts_towards_windows(msg.cmd()) {
41 self.window.take().map(|_| ())
42 } else {
43 Ok(())
46 }
47 }
48
49 fn put_for_incoming_sendme(&mut self, msg: UnparsedRelayMsg) -> Result<()> {
50 let _sendme = msg
51 .decode::<Sendme>()
52 .map_err(|e| Error::from_bytes_err(e, "failed to decode stream sendme message"))?
53 .into_msg();
54
55 self.window.put()
56 }
57
58 fn handle_incoming_xon(&mut self, _msg: UnparsedRelayMsg) -> Result<()> {
59 let msg = "XON messages not allowed with window flow control";
60 Err(Error::CircProto(msg.into()))
61 }
62
63 fn handle_incoming_xoff(&mut self, _msg: UnparsedRelayMsg) -> Result<()> {
64 let msg = "XOFF messages not allowed with window flow control";
65 Err(Error::CircProto(msg.into()))
66 }
67
68 fn maybe_send_xon(&mut self, _rate: XonKbpsEwma, _buffer_len: usize) -> Result<Option<Xon>> {
69 let msg = "XON messages cannot be sent with window flow control";
70 Err(Error::CircProto(msg.into()))
71 }
72
73 fn maybe_send_xoff(&mut self, _buffer_len: usize) -> Result<Option<Xoff>> {
74 let msg = "XOFF messages cannot be sent with window flow control";
75 Err(Error::CircProto(msg.into()))
76 }
77
78 fn inbound_queue_max_len(&self) -> usize {
79 STREAM_READER_BUFFER
82 }
83}
84
85#[derive(Debug)]
87pub(crate) struct HalfStreamWindowFlowCtrl {
88 inner: WindowFlowCtrl,
92 recv_window: StreamRecvWindow,
97}
98
99impl HalfStreamWindowFlowCtrl {
100 pub(crate) fn new(flow_ctrl: WindowFlowCtrl) -> Self {
102 Self {
103 inner: flow_ctrl,
104 recv_window: StreamRecvWindow::new(RECV_WINDOW_INIT),
108 }
109 }
110}
111
112impl HalfStreamFlowCtrlHooks for HalfStreamWindowFlowCtrl {
113 fn handle_incoming_dropped(&mut self, msg_count: u16) -> Result<()> {
114 self.recv_window.decrement_n(msg_count)
115 }
116
117 fn handle_incoming_msg(&mut self, msg: UnparsedRelayMsg) -> Result<Option<UnparsedRelayMsg>> {
118 match msg.cmd() {
119 RelayCmd::SENDME => {
120 self.inner.put_for_incoming_sendme(msg)?;
121 Ok(None)
122 }
123 RelayCmd::XON => {
124 self.inner.handle_incoming_xon(msg)?;
125 Ok(None)
126 }
127 RelayCmd::XOFF => {
128 self.inner.handle_incoming_xoff(msg)?;
129 Ok(None)
130 }
131 cmd if cmd_counts_towards_windows(cmd) => {
132 let _ = self.recv_window.take()?;
134 Ok(Some(msg))
135 }
136 _ => Ok(Some(msg)),
138 }
139 }
140}