//! 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, IqError, IqErrorType, 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>, iq: Iq) { 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: IqError { r#type: IqErrorType::Cancel, }, }; 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 } }