aboutsummaryrefslogtreecommitdiffstats
path: root/src/stanza
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2024-11-29 02:11:02 +0000
committerLibravatar cel 🌸 <cel@bunny.garden>2024-11-29 02:11:02 +0000
commitb6593389069903cc4c85e40611296d8a240f718d (patch)
treeae4df92ea45cce5e5b904041a925263e8d629274 /src/stanza
parent2dcbc9e1f4339993dd47b2659770a9cf4855b02d (diff)
downloadluz-b6593389069903cc4c85e40611296d8a240f718d.tar.gz
luz-b6593389069903cc4c85e40611296d8a240f718d.tar.bz2
luz-b6593389069903cc4c85e40611296d8a240f718d.zip
implement sasl kinda
Diffstat (limited to 'src/stanza')
-rw-r--r--src/stanza/sasl.rs169
-rw-r--r--src/stanza/stream.rs42
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)
+ }
}
}
}