luz/src/stanza/stream.rs

191 lines
6.1 KiB
Rust
Raw Normal View History

2023-07-11 21:28:42 +01:00
use std::str;
2023-06-19 19:23:54 +01:00
2023-07-11 21:28:42 +01:00
use quick_xml::{
events::{BytesStart, Event},
name::QName,
};
2023-07-04 21:27:15 +01:00
use super::Element;
use crate::{JabberError, Result, JID};
2023-07-11 21:28:42 +01:00
const XMLNS_STREAM: &str = "http://etherx.jabber.org/streams";
const VERSION: &str = "1.0";
enum XMLNS {
Client,
Server,
}
impl From<XMLNS> for &str {
fn from(xmlns: XMLNS) -> Self {
match xmlns {
XMLNS::Client => return "jabber:client",
XMLNS::Server => return "jabber:server",
}
}
}
impl TryInto<XMLNS> for &str {
type Error = JabberError;
fn try_into(self) -> Result<XMLNS> {
match self {
"jabber:client" => Ok(XMLNS::Client),
"jabber:server" => Ok(XMLNS::Server),
_ => Err(JabberError::UnknownNamespace),
}
}
}
pub struct Stream {
from: Option<JID>,
2023-06-19 19:23:54 +01:00
id: Option<String>,
2023-07-11 21:28:42 +01:00
to: Option<JID>,
version: Option<String>,
2023-06-19 19:23:54 +01:00
lang: Option<String>,
2023-07-12 13:03:04 +01:00
ns: XMLNS,
2023-06-19 19:23:54 +01:00
}
2023-07-11 21:28:42 +01:00
impl Stream {
pub fn new_client(from: &JID, to: &JID, id: Option<String>, lang: Option<String>) -> Self {
Self {
from: Some(from.clone()),
id,
to: Some(to.clone()),
version: Some(VERSION.to_owned()),
lang,
2023-07-12 13:03:04 +01:00
ns: XMLNS::Client,
2023-07-11 21:28:42 +01:00
}
}
2023-07-12 21:11:20 +01:00
fn event(&self) -> Event<'static> {
2023-07-11 21:28:42 +01:00
let mut start = BytesStart::new("stream:stream");
if let Some(from) = &self.from {
start.push_attribute(("from", from.to_string().as_str()));
}
if let Some(id) = &self.id {
start.push_attribute(("id", id.as_str()));
}
if let Some(to) = &self.to {
start.push_attribute(("to", to.to_string().as_str()));
}
if let Some(version) = &self.version {
start.push_attribute(("version", version.to_string().as_str()));
}
if let Some(lang) = &self.lang {
start.push_attribute(("xml:lang", lang.as_str()));
}
2023-07-12 13:03:04 +01:00
match &self.ns {
XMLNS::Client => start.push_attribute(("xmlns", XMLNS::Client.into())),
XMLNS::Server => start.push_attribute(("xmlns", XMLNS::Server.into())),
}
2023-07-11 21:28:42 +01:00
start.push_attribute(("xmlns:stream", XMLNS_STREAM));
2023-07-12 21:11:20 +01:00
Event::Start(start)
2023-07-11 21:28:42 +01:00
}
}
impl<'e> Into<Element<'e>> for Stream {
fn into(self) -> Element<'e> {
Element {
2023-07-12 21:11:20 +01:00
event: self.event(),
children: None,
2023-07-11 21:28:42 +01:00
}
}
2023-06-19 19:23:54 +01:00
}
2023-07-11 21:28:42 +01:00
impl<'e> TryFrom<Element<'e>> for Stream {
type Error = JabberError;
fn try_from(value: Element<'e>) -> Result<Stream> {
let (mut from, mut id, mut to, mut version, mut lang, mut ns) =
(None, None, None, None, None, XMLNS::Client);
if let Event::Start(e) = value.event.as_ref() {
for attribute in e.attributes() {
let attribute = attribute?;
match attribute.key {
QName(b"from") => {
from = Some(str::from_utf8(&attribute.value)?.to_string().try_into()?);
}
QName(b"id") => {
id = Some(str::from_utf8(&attribute.value)?.to_owned());
}
QName(b"to") => {
to = Some(str::from_utf8(&attribute.value)?.to_string().try_into()?);
}
QName(b"version") => {
version = Some(str::from_utf8(&attribute.value)?.to_owned());
}
QName(b"lang") => {
lang = Some(str::from_utf8(&attribute.value)?.to_owned());
}
QName(b"xmlns") => {
ns = str::from_utf8(&attribute.value)?.try_into()?;
}
_ => {
println!("unknown attribute: {:?}", attribute)
}
}
}
Ok(Stream {
from,
id,
to,
version,
lang,
2023-07-12 13:03:04 +01:00
ns,
2023-07-11 21:28:42 +01:00
})
} else {
Err(JabberError::ParseError)
}
}
}
#[derive(PartialEq, Debug)]
2023-06-19 19:23:54 +01:00
pub enum StreamFeature {
StartTls,
2023-07-11 21:28:42 +01:00
Sasl(Vec<String>),
2023-06-19 19:23:54 +01:00
Bind,
2023-07-04 21:27:15 +01:00
Unknown,
2023-06-19 19:23:54 +01:00
}
2023-07-11 21:28:42 +01:00
impl<'e> TryFrom<Element<'e>> for Vec<StreamFeature> {
type Error = JabberError;
fn try_from(features_element: Element) -> Result<Self> {
let mut features = Vec::new();
2023-07-12 21:11:20 +01:00
if let Some(children) = features_element.children {
for feature_element in children {
2023-07-11 21:28:42 +01:00
match feature_element.event {
Event::Start(e) => match e.name() {
QName(b"starttls") => features.push(StreamFeature::StartTls),
QName(b"mechanisms") => {
let mut mechanisms = Vec::new();
2023-07-12 21:11:20 +01:00
if let Some(children) = feature_element.children {
for mechanism_element in children {
if let Some(children) = mechanism_element.children {
for mechanism_text in children {
2023-07-11 21:28:42 +01:00
match mechanism_text.event {
Event::Text(e) => mechanisms
.push(str::from_utf8(e.as_ref())?.to_owned()),
_ => {}
}
}
}
}
}
features.push(StreamFeature::Sasl(mechanisms))
}
2023-08-02 00:56:38 +01:00
_ => features.push(StreamFeature::Unknown),
},
Event::Empty(e) => match e.name() {
QName(b"bind") => features.push(StreamFeature::Bind),
_ => features.push(StreamFeature::Unknown),
2023-07-11 21:28:42 +01:00
},
_ => features.push(StreamFeature::Unknown),
}
}
}
Ok(features)
}
}