1#[cfg(test)]
2mod attributes_test;
3
4use crate::message::*;
5use shared::error::*;
6
7use std::fmt;
8
9#[derive(Default, PartialEq, Eq, Debug, Clone)]
11pub struct Attributes(pub Vec<RawAttribute>);
12
13impl Attributes {
14 pub fn get(&self, t: AttrType) -> (RawAttribute, bool) {
19 for candidate in &self.0 {
20 if candidate.typ == t {
21 return (candidate.clone(), true);
22 }
23 }
24
25 (RawAttribute::default(), false)
26 }
27}
28
29#[derive(PartialEq, Debug, Eq, Default, Copy, Clone)]
31pub struct AttrType(pub u16);
32
33impl fmt::Display for AttrType {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 let other = format!("0x{:x}", self.0);
36
37 let s = match *self {
38 ATTR_MAPPED_ADDRESS => "MAPPED-ADDRESS",
39 ATTR_USERNAME => "USERNAME",
40 ATTR_ERROR_CODE => "ERROR-CODE",
41 ATTR_MESSAGE_INTEGRITY => "MESSAGE-INTEGRITY",
42 ATTR_UNKNOWN_ATTRIBUTES => "UNKNOWN-ATTRIBUTES",
43 ATTR_REALM => "REALM",
44 ATTR_NONCE => "NONCE",
45 ATTR_XORMAPPED_ADDRESS => "XOR-MAPPED-ADDRESS",
46 ATTR_SOFTWARE => "SOFTWARE",
47 ATTR_ALTERNATE_SERVER => "ALTERNATE-SERVER",
48 ATTR_FINGERPRINT => "FINGERPRINT",
49 ATTR_PRIORITY => "PRIORITY",
50 ATTR_USE_CANDIDATE => "USE-CANDIDATE",
51 ATTR_ICE_CONTROLLED => "ICE-CONTROLLED",
52 ATTR_ICE_CONTROLLING => "ICE-CONTROLLING",
53 ATTR_CHANNEL_NUMBER => "CHANNEL-NUMBER",
54 ATTR_LIFETIME => "LIFETIME",
55 ATTR_XOR_PEER_ADDRESS => "XOR-PEER-ADDRESS",
56 ATTR_DATA => "DATA",
57 ATTR_XOR_RELAYED_ADDRESS => "XOR-RELAYED-ADDRESS",
58 ATTR_EVEN_PORT => "EVEN-PORT",
59 ATTR_REQUESTED_TRANSPORT => "REQUESTED-TRANSPORT",
60 ATTR_DONT_FRAGMENT => "DONT-FRAGMENT",
61 ATTR_RESERVATION_TOKEN => "RESERVATION-TOKEN",
62 ATTR_CONNECTION_ID => "CONNECTION-ID",
63 ATTR_REQUESTED_ADDRESS_FAMILY => "REQUESTED-ADDRESS-FAMILY",
64 ATTR_MESSAGE_INTEGRITY_SHA256 => "MESSAGE-INTEGRITY-SHA256",
65 ATTR_PASSWORD_ALGORITHM => "PASSWORD-ALGORITHM",
66 ATTR_USER_HASH => "USERHASH",
67 ATTR_PASSWORD_ALGORITHMS => "PASSWORD-ALGORITHMS",
68 ATTR_ALTERNATE_DOMAIN => "ALTERNATE-DOMAIN",
69 _ => other.as_str(),
70 };
71
72 write!(f, "{s}")
73 }
74}
75
76impl AttrType {
77 pub fn required(&self) -> bool {
79 self.0 <= 0x7FFF
80 }
81
82 pub fn optional(&self) -> bool {
84 self.0 >= 0x8000
85 }
86
87 pub fn value(&self) -> u16 {
89 self.0
90 }
91}
92
93pub const ATTR_MAPPED_ADDRESS: AttrType = AttrType(0x0001); pub const ATTR_USERNAME: AttrType = AttrType(0x0006); pub const ATTR_MESSAGE_INTEGRITY: AttrType = AttrType(0x0008); pub const ATTR_ERROR_CODE: AttrType = AttrType(0x0009); pub const ATTR_UNKNOWN_ATTRIBUTES: AttrType = AttrType(0x000A); pub const ATTR_REALM: AttrType = AttrType(0x0014); pub const ATTR_NONCE: AttrType = AttrType(0x0015); pub const ATTR_XORMAPPED_ADDRESS: AttrType = AttrType(0x0020); pub const ATTR_SOFTWARE: AttrType = AttrType(0x8022); pub const ATTR_ALTERNATE_SERVER: AttrType = AttrType(0x8023); pub const ATTR_FINGERPRINT: AttrType = AttrType(0x8028); pub const ATTR_PRIORITY: AttrType = AttrType(0x0024); pub const ATTR_USE_CANDIDATE: AttrType = AttrType(0x0025); pub const ATTR_ICE_CONTROLLED: AttrType = AttrType(0x8029); pub const ATTR_ICE_CONTROLLING: AttrType = AttrType(0x802A); pub const ATTR_NETWORK_COST: AttrType = AttrType(0xC057); pub const ATTR_CHANNEL_NUMBER: AttrType = AttrType(0x000C); pub const ATTR_LIFETIME: AttrType = AttrType(0x000D); pub const ATTR_XOR_PEER_ADDRESS: AttrType = AttrType(0x0012); pub const ATTR_DATA: AttrType = AttrType(0x0013); pub const ATTR_XOR_RELAYED_ADDRESS: AttrType = AttrType(0x0016); pub const ATTR_EVEN_PORT: AttrType = AttrType(0x0018); pub const ATTR_REQUESTED_TRANSPORT: AttrType = AttrType(0x0019); pub const ATTR_DONT_FRAGMENT: AttrType = AttrType(0x001A); pub const ATTR_RESERVATION_TOKEN: AttrType = AttrType(0x0022); pub const ATTR_CHANGE_REQUEST: AttrType = AttrType(0x0003); pub const ATTR_PADDING: AttrType = AttrType(0x0026); pub const ATTR_RESPONSE_PORT: AttrType = AttrType(0x0027); pub const ATTR_CACHE_TIMEOUT: AttrType = AttrType(0x8027); pub const ATTR_RESPONSE_ORIGIN: AttrType = AttrType(0x802b); pub const ATTR_OTHER_ADDRESS: AttrType = AttrType(0x802C); pub const ATTR_SOURCE_ADDRESS: AttrType = AttrType(0x0004); pub const ATTR_CHANGED_ADDRESS: AttrType = AttrType(0x0005); pub const ATTR_CONNECTION_ID: AttrType = AttrType(0x002a); pub const ATTR_REQUESTED_ADDRESS_FAMILY: AttrType = AttrType(0x0017); pub const ATTR_ORIGIN: AttrType = AttrType(0x802F);
147
148pub const ATTR_MESSAGE_INTEGRITY_SHA256: AttrType = AttrType(0x001C); pub const ATTR_PASSWORD_ALGORITHM: AttrType = AttrType(0x001D); pub const ATTR_USER_HASH: AttrType = AttrType(0x001E); pub const ATTR_PASSWORD_ALGORITHMS: AttrType = AttrType(0x8002); pub const ATTR_ALTERNATE_DOMAIN: AttrType = AttrType(0x8003); #[derive(Default, Debug, Clone, PartialEq, Eq)]
163pub struct RawAttribute {
164 pub typ: AttrType,
165 pub length: u16, pub value: Vec<u8>,
167}
168
169impl fmt::Display for RawAttribute {
170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 write!(f, "{}: {:?}", self.typ, self.value)
172 }
173}
174
175impl Setter for RawAttribute {
176 fn add_to(&self, m: &mut Message) -> Result<()> {
179 m.add(self.typ, &self.value);
180 Ok(())
181 }
182}
183
184pub(crate) const PADDING: usize = 4;
185
186pub(crate) fn nearest_padded_value_length(l: usize) -> usize {
193 let mut n = PADDING * (l / PADDING);
194 if n < l {
195 n += PADDING
196 }
197 n
198}
199
200pub(crate) fn compat_attr_type(val: u16) -> AttrType {
204 if val == 0x8020 {
205 ATTR_XORMAPPED_ADDRESS } else {
208 AttrType(val)
209 }
210}