tor_proto/tunnel/circuit/
celltypes.rs1use crate::{Error, Result};
8use derive_deftly::Deftly;
9use std::fmt::{self, Display};
10use tor_cell::chancell::{
11 msg::{self as chanmsg, AnyChanMsg},
12 ChanMsg,
13};
14use tor_memquota::derive_deftly_template_HasMemoryCost;
15
16#[cfg_attr(docsrs, doc(cfg(feature = "testing")))]
19#[derive(Debug)]
20#[allow(unreachable_pub)] #[allow(clippy::exhaustive_enums)]
22pub enum CreateResponse {
23 Destroy(chanmsg::Destroy),
25 CreatedFast(chanmsg::CreatedFast),
27 Created2(chanmsg::Created2),
29}
30
31impl Display for CreateResponse {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 use CreateResponse as CR;
34 match self {
35 CR::Destroy(destroy) => write!(f, "DESTROY({})", destroy.reason()),
36 CR::CreatedFast(_) => Display::fmt("CREATED_FAST", f),
37 CR::Created2(_) => Display::fmt("CREATED2", f),
38 }
39 }
40}
41
42impl TryFrom<AnyChanMsg> for CreateResponse {
43 type Error = crate::Error;
44
45 fn try_from(m: AnyChanMsg) -> Result<CreateResponse> {
46 match m {
47 AnyChanMsg::Destroy(m) => Ok(CreateResponse::Destroy(m)),
48 AnyChanMsg::CreatedFast(m) => Ok(CreateResponse::CreatedFast(m)),
49 AnyChanMsg::Created2(m) => Ok(CreateResponse::Created2(m)),
50 _ => Err(Error::ChanProto(format!(
51 "Got a {} in response to circuit creation",
52 m.cmd()
53 ))),
54 }
55 }
56}
57
58#[derive(Debug, Deftly)]
61#[allow(unreachable_pub)] #[derive_deftly(HasMemoryCost)]
63pub enum ClientCircChanMsg {
64 Relay(chanmsg::Relay),
67 Destroy(chanmsg::Destroy),
69 }
71
72impl TryFrom<AnyChanMsg> for ClientCircChanMsg {
73 type Error = crate::Error;
74
75 fn try_from(m: AnyChanMsg) -> Result<ClientCircChanMsg> {
76 match m {
77 AnyChanMsg::Destroy(m) => Ok(ClientCircChanMsg::Destroy(m)),
78 AnyChanMsg::Relay(m) => Ok(ClientCircChanMsg::Relay(m)),
79 _ => Err(Error::ChanProto(format!(
80 "Got a {} cell on an open circuit",
81 m.cmd()
82 ))),
83 }
84 }
85}
86
87#[cfg(test)]
88mod test {
89 #![allow(clippy::bool_assert_comparison)]
91 #![allow(clippy::clone_on_copy)]
92 #![allow(clippy::dbg_macro)]
93 #![allow(clippy::mixed_attributes_style)]
94 #![allow(clippy::print_stderr)]
95 #![allow(clippy::print_stdout)]
96 #![allow(clippy::single_char_pattern)]
97 #![allow(clippy::unwrap_used)]
98 #![allow(clippy::unchecked_duration_subtraction)]
99 #![allow(clippy::useless_vec)]
100 #![allow(clippy::needless_pass_by_value)]
101 use super::*;
103
104 #[test]
105 fn create_response() {
106 use tor_cell::chancell::msg::{self, AnyChanMsg};
107 fn good(m: AnyChanMsg) {
108 assert!(CreateResponse::try_from(m).is_ok());
109 }
110 fn bad(m: AnyChanMsg) {
111 assert!(CreateResponse::try_from(m).is_err());
112 }
113
114 good(msg::Destroy::new(2.into()).into());
115 good(msg::CreatedFast::new(&b"this offer is unrepeatable"[..]).into());
116 good(msg::Created2::new(&b"guaranteed guaranteed"[..]).into());
117 bad(msg::CreateFast::new(&b"for a lifetime or more"[..]).into());
118 bad(msg::Versions::new([1, 2, 3]).unwrap().into());
119 }
120
121 #[test]
122 fn client_circ_chan_msg() {
123 use tor_cell::chancell::msg::{self, AnyChanMsg};
124 fn good(m: AnyChanMsg) {
125 assert!(ClientCircChanMsg::try_from(m).is_ok());
126 }
127 fn bad(m: AnyChanMsg) {
128 assert!(ClientCircChanMsg::try_from(m).is_err());
129 }
130
131 good(msg::Destroy::new(2.into()).into());
132 bad(msg::CreatedFast::new(&b"guaranteed in this world"[..]).into());
133 bad(msg::Created2::new(&b"and the next"[..]).into());
134 good(msg::Relay::new(&b"guaranteed guaranteed"[..]).into());
135 bad(msg::AnyChanMsg::RelayEarly(
136 msg::Relay::new(&b"for the world and its mother"[..]).into(),
137 ));
138 bad(msg::Versions::new([1, 2, 3]).unwrap().into());
139 }
140}