Skip to main content

tor_proto/relay/reactor/
backward.rs

1//! A relay's view of the backward (towards the client) state of a circuit.
2
3use crate::circuit::UniqId;
4use crate::circuit::reactor::ControlHandler;
5use crate::circuit::reactor::backward::{BackwardCellDisposition, BackwardHandler};
6use crate::crypto::cell::{InboundRelayLayer, RelayCellBody};
7use crate::relay::RelayCircChanMsg;
8use crate::util::err::ReactorError;
9use crate::{Error, HopNum};
10
11use tor_cell::chancell::msg::{AnyChanMsg, Relay};
12use tor_cell::chancell::{BoxedCellBody, ChanCmd, CircId};
13use tor_cell::relaycell::msg::SendmeTag;
14
15use std::result::Result as StdResult;
16
17use tracing::debug;
18
19/// Placeholder for our custom control message type.
20type CtrlMsg = ();
21
22/// Placeholder for our custom control command type.
23type CtrlCmd = ();
24
25/// Relay-specific state for the backward reactor.
26pub(crate) struct Backward {
27    /// The cryptographic state for this circuit for client-bound cells.
28    crypto_in: Box<dyn InboundRelayLayer + Send>,
29}
30
31impl Backward {
32    /// Create a new [`Backward`].
33    pub(crate) fn new(crypto_in: Box<dyn InboundRelayLayer + Send>) -> Self {
34        Self { crypto_in }
35    }
36}
37
38impl BackwardHandler for Backward {
39    type CircChanMsg = RelayCircChanMsg;
40
41    fn encrypt_relay_cell(
42        &mut self,
43        cmd: ChanCmd,
44        body: &mut RelayCellBody,
45        hop: Option<HopNum>,
46    ) -> SendmeTag {
47        // TODO(DEDUP): the hop is used on the client side
48        let _ = hop;
49        self.crypto_in.originate(cmd, body)
50    }
51
52    fn handle_backward_cell(
53        &mut self,
54        circ_uniq_id: UniqId,
55        circ_id: CircId,
56        cell: RelayCircChanMsg,
57    ) -> StdResult<BackwardCellDisposition, ReactorError> {
58        let disp = match cell {
59            RelayCircChanMsg::Relay(c) => {
60                let body = c.into_relay_body();
61
62                let mut relay_body = body.into();
63                self.crypto_in
64                    .encrypt_inbound(ChanCmd::RELAY, &mut relay_body);
65
66                let cell = AnyChanMsg::Relay(Relay::from(BoxedCellBody::from(relay_body)));
67
68                BackwardCellDisposition::Forward(cell)
69            }
70            RelayCircChanMsg::RelayEarly(_) => {
71                return Err(ReactorError::Err(Error::CircProto(
72                    "Received inbound RELAY_EARLY cell".into(),
73                )));
74            }
75            RelayCircChanMsg::Destroy(d) => {
76                debug!(
77                    circ_uniq_id = %circ_uniq_id,
78                    backward_circ_id = %circ_id,
79                    reason = %d.reason(),
80                    "Received inbound DESTROY, circuit shutting down",
81                );
82
83                // We don't need to send a DESTROY cell down the channel,
84                // because that's handled implicitly by our Drop implementation
85                return Err(ReactorError::Shutdown);
86            }
87            RelayCircChanMsg::PaddingNegotiate(_) => {
88                return Err(ReactorError::Err(Error::CircProto(
89                    "R2R PADDING_NEGOTIATE not supported".into(),
90                )));
91            }
92        };
93
94        Ok(disp)
95    }
96}
97
98impl ControlHandler for Backward {
99    type CtrlMsg = CtrlMsg;
100    type CtrlCmd = CtrlCmd;
101
102    fn handle_cmd(&mut self, cmd: Self::CtrlCmd) -> StdResult<(), ReactorError> {
103        let () = cmd;
104        Ok(())
105    }
106
107    fn handle_msg(&mut self, msg: Self::CtrlMsg) -> StdResult<(), ReactorError> {
108        let () = msg;
109        Ok(())
110    }
111}