diff options
Diffstat (limited to '')
-rw-r--r-- | src/stanza/sasl.rs | 169 | ||||
-rw-r--r-- | src/stanza/stream.rs | 42 |
2 files changed, 187 insertions, 24 deletions
diff --git a/src/stanza/sasl.rs b/src/stanza/sasl.rs index 8b13789..6ac4fc9 100644 --- a/src/stanza/sasl.rs +++ b/src/stanza/sasl.rs @@ -1 +1,170 @@ +use std::ops::Deref; +use peanuts::{ + element::{FromElement, IntoElement}, + DeserializeError, Element, +}; +use tracing::debug; + +pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-sasl"; + +#[derive(Debug, Clone)] +pub struct Mechanisms { + pub mechanisms: Vec<String>, +} + +impl FromElement for Mechanisms { + fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("mechanisms")?; + element.check_namespace(XMLNS)?; + debug!("getting mechanisms"); + let mechanisms: Vec<Mechanism> = element.pop_children()?; + debug!("gottting mechanisms"); + let mechanisms = mechanisms + .into_iter() + .map(|Mechanism(mechanism)| mechanism) + .collect(); + debug!("gottting mechanisms"); + + Ok(Mechanisms { mechanisms }) + } +} + +impl IntoElement for Mechanisms { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("mechanisms", Some(XMLNS)).push_children( + self.mechanisms + .iter() + .map(|mechanism| Mechanism(mechanism.to_string())) + .collect(), + ) + } +} + +pub struct Mechanism(String); + +impl FromElement for Mechanism { + fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("mechanism")?; + element.check_namespace(XMLNS)?; + + let mechanism = element.pop_value()?; + + Ok(Mechanism(mechanism)) + } +} + +impl IntoElement for Mechanism { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("mechanism", Some(XMLNS)).push_text(self.0.clone()) + } +} + +impl Deref for Mechanism { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[derive(Debug)] +pub struct Auth { + pub mechanism: String, + pub sasl_data: String, +} + +impl IntoElement for Auth { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("auth", Some(XMLNS)) + .push_attribute("mechanism", self.mechanism.clone()) + .push_text(self.sasl_data.clone()) + } +} + +#[derive(Debug)] +pub struct Challenge(String); + +impl Deref for Challenge { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl FromElement for Challenge { + fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("challenge")?; + element.check_namespace(XMLNS)?; + + let sasl_data = element.value()?; + + Ok(Challenge(sasl_data)) + } +} + +#[derive(Debug)] +pub struct Success(String); + +impl Deref for Success { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl FromElement for Success { + fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> { + element.check_name("success")?; + element.check_namespace(XMLNS)?; + + let sasl_data = element.value()?; + + Ok(Success(sasl_data)) + } +} + +#[derive(Debug)] +pub enum ServerResponse { + Challenge(Challenge), + Success(Success), +} + +impl FromElement for ServerResponse { + fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> { + match element.identify() { + (Some(XMLNS), "challenge") => { + Ok(ServerResponse::Challenge(Challenge::from_element(element)?)) + } + (Some(XMLNS), "success") => { + Ok(ServerResponse::Success(Success::from_element(element)?)) + } + _ => Err(DeserializeError::UnexpectedElement(element)), + } + } +} + +#[derive(Debug)] +pub struct Response(String); + +impl Response { + pub fn new(response: String) -> Self { + Self(response) + } +} + +impl Deref for Response { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl IntoElement for Response { + fn builder(&self) -> peanuts::element::ElementBuilder { + Element::builder("reponse", Some(XMLNS)).push_text(self.0.clone()) + } +} diff --git a/src/stanza/stream.rs b/src/stanza/stream.rs index 40f6ba0..fecace5 100644 --- a/src/stanza/stream.rs +++ b/src/stanza/stream.rs @@ -3,9 +3,11 @@ use std::collections::{HashMap, HashSet}; use peanuts::element::{Content, ElementBuilder, FromElement, IntoElement, NamespaceDeclaration}; use peanuts::XML_NS; use peanuts::{element::Name, Element}; +use tracing::debug; use crate::{Error, JID}; +use super::sasl::{self, Mechanisms}; use super::starttls::{self, StartTls}; pub const XMLNS: &str = "http://etherx.jabber.org/streams"; @@ -92,32 +94,12 @@ impl<'s> Stream { #[derive(Debug)] pub struct Features { - features: Vec<Feature>, + pub features: Vec<Feature>, } impl IntoElement for Features { fn builder(&self) -> ElementBuilder { Element::builder("features", Some(XMLNS)).push_children(self.features.clone()) - // let mut content = Vec::new(); - // for feature in &self.features { - // match feature { - // Feature::StartTls(start_tls) => { - // content.push(Content::Element(start_tls.into_element())) - // } - // Feature::Sasl => {} - // Feature::Bind => {} - // Feature::Unknown => {} - // } - // } - // Element { - // name: Name { - // namespace: Some(XMLNS.to_string()), - // local_name: "features".to_string(), - // }, - // namespace_declaration_overrides: HashSet::new(), - // attributes: HashMap::new(), - // content, - // } } } @@ -128,7 +110,9 @@ impl FromElement for Features { element.check_namespace(XMLNS)?; element.check_name("features")?; + debug!("got features stanza"); let features = element.children()?; + debug!("got features period"); Ok(Features { features }) } @@ -137,7 +121,7 @@ impl FromElement for Features { #[derive(Debug, Clone)] pub enum Feature { StartTls(StartTls), - Sasl, + Sasl(Mechanisms), Bind, Unknown, } @@ -146,7 +130,7 @@ impl IntoElement for Feature { fn builder(&self) -> ElementBuilder { match self { Feature::StartTls(start_tls) => start_tls.builder(), - Feature::Sasl => todo!(), + Feature::Sasl(mechanisms) => mechanisms.builder(), Feature::Bind => todo!(), Feature::Unknown => todo!(), } @@ -155,11 +139,21 @@ impl IntoElement for Feature { impl FromElement for Feature { fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> { + let identity = element.identify(); + debug!("identity: {:?}", identity); match element.identify() { (Some(starttls::XMLNS), "starttls") => { + debug!("identified starttls"); Ok(Feature::StartTls(StartTls::from_element(element)?)) } - _ => Ok(Feature::Unknown), + (Some(sasl::XMLNS), "mechanisms") => { + debug!("identified mechanisms"); + Ok(Feature::Sasl(Mechanisms::from_element(element)?)) + } + _ => { + debug!("identified unknown feature"); + Ok(Feature::Unknown) + } } } } |