lavina/crates/projection-xmpp/src/iq.rs

163 lines
5.0 KiB
Rust

//! Handling of all client2server iq stanzas
use quick_xml::events::Event;
use lavina_core::room::RoomRegistry;
use proto_xmpp::bind::{BindResponse, Jid, Name, Resource, Server};
use proto_xmpp::client::{Iq, IqType};
use proto_xmpp::disco::{Feature, Identity, InfoQuery, Item, ItemQuery};
use proto_xmpp::roster::RosterQuery;
use proto_xmpp::session::Session;
use crate::proto::IqClientBody;
use crate::XmppConnection;
use proto_xmpp::xml::ToXml;
impl<'a> XmppConnection<'a> {
pub async fn handle_iq(&self, output: &mut Vec<Event<'static>>, iq: Iq<IqClientBody>) {
match iq.body {
IqClientBody::Bind(b) => {
let req = Iq {
from: None,
id: iq.id,
to: None,
r#type: IqType::Result,
body: BindResponse(Jid {
name: Some(Name("darova".into())),
server: Server("localhost".into()),
resource: Some(Resource("kek".into())),
}),
};
req.serialize(output);
}
IqClientBody::Session(_) => {
let req = Iq {
from: None,
id: iq.id,
to: None,
r#type: IqType::Result,
body: Session,
};
req.serialize(output);
}
IqClientBody::Roster(_) => {
let req = Iq {
from: None,
id: iq.id,
to: None,
r#type: IqType::Result,
body: RosterQuery,
};
req.serialize(output);
}
IqClientBody::DiscoInfo(info) => {
let response = disco_info(iq.to.as_deref(), &info);
let req = Iq {
from: iq.to,
id: iq.id,
to: None,
r#type: IqType::Result,
body: response,
};
req.serialize(output);
}
IqClientBody::DiscoItem(item) => {
let response = disco_items(iq.to.as_deref(), &item, self.rooms).await;
let req = Iq {
from: iq.to,
id: iq.id,
to: None,
r#type: IqType::Result,
body: response,
};
req.serialize(output);
}
_ => {
let req = Iq {
from: None,
id: iq.id,
to: None,
r#type: IqType::Error,
body: (),
};
req.serialize(output);
}
}
}
}
fn disco_info(to: Option<&str>, req: &InfoQuery) -> InfoQuery {
let identity;
let feature;
match to {
Some("localhost") => {
identity = vec![Identity {
category: "server".into(),
name: None,
r#type: "im".into(),
}];
feature = vec![
Feature::new("http://jabber.org/protocol/disco#info"),
Feature::new("http://jabber.org/protocol/disco#items"),
Feature::new("iq"),
Feature::new("presence"),
]
}
Some("rooms.localhost") => {
identity = vec![Identity {
category: "conference".into(),
name: Some("Chat rooms".into()),
r#type: "text".into(),
}];
feature = vec![
Feature::new("http://jabber.org/protocol/disco#info"),
Feature::new("http://jabber.org/protocol/disco#items"),
Feature::new("http://jabber.org/protocol/muc"),
]
}
_ => {
identity = vec![];
feature = vec![];
}
};
InfoQuery {
node: None,
identity,
feature,
}
}
async fn disco_items(to: Option<&str>, req: &ItemQuery, rooms: &RoomRegistry) -> ItemQuery {
let item = match to {
Some("localhost") => {
vec![Item {
jid: Jid {
name: None,
server: Server("rooms.localhost".into()),
resource: None,
},
name: None,
node: None,
}]
}
Some("rooms.localhost") => {
let room_list = rooms.get_all_rooms().await;
room_list
.into_iter()
.map(|room_info| Item {
jid: Jid {
name: Some(Name(room_info.id.into_inner())),
server: Server("rooms.localhost".into()),
resource: None,
},
name: None,
node: None,
})
.collect()
}
_ => vec![],
};
ItemQuery { item }
}