use stringprep::saslprep;
pub use super::errors::{IntegrityKeyGenerationError, MessageDecodeError, MessageEncodeError};
use crate::definitions::StunTransactionId;
use crate::header::StunHeader;
use crate::header::{StunMessageClass, StunMessageMethod};
use crate::StunAttribute;
use super::message::StunMessage;
impl StunMessage {
pub fn new(method: StunMessageMethod, class: StunMessageClass) -> Self {
let header = StunHeader::new(method, class, None);
Self {
header,
attributes: Vec::new(),
}
}
pub fn create_request() -> Self {
Self::default().set_message_class(StunMessageClass::Request)
}
pub fn create_success_response() -> Self {
Self::default().set_message_class(StunMessageClass::SuccessResponse)
}
pub fn create_error_response() -> Self {
Self::default().set_message_class(StunMessageClass::ErrorResponse)
}
pub fn create_indication() -> Self {
Self::default().set_message_class(StunMessageClass::Indication)
}
pub fn set_transaction_id(mut self, transaction_id: StunTransactionId) -> Self {
self.header.transaction_id = transaction_id;
self
}
pub fn set_message_class(mut self, class: StunMessageClass) -> Self {
self.header.message_class = class;
self
}
pub fn set_message_method(mut self, method: StunMessageMethod) -> Self {
self.header.message_method = method;
self
}
pub fn get_header(&self) -> &StunHeader {
&self.header
}
pub fn get_attributes(&self) -> &Vec<StunAttribute> {
&self.attributes
}
pub fn add_attribute(mut self, attr: StunAttribute) -> Self {
self.attributes.push(attr);
self
}
pub fn add_fingerprint(mut self) -> Self {
self.attributes
.push(StunAttribute::Fingerprint { value: 0 });
self
}
pub fn add_message_integrity(mut self) -> Self {
self.attributes
.push(StunAttribute::MessageIntegrity { key: Vec::new() });
self
}
pub fn add_long_term_credential_message_integrity(
mut self,
username: &str,
realm: &str,
) -> Result<Self, stringprep::Error> {
self.attributes.push(StunAttribute::Username {
value: saslprep(username)?.to_string(),
});
self.attributes.push(StunAttribute::Realm {
value: saslprep(realm)?.to_string(),
});
Ok(self.add_message_integrity())
}
}
impl std::default::Default for StunMessage {
fn default() -> Self {
Self::new(StunMessageMethod::BindingRequest, StunMessageClass::Request)
}
}