xref: /webrtc/ice/src/control/mod.rs (revision 5d8fe953)
1 #[cfg(test)]
2 mod control_test;
3 
4 use stun::attributes::*;
5 use stun::checks::*;
6 use stun::message::*;
7 
8 use std::fmt;
9 
10 /// Common helper for ICE-{CONTROLLED,CONTROLLING} and represents the so-called Tiebreaker number.
11 #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
12 pub struct TieBreaker(pub u64);
13 
14 pub(crate) const TIE_BREAKER_SIZE: usize = 8; // 64 bit
15 
16 impl TieBreaker {
17     /// Adds Tiebreaker value to m as t attribute.
add_to_as(self, m: &mut Message, t: AttrType) -> Result<(), stun::Error>18     pub fn add_to_as(self, m: &mut Message, t: AttrType) -> Result<(), stun::Error> {
19         let mut v = vec![0; TIE_BREAKER_SIZE];
20         v.copy_from_slice(&self.0.to_be_bytes());
21         m.add(t, &v);
22         Ok(())
23     }
24 
25     /// Decodes Tiebreaker value in message getting it as for t type.
get_from_as(&mut self, m: &Message, t: AttrType) -> Result<(), stun::Error>26     pub fn get_from_as(&mut self, m: &Message, t: AttrType) -> Result<(), stun::Error> {
27         let v = m.get(t)?;
28         check_size(t, v.len(), TIE_BREAKER_SIZE)?;
29         self.0 = u64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);
30         Ok(())
31     }
32 }
33 /// Represents ICE-CONTROLLED attribute.
34 #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
35 pub struct AttrControlled(pub u64);
36 
37 impl Setter for AttrControlled {
38     /// Adds ICE-CONTROLLED to message.
add_to(&self, m: &mut Message) -> Result<(), stun::Error>39     fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> {
40         TieBreaker(self.0).add_to_as(m, ATTR_ICE_CONTROLLED)
41     }
42 }
43 
44 impl Getter for AttrControlled {
45     /// Decodes ICE-CONTROLLED from message.
get_from(&mut self, m: &Message) -> Result<(), stun::Error>46     fn get_from(&mut self, m: &Message) -> Result<(), stun::Error> {
47         let mut t = TieBreaker::default();
48         t.get_from_as(m, ATTR_ICE_CONTROLLED)?;
49         self.0 = t.0;
50         Ok(())
51     }
52 }
53 
54 /// Represents ICE-CONTROLLING attribute.
55 #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
56 pub struct AttrControlling(pub u64);
57 
58 impl Setter for AttrControlling {
59     // add_to adds ICE-CONTROLLING to message.
add_to(&self, m: &mut Message) -> Result<(), stun::Error>60     fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> {
61         TieBreaker(self.0).add_to_as(m, ATTR_ICE_CONTROLLING)
62     }
63 }
64 
65 impl Getter for AttrControlling {
66     // get_from decodes ICE-CONTROLLING from message.
get_from(&mut self, m: &Message) -> Result<(), stun::Error>67     fn get_from(&mut self, m: &Message) -> Result<(), stun::Error> {
68         let mut t = TieBreaker::default();
69         t.get_from_as(m, ATTR_ICE_CONTROLLING)?;
70         self.0 = t.0;
71         Ok(())
72     }
73 }
74 
75 /// Helper that wraps ICE-{CONTROLLED,CONTROLLING}.
76 #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
77 pub struct AttrControl {
78     role: Role,
79     tie_breaker: TieBreaker,
80 }
81 
82 impl Setter for AttrControl {
83     // add_to adds ICE-CONTROLLED or ICE-CONTROLLING attribute depending on Role.
add_to(&self, m: &mut Message) -> Result<(), stun::Error>84     fn add_to(&self, m: &mut Message) -> Result<(), stun::Error> {
85         if self.role == Role::Controlling {
86             self.tie_breaker.add_to_as(m, ATTR_ICE_CONTROLLING)
87         } else {
88             self.tie_breaker.add_to_as(m, ATTR_ICE_CONTROLLED)
89         }
90     }
91 }
92 
93 impl Getter for AttrControl {
94     // get_from decodes Role and Tiebreaker value from message.
get_from(&mut self, m: &Message) -> Result<(), stun::Error>95     fn get_from(&mut self, m: &Message) -> Result<(), stun::Error> {
96         if m.contains(ATTR_ICE_CONTROLLING) {
97             self.role = Role::Controlling;
98             return self.tie_breaker.get_from_as(m, ATTR_ICE_CONTROLLING);
99         }
100         if m.contains(ATTR_ICE_CONTROLLED) {
101             self.role = Role::Controlled;
102             return self.tie_breaker.get_from_as(m, ATTR_ICE_CONTROLLED);
103         }
104 
105         Err(stun::Error::ErrAttributeNotFound)
106     }
107 }
108 
109 /// Represents ICE agent role, which can be controlling or controlled.
110 /// Possible ICE agent roles.
111 #[derive(PartialEq, Eq, Copy, Clone, Debug)]
112 pub enum Role {
113     Controlling,
114     Controlled,
115     Unspecified,
116 }
117 
118 impl Default for Role {
default() -> Self119     fn default() -> Self {
120         Self::Controlling
121     }
122 }
123 
124 impl From<&str> for Role {
from(raw: &str) -> Self125     fn from(raw: &str) -> Self {
126         match raw {
127             "controlling" => Self::Controlling,
128             "controlled" => Self::Controlled,
129             _ => Self::Unspecified,
130         }
131     }
132 }
133 
134 impl fmt::Display for Role {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result135     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136         let s = match *self {
137             Self::Controlling => "controlling",
138             Self::Controlled => "controlled",
139             Self::Unspecified => "unspecified",
140         };
141         write!(f, "{s}")
142     }
143 }
144