1#[cfg(test)]
17mod attributes_test;
18
19use crate::message::*;
20use shared::error::*;
21
22use std::fmt;
23
24#[derive(Default, PartialEq, Eq, Debug, Clone)]
26pub struct Attributes(pub Vec<RawAttribute>);
27
28impl Attributes {
29 pub fn get(&self, t: AttrType) -> (RawAttribute, bool) {
34 for candidate in &self.0 {
35 if candidate.typ == t {
36 return (candidate.clone(), true);
37 }
38 }
39
40 (RawAttribute::default(), false)
41 }
42}
43
44#[derive(PartialEq, Debug, Eq, Default, Copy, Clone)]
46pub struct AttrType(pub u16);
47
48impl fmt::Display for AttrType {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 let other = format!("0x{:x}", self.0);
51
52 let s = match *self {
53 ATTR_MAPPED_ADDRESS => "MAPPED-ADDRESS",
54 ATTR_USERNAME => "USERNAME",
55 ATTR_ERROR_CODE => "ERROR-CODE",
56 ATTR_MESSAGE_INTEGRITY => "MESSAGE-INTEGRITY",
57 ATTR_UNKNOWN_ATTRIBUTES => "UNKNOWN-ATTRIBUTES",
58 ATTR_REALM => "REALM",
59 ATTR_NONCE => "NONCE",
60 ATTR_XORMAPPED_ADDRESS => "XOR-MAPPED-ADDRESS",
61 ATTR_SOFTWARE => "SOFTWARE",
62 ATTR_ALTERNATE_SERVER => "ALTERNATE-SERVER",
63 ATTR_FINGERPRINT => "FINGERPRINT",
64 ATTR_PRIORITY => "PRIORITY",
65 ATTR_USE_CANDIDATE => "USE-CANDIDATE",
66 ATTR_ICE_CONTROLLED => "ICE-CONTROLLED",
67 ATTR_ICE_CONTROLLING => "ICE-CONTROLLING",
68 ATTR_CHANNEL_NUMBER => "CHANNEL-NUMBER",
69 ATTR_LIFETIME => "LIFETIME",
70 ATTR_XOR_PEER_ADDRESS => "XOR-PEER-ADDRESS",
71 ATTR_DATA => "DATA",
72 ATTR_XOR_RELAYED_ADDRESS => "XOR-RELAYED-ADDRESS",
73 ATTR_EVEN_PORT => "EVEN-PORT",
74 ATTR_REQUESTED_TRANSPORT => "REQUESTED-TRANSPORT",
75 ATTR_DONT_FRAGMENT => "DONT-FRAGMENT",
76 ATTR_RESERVATION_TOKEN => "RESERVATION-TOKEN",
77 ATTR_CONNECTION_ID => "CONNECTION-ID",
78 ATTR_REQUESTED_ADDRESS_FAMILY => "REQUESTED-ADDRESS-FAMILY",
79 ATTR_MESSAGE_INTEGRITY_SHA256 => "MESSAGE-INTEGRITY-SHA256",
80 ATTR_PASSWORD_ALGORITHM => "PASSWORD-ALGORITHM",
81 ATTR_USER_HASH => "USERHASH",
82 ATTR_PASSWORD_ALGORITHMS => "PASSWORD-ALGORITHMS",
83 ATTR_ALTERNATE_DOMAIN => "ALTERNATE-DOMAIN",
84 _ => other.as_str(),
85 };
86
87 write!(f, "{s}")
88 }
89}
90
91impl AttrType {
92 pub fn required(&self) -> bool {
94 self.0 <= 0x7FFF
95 }
96
97 pub fn optional(&self) -> bool {
99 self.0 >= 0x8000
100 }
101
102 pub fn value(&self) -> u16 {
104 self.0
105 }
106}
107
108pub const ATTR_MAPPED_ADDRESS: AttrType = AttrType(0x0001);
111pub const ATTR_USERNAME: AttrType = AttrType(0x0006);
113pub const ATTR_MESSAGE_INTEGRITY: AttrType = AttrType(0x0008);
115pub const ATTR_ERROR_CODE: AttrType = AttrType(0x0009);
117pub const ATTR_UNKNOWN_ATTRIBUTES: AttrType = AttrType(0x000A);
119pub const ATTR_REALM: AttrType = AttrType(0x0014);
121pub const ATTR_NONCE: AttrType = AttrType(0x0015);
123pub const ATTR_XORMAPPED_ADDRESS: AttrType = AttrType(0x0020);
125
126pub const ATTR_SOFTWARE: AttrType = AttrType(0x8022);
129pub const ATTR_ALTERNATE_SERVER: AttrType = AttrType(0x8023);
131pub const ATTR_FINGERPRINT: AttrType = AttrType(0x8028);
133
134pub const ATTR_PRIORITY: AttrType = AttrType(0x0024);
137pub const ATTR_USE_CANDIDATE: AttrType = AttrType(0x0025);
139pub const ATTR_ICE_CONTROLLED: AttrType = AttrType(0x8029);
141pub const ATTR_ICE_CONTROLLING: AttrType = AttrType(0x802A);
143pub const ATTR_NETWORK_COST: AttrType = AttrType(0xC057);
145
146pub const ATTR_CHANNEL_NUMBER: AttrType = AttrType(0x000C);
149pub const ATTR_LIFETIME: AttrType = AttrType(0x000D);
151pub const ATTR_XOR_PEER_ADDRESS: AttrType = AttrType(0x0012);
153pub const ATTR_DATA: AttrType = AttrType(0x0013);
155pub const ATTR_XOR_RELAYED_ADDRESS: AttrType = AttrType(0x0016);
157pub const ATTR_EVEN_PORT: AttrType = AttrType(0x0018);
159pub const ATTR_REQUESTED_TRANSPORT: AttrType = AttrType(0x0019);
161pub const ATTR_DONT_FRAGMENT: AttrType = AttrType(0x001A);
163pub const ATTR_RESERVATION_TOKEN: AttrType = AttrType(0x0022);
165
166pub const ATTR_CHANGE_REQUEST: AttrType = AttrType(0x0003);
169pub const ATTR_PADDING: AttrType = AttrType(0x0026);
171pub const ATTR_RESPONSE_PORT: AttrType = AttrType(0x0027);
173pub const ATTR_CACHE_TIMEOUT: AttrType = AttrType(0x8027);
175pub const ATTR_RESPONSE_ORIGIN: AttrType = AttrType(0x802b);
177pub const ATTR_OTHER_ADDRESS: AttrType = AttrType(0x802C);
179
180pub const ATTR_SOURCE_ADDRESS: AttrType = AttrType(0x0004);
184pub const ATTR_CHANGED_ADDRESS: AttrType = AttrType(0x0005);
186
187pub const ATTR_CONNECTION_ID: AttrType = AttrType(0x002a);
190
191pub const ATTR_REQUESTED_ADDRESS_FAMILY: AttrType = AttrType(0x0017);
194
195pub const ATTR_ORIGIN: AttrType = AttrType(0x802F);
197
198pub const ATTR_MESSAGE_INTEGRITY_SHA256: AttrType = AttrType(0x001C);
201pub const ATTR_PASSWORD_ALGORITHM: AttrType = AttrType(0x001D);
203pub const ATTR_USER_HASH: AttrType = AttrType(0x001E);
205pub const ATTR_PASSWORD_ALGORITHMS: AttrType = AttrType(0x8002);
207pub const ATTR_ALTERNATE_DOMAIN: AttrType = AttrType(0x8003);
209
210#[derive(Default, Debug, Clone, PartialEq, Eq)]
218pub struct RawAttribute {
219 pub typ: AttrType,
221 pub length: u16, pub value: Vec<u8>,
225}
226
227impl fmt::Display for RawAttribute {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 write!(f, "{}: {:?}", self.typ, self.value)
230 }
231}
232
233impl Setter for RawAttribute {
234 fn add_to(&self, m: &mut Message) -> Result<()> {
237 m.add(self.typ, &self.value);
238 Ok(())
239 }
240}
241
242pub(crate) const PADDING: usize = 4;
243
244pub(crate) fn nearest_padded_value_length(l: usize) -> usize {
251 let mut n = PADDING * (l / PADDING);
252 if n < l {
253 n += PADDING
254 }
255 n
256}
257
258pub(crate) fn compat_attr_type(val: u16) -> AttrType {
262 if val == 0x8020 {
263 ATTR_XORMAPPED_ADDRESS } else {
266 AttrType(val)
267 }
268}