forked from lavina/lavina
feat(xmpp): implement session iq
This commit is contained in:
parent
4107c5b663
commit
33dbfba116
|
@ -25,6 +25,7 @@ use crate::prelude::*;
|
|||
use crate::protos::xmpp;
|
||||
use crate::protos::xmpp::bind::{BindResponse, Jid, Name, Server};
|
||||
use crate::protos::xmpp::client::Iq;
|
||||
use crate::protos::xmpp::session::Session;
|
||||
use crate::protos::xmpp::stream::*;
|
||||
use crate::util::xml::{Continuation, FromXml, Parser, ToXml};
|
||||
use crate::util::Terminator;
|
||||
|
@ -301,6 +302,21 @@ async fn socket_final(
|
|||
}
|
||||
xml_writer.get_mut().flush().await?;
|
||||
}
|
||||
proto::IqClientBody::Session(_) => {
|
||||
let mut events = vec![];
|
||||
let req = Iq {
|
||||
from: None,
|
||||
id: iq.id,
|
||||
to: None,
|
||||
r#type: xmpp::client::IqType::Result,
|
||||
body: Session,
|
||||
};
|
||||
req.serialize(&mut events);
|
||||
for i in events {
|
||||
xml_writer.write_event_async(i).await?;
|
||||
}
|
||||
xml_writer.get_mut().flush().await?;
|
||||
}
|
||||
},
|
||||
proto::ClientPacket::Message(_) => todo!(),
|
||||
}
|
||||
|
|
|
@ -4,13 +4,15 @@ use quick_xml::name::{Namespace, ResolveResult};
|
|||
|
||||
use crate::protos::xmpp::bind::BindRequest;
|
||||
use crate::protos::xmpp::client::{Iq, Message};
|
||||
use crate::util::xml::{Continuation, FromXml, Parser};
|
||||
use crate::protos::xmpp::session::Session;
|
||||
use crate::util::xml::{Continuation, FromXml, FromXmlTag, Parser};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, From)]
|
||||
pub enum IqClientBody {
|
||||
Bind(BindRequest),
|
||||
Session(Session),
|
||||
}
|
||||
|
||||
#[derive(From)]
|
||||
|
@ -20,6 +22,7 @@ pub struct IqClientBodyParser(IqClientBodyParserInner);
|
|||
enum IqClientBodyParserInner {
|
||||
Initial,
|
||||
Bind(<BindRequest as FromXml>::P),
|
||||
SessionV(<Session as FromXml>::P),
|
||||
}
|
||||
|
||||
impl FromXml for IqClientBody {
|
||||
|
@ -41,20 +44,21 @@ impl Parser for IqClientBodyParser {
|
|||
use IqClientBodyParserInner::*;
|
||||
match self.0 {
|
||||
Initial => {
|
||||
let Event::Start(bytes) = event else {
|
||||
return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}. Expected start of {}", BindRequest::NAME)));
|
||||
let bytes = match event {
|
||||
Event::Start(bytes) => bytes,
|
||||
Event::Empty(bytes) => bytes,
|
||||
_ => {
|
||||
return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")))
|
||||
}
|
||||
};
|
||||
if bytes.name().0 == BindRequest::NAME.as_bytes()
|
||||
&& namespace == ResolveResult::Bound(Namespace(BindRequest::NS.as_bytes()))
|
||||
{
|
||||
match BindRequest::parse().consume(namespace, event) {
|
||||
Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())),
|
||||
Continuation::Final(Err(e)) => Continuation::Final(Err(e)),
|
||||
Continuation::Continue(s) => {
|
||||
let inner: IqClientBodyParserInner = s.into();
|
||||
Continuation::Continue(inner.into())
|
||||
}
|
||||
}
|
||||
IqClientBodyParser(BindRequest::parse().into()).consume(namespace, event)
|
||||
} else if bytes.name().0 == Session::NAME.as_bytes()
|
||||
&& namespace == ResolveResult::Bound(Namespace(Session::NS.as_bytes()))
|
||||
{
|
||||
IqClientBodyParser(Session::parse().into()).consume(namespace, event)
|
||||
} else {
|
||||
Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")))
|
||||
}
|
||||
|
@ -67,6 +71,14 @@ impl Parser for IqClientBodyParser {
|
|||
Continuation::Continue(inner.into())
|
||||
}
|
||||
},
|
||||
SessionV(p) => match p.consume(namespace, event) {
|
||||
Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())),
|
||||
Continuation::Final(Err(e)) => Continuation::Final(Err(e)),
|
||||
Continuation::Continue(s) => {
|
||||
let inner: IqClientBodyParserInner = s.into();
|
||||
Continuation::Continue(inner.into())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
|
|||
use quick_xml::name::{Namespace, ResolveResult};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::util::xml::{Continuation, FromXml, Parser, ToXml};
|
||||
use crate::util::xml::*;
|
||||
|
||||
pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-bind";
|
||||
|
||||
|
@ -55,9 +55,9 @@ enum BindRequestParserInner {
|
|||
InBindResourceEnd(String),
|
||||
}
|
||||
|
||||
impl BindRequest {
|
||||
pub const NS: &'static str = XMLNS;
|
||||
pub const NAME: &'static str = "bind";
|
||||
impl FromXmlTag for BindRequest {
|
||||
const NS: &'static str = XMLNS;
|
||||
const NAME: &'static str = "bind";
|
||||
}
|
||||
|
||||
impl FromXml for BindRequest {
|
||||
|
|
|
@ -21,9 +21,9 @@ pub struct Message {
|
|||
pub body: String,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub const NS: &'static str = XMLNS;
|
||||
pub const NAME: &'static str = "message";
|
||||
impl FromXmlTag for Message {
|
||||
const NS: &'static str = XMLNS;
|
||||
const NAME: &'static str = "message";
|
||||
}
|
||||
|
||||
impl FromXml for Message {
|
||||
|
@ -180,9 +180,9 @@ pub struct Iq<T> {
|
|||
pub body: T,
|
||||
}
|
||||
|
||||
impl<T> Iq<T> {
|
||||
pub const NS: &'static str = XMLNS;
|
||||
pub const NAME: &'static str = "iq";
|
||||
impl<T: FromXml> FromXmlTag for Iq<T> {
|
||||
const NAME: &'static str = "iq";
|
||||
const NS: &'static str = XMLNS;
|
||||
}
|
||||
|
||||
impl<T: FromXml> FromXml for Iq<T> {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod bind;
|
||||
pub mod client;
|
||||
pub mod sasl;
|
||||
pub mod session;
|
||||
pub mod stanzaerror;
|
||||
pub mod stream;
|
||||
pub mod tls;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
use quick_xml::events::{BytesStart, Event};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::util::xml::*;
|
||||
|
||||
pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-session";
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Session;
|
||||
|
||||
pub struct SessionParser(SessionParserInner);
|
||||
|
||||
enum SessionParserInner {
|
||||
Initial,
|
||||
InSession,
|
||||
}
|
||||
|
||||
impl Parser for SessionParser {
|
||||
type Output = Result<Session>;
|
||||
|
||||
fn consume<'a>(
|
||||
self: Self,
|
||||
namespace: quick_xml::name::ResolveResult,
|
||||
event: &quick_xml::events::Event<'a>,
|
||||
) -> Continuation<Self, Self::Output> {
|
||||
match self.0 {
|
||||
SessionParserInner::Initial => match event {
|
||||
Event::Start(_) => {
|
||||
Continuation::Continue(SessionParser(SessionParserInner::InSession))
|
||||
}
|
||||
Event::Empty(_) => Continuation::Final(Ok(Session)),
|
||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||
},
|
||||
SessionParserInner::InSession => match event {
|
||||
Event::End(_) => Continuation::Final(Ok(Session)),
|
||||
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromXml for Session {
|
||||
type P = SessionParser;
|
||||
|
||||
fn parse() -> Self::P {
|
||||
SessionParser(SessionParserInner::Initial)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromXmlTag for Session {
|
||||
const NAME: &'static str = "session";
|
||||
const NS: &'static str = XMLNS;
|
||||
}
|
||||
|
||||
impl ToXml for Session {
|
||||
fn serialize(&self, events: &mut Vec<Event<'static>>) {
|
||||
events.push(Event::Empty(BytesStart::new(format!(
|
||||
r#"session xmlns="{}""#,
|
||||
XMLNS
|
||||
))));
|
||||
}
|
||||
}
|
|
@ -13,6 +13,11 @@ pub trait ToXml: Sized {
|
|||
fn serialize(&self, events: &mut Vec<Event<'static>>);
|
||||
}
|
||||
|
||||
pub trait FromXmlTag: FromXml {
|
||||
const NAME: &'static str;
|
||||
const NS: &'static str;
|
||||
}
|
||||
|
||||
pub trait Parser: Sized {
|
||||
type Output;
|
||||
|
||||
|
|
Loading…
Reference in New Issue