forked from lavina/lavina
1
0
Fork 0

feat(xmpp): answer to bind requests

This commit is contained in:
Nikita Vilunov 2023-03-12 13:25:23 +01:00
parent 4730526fee
commit 4107c5b663
4 changed files with 104 additions and 10 deletions

View File

@ -23,8 +23,10 @@ use crate::core::player::PlayerRegistry;
use crate::core::room::RoomRegistry; use crate::core::room::RoomRegistry;
use crate::prelude::*; use crate::prelude::*;
use crate::protos::xmpp; use crate::protos::xmpp;
use crate::protos::xmpp::bind::{BindResponse, Jid, Name, Server};
use crate::protos::xmpp::client::Iq;
use crate::protos::xmpp::stream::*; use crate::protos::xmpp::stream::*;
use crate::util::xml::{Continuation, FromXml, Parser}; use crate::util::xml::{Continuation, FromXml, Parser, ToXml};
use crate::util::Terminator; use crate::util::Terminator;
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
@ -277,7 +279,31 @@ async fn socket_final(
match parser.consume(ns, &event) { match parser.consume(ns, &event) {
Continuation::Final(res) => { Continuation::Final(res) => {
let res = res?; let res = res?;
dbg!(res); dbg!(&res);
match res {
proto::ClientPacket::Iq(iq) => match iq.body {
proto::IqClientBody::Bind(b) => {
let mut events = vec![];
let req = Iq {
from: None,
id: iq.id,
to: None,
r#type: xmpp::client::IqType::Result,
body: BindResponse(Jid {
name: Name("darova".to_string()),
server: Server("localhost".to_string()),
resource: b.0,
}),
};
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!(),
}
parser = proto::ClientPacket::parse(); parser = proto::ClientPacket::parse();
} }
Continuation::Continue(p) => parser = p, Continuation::Continue(p) => parser = p,

View File

@ -1,17 +1,19 @@
use nom::AsBytes; use nom::AsBytes;
use quick_xml::events::Event; use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
use quick_xml::name::{Namespace, ResolveResult}; use quick_xml::name::{Namespace, ResolveResult};
use crate::prelude::*; use crate::prelude::*;
use crate::util::xml::{Continuation, FromXml, Parser}; use crate::util::xml::{Continuation, FromXml, Parser, ToXml};
pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-bind"; pub const XMLNS: &'static str = "urn:ietf:params:xml:ns:xmpp-bind";
#[derive(PartialEq, Eq, Debug)] // TODO remove `pub` in newtypes, introduce validation
pub struct Name(String);
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub struct Server(String); pub struct Name(pub String);
#[derive(PartialEq, Eq, Debug)]
pub struct Server(pub String);
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
pub struct Resource(pub(super) String); pub struct Resource(pub(super) String);
@ -23,6 +25,12 @@ pub struct Jid {
pub resource: Resource, pub resource: Resource,
} }
impl Jid {
pub fn to_string(&self) -> String {
format!("{}@{}/{}", self.name.0, self.server.0, self.resource.0)
}
}
/// Request to bind to a resource. /// Request to bind to a resource.
/// ///
/// Example: /// Example:
@ -121,7 +129,21 @@ impl Parser for BindRequestParser {
} }
} }
pub struct BindResponse(Jid); pub struct BindResponse(pub Jid);
impl ToXml for BindResponse {
fn serialize(&self, events: &mut Vec<Event<'static>>) {
events.extend_from_slice(&[
Event::Start(BytesStart::new(
r#"bind xmlns="urn:ietf:params:xml:ns:xmpp-bind""#,
)),
Event::Start(BytesStart::new(r#"jid"#)),
Event::Text(BytesText::new(self.0.to_string().as_str()).into_owned()),
Event::End(BytesEnd::new("jid")),
Event::End(BytesEnd::new("bind")),
]);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

@ -1,6 +1,7 @@
use derive_more::From; use derive_more::From;
use quick_xml::events::Event; use quick_xml::events::attributes::Attribute;
use quick_xml::name::ResolveResult; use quick_xml::events::{BytesEnd, BytesStart, Event};
use quick_xml::name::{QName, ResolveResult};
use crate::prelude::*; use crate::prelude::*;
use crate::util::xml::*; use crate::util::xml::*;
@ -298,6 +299,47 @@ impl IqType {
t => Err(ffail!("Unknown iq type: {t}")), t => Err(ffail!("Unknown iq type: {t}")),
} }
} }
pub fn as_str(&self) -> &'static str {
match self {
IqType::Error => "error",
IqType::Get => "get",
IqType::Result => "result",
IqType::Set => "set",
}
}
}
impl<T: ToXml> ToXml for Iq<T> {
fn serialize(&self, events: &mut Vec<Event<'static>>) {
let start = format!(r#"iq xmlns="{}""#, XMLNS);
let mut start = BytesStart::new(start);
let mut attrs = vec![];
if let Some(ref from) = self.from {
attrs.push(Attribute {
key: QName(b"from"),
value: from.as_bytes().into(),
});
};
if let Some(ref to) = self.to {
attrs.push(Attribute {
key: QName(b"to"),
value: to.as_bytes().into(),
});
}
attrs.push(Attribute {
key: QName(b"id"),
value: self.id.as_bytes().into(),
});
attrs.push(Attribute {
key: QName(b"type"),
value: self.r#type.as_str().as_bytes().into(),
});
start.extend_attributes(attrs.into_iter());
events.push(Event::Start(start));
self.body.serialize(events);
events.push(Event::End(BytesEnd::new("iq")));
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -9,6 +9,10 @@ pub trait FromXml: Sized {
fn parse() -> Self::P; fn parse() -> Self::P;
} }
pub trait ToXml: Sized {
fn serialize(&self, events: &mut Vec<Event<'static>>);
}
pub trait Parser: Sized { pub trait Parser: Sized {
type Output; type Output;