tor_proto/tunnel/reactor/circuit/
create.rs

1//! Helpers for handling CREATE* cells.
2
3use crate::tunnel::circuit::celltypes::CreateResponse;
4use crate::{Error, Result};
5use tor_cell::chancell;
6use tor_cell::chancell::msg::{AnyChanMsg, HandshakeType};
7
8/// An object that can put a given handshake into a ChanMsg for a CREATE*
9/// cell, and unwrap a CREATED* cell.
10pub(super) trait CreateHandshakeWrap {
11    /// Construct an appropriate ChanMsg to hold this kind of handshake.
12    fn to_chanmsg(&self, bytes: Vec<u8>) -> AnyChanMsg;
13    /// Decode a ChanMsg to an appropriate handshake value, checking
14    /// its type.
15    fn decode_chanmsg(&self, msg: CreateResponse) -> Result<Vec<u8>>;
16}
17
18/// A CreateHandshakeWrap that generates CREATE_FAST and handles CREATED_FAST.
19pub(super) struct CreateFastWrap;
20
21impl CreateHandshakeWrap for CreateFastWrap {
22    fn to_chanmsg(&self, bytes: Vec<u8>) -> AnyChanMsg {
23        chancell::msg::CreateFast::new(bytes).into()
24    }
25
26    fn decode_chanmsg(&self, msg: CreateResponse) -> Result<Vec<u8>> {
27        use CreateResponse::*;
28        match msg {
29            CreatedFast(m) => Ok(m.into_handshake()),
30            Destroy(_) => Err(Error::CircRefused(
31                "Relay replied to CREATE_FAST with DESTROY.",
32            )),
33            _ => Err(Error::CircProto(format!(
34                "Relay replied to CREATE_FAST with unexpected cell: {}",
35                msg
36            ))),
37        }
38    }
39}
40
41/// A CreateHandshakeWrap that generates CREATE2 and handles CREATED2
42pub(super) struct Create2Wrap {
43    /// The handshake type to put in the CREATE2 cell.
44    pub(super) handshake_type: HandshakeType,
45}
46
47impl CreateHandshakeWrap for Create2Wrap {
48    fn to_chanmsg(&self, bytes: Vec<u8>) -> AnyChanMsg {
49        chancell::msg::Create2::new(self.handshake_type, bytes).into()
50    }
51
52    fn decode_chanmsg(&self, msg: CreateResponse) -> Result<Vec<u8>> {
53        use CreateResponse::*;
54        match msg {
55            Created2(m) => Ok(m.into_body()),
56            Destroy(_) => Err(Error::CircRefused("Relay replied to CREATE2 with DESTROY.")),
57            _ => Err(Error::CircProto(format!(
58                "Relay replied to CREATE2 with unexpected cell {}",
59                msg
60            ))),
61        }
62    }
63}