forked from lavina/lavina
1
0
Fork 0
lavina/src/protos/xmpp/sasl.rs

79 lines
2.2 KiB
Rust
Raw Normal View History

use std::borrow::Borrow;
use quick_xml::{
events::{BytesStart, Event},
NsReader, Writer,
};
use tokio::io::{AsyncBufRead, AsyncWrite};
use super::skip_text;
use crate::prelude::*;
pub enum Mechanism {
Plain,
}
impl Mechanism {
pub fn to_str(&self) -> &'static str {
match self {
Mechanism::Plain => "PLAIN",
}
}
pub fn from_str(input: &[u8]) -> Result<Mechanism> {
match input {
b"PLAIN" => Ok(Mechanism::Plain),
_ => Err(fail(format!("unknown auth mechanism: {input:?}").as_str())),
}
}
}
pub struct Auth {
pub mechanism: Mechanism,
pub body: Vec<u8>,
}
impl Auth {
pub async fn parse(
reader: &mut NsReader<impl AsyncBufRead + Unpin>,
buf: &mut Vec<u8>,
) -> Result<Auth> {
let event = skip_text!(reader, buf);
let mechanism = if let Event::Start(bytes) = event {
let mut mechanism = None;
for attr in bytes.attributes() {
let attr = attr?;
if attr.key.0 == b"mechanism" {
mechanism = Some(attr.value)
}
}
if let Some(mechanism) = mechanism {
Mechanism::from_str(mechanism.borrow())?
} else {
return Err(fail("expected mechanism attribute in <auth>"));
}
} else {
return Err(fail("expected start of <auth>"));
};
let body = if let Event::Text(text) = reader.read_event_into_async(buf).await? {
text.into_inner().into_owned()
} else {
return Err(fail("expected text body in <auth>"));
};
if let Event::End(_) = reader.read_event_into_async(buf).await? {
//TODO
} else {
return Err(fail("expected end of <auth>"));
};
Ok(Auth { mechanism, body })
}
}
pub struct Success;
impl Success {
pub async fn write_xml(&self, writer: &mut Writer<impl AsyncWrite + Unpin>) -> Result<()> {
let event = BytesStart::new(r#"success xmlns="urn:ietf:params:xml:ns:xmpp-sasl""#);
writer.write_event_async(Event::Empty(event)).await?;
Ok(())
}
}