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