1
//! Helpers for handling CREATE* cells.
2

            
3
use crate::circuit::celltypes::CreateResponse;
4
use crate::{Error, Result};
5
use tor_cell::chancell;
6
use 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.
10
pub(crate) 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.
19
pub(crate) struct CreateFastWrap;
20

            
21
impl CreateHandshakeWrap for CreateFastWrap {
22
12
    fn to_chanmsg(&self, bytes: Vec<u8>) -> AnyChanMsg {
23
12
        chancell::msg::CreateFast::new(bytes).into()
24
12
    }
25

            
26
12
    fn decode_chanmsg(&self, msg: CreateResponse) -> Result<Vec<u8>> {
27
        use CreateResponse::*;
28
12
        match msg {
29
12
            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
12
    }
39
}
40

            
41
/// A CreateHandshakeWrap that generates CREATE2 and handles CREATED2
42
pub(crate) struct Create2Wrap {
43
    /// The handshake type to put in the CREATE2 cell.
44
    pub(crate) handshake_type: HandshakeType,
45
}
46

            
47
impl CreateHandshakeWrap for Create2Wrap {
48
36
    fn to_chanmsg(&self, bytes: Vec<u8>) -> AnyChanMsg {
49
36
        chancell::msg::Create2::new(self.handshake_type, bytes).into()
50
36
    }
51

            
52
36
    fn decode_chanmsg(&self, msg: CreateResponse) -> Result<Vec<u8>> {
53
        use CreateResponse::*;
54
36
        match msg {
55
36
            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
36
    }
63
}