forked from lavina/lavina
feat(xmpp): roster query stub
This commit is contained in:
parent
33dbfba116
commit
6add6db371
|
@ -25,6 +25,7 @@ use crate::prelude::*;
|
||||||
use crate::protos::xmpp;
|
use crate::protos::xmpp;
|
||||||
use crate::protos::xmpp::bind::{BindResponse, Jid, Name, Server};
|
use crate::protos::xmpp::bind::{BindResponse, Jid, Name, Server};
|
||||||
use crate::protos::xmpp::client::Iq;
|
use crate::protos::xmpp::client::Iq;
|
||||||
|
use crate::protos::xmpp::roster::RosterQuery;
|
||||||
use crate::protos::xmpp::session::Session;
|
use crate::protos::xmpp::session::Session;
|
||||||
use crate::protos::xmpp::stream::*;
|
use crate::protos::xmpp::stream::*;
|
||||||
use crate::util::xml::{Continuation, FromXml, Parser, ToXml};
|
use crate::util::xml::{Continuation, FromXml, Parser, ToXml};
|
||||||
|
@ -317,6 +318,21 @@ async fn socket_final(
|
||||||
}
|
}
|
||||||
xml_writer.get_mut().flush().await?;
|
xml_writer.get_mut().flush().await?;
|
||||||
}
|
}
|
||||||
|
proto::IqClientBody::Roster(_) => {
|
||||||
|
let mut events = vec![];
|
||||||
|
let req = Iq {
|
||||||
|
from: None,
|
||||||
|
id: iq.id,
|
||||||
|
to: None,
|
||||||
|
r#type: xmpp::client::IqType::Result,
|
||||||
|
body: RosterQuery,
|
||||||
|
};
|
||||||
|
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!(),
|
proto::ClientPacket::Message(_) => todo!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,9 @@ use quick_xml::name::{Namespace, ResolveResult};
|
||||||
|
|
||||||
use crate::protos::xmpp::bind::BindRequest;
|
use crate::protos::xmpp::bind::BindRequest;
|
||||||
use crate::protos::xmpp::client::{Iq, Message};
|
use crate::protos::xmpp::client::{Iq, Message};
|
||||||
|
use crate::protos::xmpp::roster::RosterQuery;
|
||||||
use crate::protos::xmpp::session::Session;
|
use crate::protos::xmpp::session::Session;
|
||||||
use crate::util::xml::{Continuation, FromXml, FromXmlTag, Parser};
|
use crate::util::xml::*;
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ use crate::prelude::*;
|
||||||
pub enum IqClientBody {
|
pub enum IqClientBody {
|
||||||
Bind(BindRequest),
|
Bind(BindRequest),
|
||||||
Session(Session),
|
Session(Session),
|
||||||
|
Roster(RosterQuery),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(From)]
|
#[derive(From)]
|
||||||
|
@ -23,6 +25,7 @@ enum IqClientBodyParserInner {
|
||||||
Initial,
|
Initial,
|
||||||
Bind(<BindRequest as FromXml>::P),
|
Bind(<BindRequest as FromXml>::P),
|
||||||
SessionV(<Session as FromXml>::P),
|
SessionV(<Session as FromXml>::P),
|
||||||
|
RosterV(<RosterQuery as FromXml>::P),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromXml for IqClientBody {
|
impl FromXml for IqClientBody {
|
||||||
|
@ -51,34 +54,16 @@ impl Parser for IqClientBodyParser {
|
||||||
return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")))
|
return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if bytes.name().0 == BindRequest::NAME.as_bytes()
|
let name = bytes.name();
|
||||||
&& namespace == ResolveResult::Bound(Namespace(BindRequest::NS.as_bytes()))
|
match_parser!(IqClientBodyParser, name, namespace, event;
|
||||||
{
|
BindRequest,
|
||||||
IqClientBodyParser(BindRequest::parse().into()).consume(namespace, event)
|
Session,
|
||||||
} else if bytes.name().0 == Session::NAME.as_bytes()
|
RosterQuery
|
||||||
&& namespace == ResolveResult::Bound(Namespace(Session::NS.as_bytes()))
|
)
|
||||||
{
|
|
||||||
IqClientBodyParser(Session::parse().into()).consume(namespace, event)
|
|
||||||
} else {
|
|
||||||
Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")))
|
|
||||||
}
|
}
|
||||||
}
|
Bind(p) => delegate_parsing!(p, IqClientBodyParserInner, namespace, event),
|
||||||
Bind(p) => match p.consume(namespace, event) {
|
SessionV(p) => delegate_parsing!(p, IqClientBodyParserInner, namespace, event),
|
||||||
Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())),
|
RosterV(p) => delegate_parsing!(p, IqClientBodyParserInner, namespace, event),
|
||||||
Continuation::Final(Err(e)) => Continuation::Final(Err(e)),
|
|
||||||
Continuation::Continue(s) => {
|
|
||||||
let inner: IqClientBodyParserInner = s.into();
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,35 +106,14 @@ impl Parser for ClientPacketParser {
|
||||||
let Event::Start(bytes) = event else {
|
let Event::Start(bytes) = event else {
|
||||||
return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")));
|
return Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")));
|
||||||
};
|
};
|
||||||
if bytes.name().0 == Iq::<IqClientBody>::NAME.as_bytes()
|
let name = bytes.name();
|
||||||
&& namespace
|
match_parser!(ClientPacketParser, name, namespace, event;
|
||||||
== ResolveResult::Bound(Namespace(Iq::<IqClientBody>::NS.as_bytes()))
|
Iq::<IqClientBody>,
|
||||||
{
|
Message
|
||||||
ClientPacketParser(IqV(Iq::<IqClientBody>::parse())).consume(namespace, event)
|
)
|
||||||
} else if bytes.name().0 == Message::NAME.as_bytes()
|
|
||||||
&& namespace == ResolveResult::Bound(Namespace(Message::NS.as_bytes()))
|
|
||||||
{
|
|
||||||
ClientPacketParser(MessageV(Message::parse())).consume(namespace, event)
|
|
||||||
} else {
|
|
||||||
Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}")))
|
|
||||||
}
|
}
|
||||||
}
|
IqV(p) => delegate_parsing!(p, ClientPacketParserInner, namespace, event),
|
||||||
IqV(p) => match p.consume(namespace, event) {
|
MessageV(p) => delegate_parsing!(p, ClientPacketParserInner, namespace, event),
|
||||||
Continuation::Final(Ok(r)) => Continuation::Final(Ok(r.into())),
|
|
||||||
Continuation::Final(Err(e)) => Continuation::Final(Err(e)),
|
|
||||||
Continuation::Continue(s) => {
|
|
||||||
let inner: ClientPacketParserInner = s.into();
|
|
||||||
Continuation::Continue(inner.into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
MessageV(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: ClientPacketParserInner = s.into();
|
|
||||||
Continuation::Continue(inner.into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod bind;
|
pub mod bind;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
pub mod roster;
|
||||||
pub mod sasl;
|
pub mod sasl;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
pub mod stanzaerror;
|
pub mod stanzaerror;
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
use quick_xml::events::{BytesStart, Event};
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
use crate::util::xml::*;
|
||||||
|
|
||||||
|
pub const XMLNS: &'static str = "jabber:iq:roster";
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
|
pub struct RosterQuery;
|
||||||
|
|
||||||
|
pub struct QueryParser(QueryParserInner);
|
||||||
|
|
||||||
|
enum QueryParserInner {
|
||||||
|
Initial,
|
||||||
|
InQuery,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parser for QueryParser {
|
||||||
|
type Output = Result<RosterQuery>;
|
||||||
|
|
||||||
|
fn consume<'a>(
|
||||||
|
self: Self,
|
||||||
|
namespace: quick_xml::name::ResolveResult,
|
||||||
|
event: &quick_xml::events::Event<'a>,
|
||||||
|
) -> Continuation<Self, Self::Output> {
|
||||||
|
match self.0 {
|
||||||
|
QueryParserInner::Initial => match event {
|
||||||
|
Event::Start(_) => Continuation::Continue(QueryParser(QueryParserInner::InQuery)),
|
||||||
|
Event::Empty(_) => Continuation::Final(Ok(RosterQuery)),
|
||||||
|
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||||
|
},
|
||||||
|
QueryParserInner::InQuery => match event {
|
||||||
|
Event::End(_) => Continuation::Final(Ok(RosterQuery)),
|
||||||
|
_ => Continuation::Final(Err(ffail!("Unexpected XML event: {event:?}"))),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromXml for RosterQuery {
|
||||||
|
type P = QueryParser;
|
||||||
|
|
||||||
|
fn parse() -> Self::P {
|
||||||
|
QueryParser(QueryParserInner::Initial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromXmlTag for RosterQuery {
|
||||||
|
const NAME: &'static str = "query";
|
||||||
|
const NS: &'static str = XMLNS;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToXml for RosterQuery {
|
||||||
|
fn serialize(&self, events: &mut Vec<Event<'static>>) {
|
||||||
|
events.push(Event::Empty(BytesStart::new(format!(
|
||||||
|
r#"query xmlns="{}""#,
|
||||||
|
XMLNS
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,4 +42,36 @@ macro_rules! fail_fast {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! delegate_parsing {
|
||||||
|
($parser: ident, $intermediate: ident, $namespace: expr, $event: expr) => {
|
||||||
|
match $parser.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: $intermediate = s.into();
|
||||||
|
Continuation::Continue(inner.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! match_parser {
|
||||||
|
($outer: ident, $name: expr, $ns: expr, $event: expr; $subtype: ty) => {
|
||||||
|
if $name.0 == <$subtype as FromXmlTag>::NAME.as_bytes() && $ns == ResolveResult::Bound(Namespace(<$subtype as FromXmlTag>::NS.as_bytes())) {
|
||||||
|
$outer(<$subtype as FromXml>::parse().into()).consume($ns, $event)
|
||||||
|
} else {
|
||||||
|
Continuation::Final(Err(ffail!("Unexpected XML event of name {:?} in namespace {:?}", $name, $ns)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($outer: ident, $name: expr, $ns: expr, $event: expr; $subtype: ty, $($rest: ty),+) => {
|
||||||
|
if $name.0 == <$subtype as FromXmlTag>::NAME.as_bytes() && $ns == ResolveResult::Bound(Namespace(<$subtype as FromXmlTag>::NS.as_bytes())) {
|
||||||
|
$outer(<$subtype as FromXml>::parse().into()).consume($ns, $event)
|
||||||
|
} else {
|
||||||
|
match_parser!($outer, $name, $ns, $event; $($rest),*)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use delegate_parsing;
|
||||||
pub(crate) use fail_fast;
|
pub(crate) use fail_fast;
|
||||||
|
pub(crate) use match_parser;
|
||||||
|
|
Loading…
Reference in New Issue