1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//! [RFC 5389](https://tools.ietf.org/html/rfc5389) specific components.
use Result;
use message::RawMessage;
use attribute::{self, RawAttribute};
use types::{TryAsRef, U12};

pub mod methods;
pub mod attributes;
pub mod errors;
pub mod handlers;

/// Method set that are defined in [RFC 5389](https://tools.ietf.org/html/rfc5389).
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub enum Method {
    /// See [methods::Binding](methods/struct.Binding.html).
    Binding,
}
impl ::Method for Method {
    fn from_u12(value: U12) -> Option<Self> {
        match value.as_u16() {
            methods::METHOD_BINDING => Some(Method::Binding),
            _ => None,
        }
    }
    fn as_u12(&self) -> U12 {
        match *self {
            Method::Binding => methods::Binding.as_u12(),
        }
    }
}
impl From<methods::Binding> for Method {
    fn from(_: methods::Binding) -> Self {
        Method::Binding
    }
}

macro_rules! impl_attr_from {
    ($attr:ident) => {
        impl From<attributes::$attr> for Attribute {
            fn from(f: attributes::$attr) -> Self {
                Attribute::$attr(f)
            }
        }
    }
}
macro_rules! impl_attr_try_as_ref {
    ($attr:ident) => {
        impl TryAsRef<attributes::$attr> for Attribute {
            fn try_as_ref(&self) -> Option<&attributes::$attr> {
                if let Attribute::$attr(ref a) = *self {
                    Some(a)
                } else {
                    None
                }
            }
        }
    }
}

/// Attribute set that are defined in [RFC 5389](https://tools.ietf.org/html/rfc5389).
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub enum Attribute {
    MappedAddress(attributes::MappedAddress),
    Username(attributes::Username),
    MessageIntegrity(attributes::MessageIntegrity),
    ErrorCode(attributes::ErrorCode),
    UnknownAttributes(attributes::UnknownAttributes),
    Realm(attributes::Realm),
    Nonce(attributes::Nonce),
    XorMappedAddress(attributes::XorMappedAddress),
    Software(attributes::Software),
    AlternateServer(attributes::AlternateServer),
    Fingerprint(attributes::Fingerprint),
    Other(RawAttribute),
}
impl_attr_from!(MappedAddress);
impl_attr_from!(Username);
impl_attr_from!(MessageIntegrity);
impl_attr_from!(ErrorCode);
impl_attr_from!(UnknownAttributes);
impl_attr_from!(Realm);
impl_attr_from!(Nonce);
impl_attr_from!(XorMappedAddress);
impl_attr_from!(Software);
impl_attr_from!(AlternateServer);
impl_attr_from!(Fingerprint);
impl_attr_try_as_ref!(MappedAddress);
impl_attr_try_as_ref!(Username);
impl_attr_try_as_ref!(MessageIntegrity);
impl_attr_try_as_ref!(ErrorCode);
impl_attr_try_as_ref!(UnknownAttributes);
impl_attr_try_as_ref!(Realm);
impl_attr_try_as_ref!(Nonce);
impl_attr_try_as_ref!(XorMappedAddress);
impl_attr_try_as_ref!(Software);
impl_attr_try_as_ref!(AlternateServer);
impl_attr_try_as_ref!(Fingerprint);
impl ::Attribute for Attribute {
    fn get_type(&self) -> attribute::Type {
        match *self {
            Attribute::MappedAddress(ref a) => a.get_type(),
            Attribute::Username(ref a) => a.get_type(),
            Attribute::MessageIntegrity(ref a) => a.get_type(),
            Attribute::ErrorCode(ref a) => a.get_type(),
            Attribute::UnknownAttributes(ref a) => a.get_type(),
            Attribute::Realm(ref a) => a.get_type(),
            Attribute::Nonce(ref a) => a.get_type(),
            Attribute::XorMappedAddress(ref a) => a.get_type(),
            Attribute::Software(ref a) => a.get_type(),
            Attribute::AlternateServer(ref a) => a.get_type(),
            Attribute::Fingerprint(ref a) => a.get_type(),
            Attribute::Other(ref a) => a.get_type(),
        }
    }
    fn try_from_raw(attr: &RawAttribute, message: &RawMessage) -> Result<Self> {
        match attr.get_type().as_u16() {
            attributes::TYPE_MAPPED_ADDRESS => {
                attributes::MappedAddress::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_USERNAME => {
                attributes::Username::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_MESSAGE_INTEGRITY => {
                attributes::MessageIntegrity::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_ERROR_CODE => {
                attributes::ErrorCode::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_UNKNOWN_ATTRIBUTES => {
                attributes::UnknownAttributes::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_REALM => {
                attributes::Realm::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_NONCE => {
                attributes::Nonce::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_XOR_MAPPED_ADDRESS => {
                attributes::XorMappedAddress::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_SOFTWARE => {
                attributes::Software::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_ALTERNATE_SERVER => {
                attributes::AlternateServer::try_from_raw(attr, message).map(From::from)
            }
            attributes::TYPE_FINGERPRINT => {
                attributes::Fingerprint::try_from_raw(attr, message).map(From::from)
            }
            _ => Ok(Attribute::Other(attr.clone())),
        }
    }
    fn encode_value(&self, message: &RawMessage) -> Result<Vec<u8>> {
        match *self {
            Attribute::MappedAddress(ref a) => a.encode_value(message),
            Attribute::Username(ref a) => a.encode_value(message),
            Attribute::MessageIntegrity(ref a) => a.encode_value(message),
            Attribute::ErrorCode(ref a) => a.encode_value(message),
            Attribute::UnknownAttributes(ref a) => a.encode_value(message),
            Attribute::Realm(ref a) => a.encode_value(message),
            Attribute::Nonce(ref a) => a.encode_value(message),
            Attribute::XorMappedAddress(ref a) => a.encode_value(message),
            Attribute::Software(ref a) => a.encode_value(message),
            Attribute::AlternateServer(ref a) => a.encode_value(message),
            Attribute::Fingerprint(ref a) => a.encode_value(message),
            Attribute::Other(ref a) => a.encode_value(message),
        }
    }
}