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};
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_id: UniqId,
55        cell: RelayCircChanMsg,
56    ) -> StdResult<BackwardCellDisposition, ReactorError> {
57        let disp = match cell {
58            RelayCircChanMsg::Relay(c) => {
59                let body = c.into_relay_body();
60
61                let mut relay_body = body.into();
62                self.crypto_in
63                    .encrypt_inbound(ChanCmd::RELAY, &mut relay_body);
64
65                let cell = AnyChanMsg::Relay(Relay::from(BoxedCellBody::from(relay_body)));
66
67                BackwardCellDisposition::Forward(cell)
68            }
69            RelayCircChanMsg::RelayEarly(_) => {
70                return Err(ReactorError::Err(Error::CircProto(
71                    "Received inbound RELAY_EARLY cell".into(),
72                )));
73            }
74            RelayCircChanMsg::Destroy(_) => {
75                debug!(circ_id=%circ_id, "Received inbound DESTROY cell");
76                return Err(ReactorError::Shutdown);
77            }
78            RelayCircChanMsg::PaddingNegotiate(_) => {
79                return Err(ReactorError::Err(Error::CircProto(
80                    "R2R PADDING_NEGOTIATE not supported".into(),
81                )));
82            }
83        };
84
85        Ok(disp)
86    }
87}
88
89impl ControlHandler for Backward {
90    type CtrlMsg = CtrlMsg;
91    type CtrlCmd = CtrlCmd;
92
93    fn handle_cmd(&mut self, cmd: Self::CtrlCmd) -> StdResult<(), ReactorError> {
94        let () = cmd;
95        Ok(())
96    }
97
98    fn handle_msg(&mut self, msg: Self::CtrlMsg) -> StdResult<(), ReactorError> {
99        let () = msg;
100        Ok(())
101    }
102}