forked from lavina/lavina
xmpp: use the Jid type in IQs' to and from fields, separate presence handling
This commit is contained in:
parent
757d7c5665
commit
6d493d83a3
|
@ -3,7 +3,7 @@
|
||||||
use quick_xml::events::Event;
|
use quick_xml::events::Event;
|
||||||
|
|
||||||
use lavina_core::room::RoomRegistry;
|
use lavina_core::room::RoomRegistry;
|
||||||
use proto_xmpp::bind::{BindResponse, Jid, Name, Resource, Server};
|
use proto_xmpp::bind::{BindResponse, Jid, Name, Server};
|
||||||
use proto_xmpp::client::{Iq, IqError, IqErrorType, IqType};
|
use proto_xmpp::client::{Iq, IqError, IqErrorType, IqType};
|
||||||
use proto_xmpp::disco::{Feature, Identity, InfoQuery, Item, ItemQuery};
|
use proto_xmpp::disco::{Feature, Identity, InfoQuery, Item, ItemQuery};
|
||||||
use proto_xmpp::roster::RosterQuery;
|
use proto_xmpp::roster::RosterQuery;
|
||||||
|
@ -17,7 +17,7 @@ use proto_xmpp::xml::ToXml;
|
||||||
impl<'a> XmppConnection<'a> {
|
impl<'a> XmppConnection<'a> {
|
||||||
pub async fn handle_iq(&self, output: &mut Vec<Event<'static>>, iq: Iq<IqClientBody>) {
|
pub async fn handle_iq(&self, output: &mut Vec<Event<'static>>, iq: Iq<IqClientBody>) {
|
||||||
match iq.body {
|
match iq.body {
|
||||||
IqClientBody::Bind(b) => {
|
IqClientBody::Bind(_) => {
|
||||||
let req = Iq {
|
let req = Iq {
|
||||||
from: None,
|
from: None,
|
||||||
id: iq.id,
|
id: iq.id,
|
||||||
|
@ -52,7 +52,7 @@ impl<'a> XmppConnection<'a> {
|
||||||
req.serialize(output);
|
req.serialize(output);
|
||||||
}
|
}
|
||||||
IqClientBody::DiscoInfo(info) => {
|
IqClientBody::DiscoInfo(info) => {
|
||||||
let response = self.disco_info(iq.to.as_deref(), &info);
|
let response = self.disco_info(iq.to.as_ref(), &info);
|
||||||
let req = Iq {
|
let req = Iq {
|
||||||
from: iq.to,
|
from: iq.to,
|
||||||
id: iq.id,
|
id: iq.id,
|
||||||
|
@ -63,7 +63,7 @@ impl<'a> XmppConnection<'a> {
|
||||||
req.serialize(output);
|
req.serialize(output);
|
||||||
}
|
}
|
||||||
IqClientBody::DiscoItem(item) => {
|
IqClientBody::DiscoItem(item) => {
|
||||||
let response = self.disco_items(iq.to.as_deref(), &item, self.rooms).await;
|
let response = self.disco_items(iq.to.as_ref(), &item, self.rooms).await;
|
||||||
let req = Iq {
|
let req = Iq {
|
||||||
from: iq.to,
|
from: iq.to,
|
||||||
id: iq.id,
|
id: iq.id,
|
||||||
|
@ -88,12 +88,16 @@ impl<'a> XmppConnection<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disco_info(&self, to: Option<&str>, req: &InfoQuery) -> InfoQuery {
|
fn disco_info(&self, to: Option<&Jid>, req: &InfoQuery) -> InfoQuery {
|
||||||
let identity;
|
let identity;
|
||||||
let feature;
|
let feature;
|
||||||
|
|
||||||
match to {
|
match to {
|
||||||
Some(r) if r == &*self.hostname => {
|
Some(Jid {
|
||||||
|
name: None,
|
||||||
|
server,
|
||||||
|
resource: None,
|
||||||
|
}) if server.0 == self.hostname => {
|
||||||
identity = vec![Identity {
|
identity = vec![Identity {
|
||||||
category: "server".into(),
|
category: "server".into(),
|
||||||
name: None,
|
name: None,
|
||||||
|
@ -106,7 +110,11 @@ impl<'a> XmppConnection<'a> {
|
||||||
Feature::new("presence"),
|
Feature::new("presence"),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Some(r) if r == &*self.hostname_rooms => {
|
Some(Jid {
|
||||||
|
name: None,
|
||||||
|
server,
|
||||||
|
resource: None,
|
||||||
|
}) if server.0 == self.hostname_rooms => {
|
||||||
identity = vec![Identity {
|
identity = vec![Identity {
|
||||||
category: "conference".into(),
|
category: "conference".into(),
|
||||||
name: Some("Chat rooms".into()),
|
name: Some("Chat rooms".into()),
|
||||||
|
@ -130,9 +138,13 @@ impl<'a> XmppConnection<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn disco_items(&self, to: Option<&str>, req: &ItemQuery, rooms: &RoomRegistry) -> ItemQuery {
|
async fn disco_items(&self, to: Option<&Jid>, req: &ItemQuery, rooms: &RoomRegistry) -> ItemQuery {
|
||||||
let item = match to {
|
let item = match to {
|
||||||
Some(r) if r == &*self.hostname => {
|
Some(Jid {
|
||||||
|
name: None,
|
||||||
|
server,
|
||||||
|
resource: None,
|
||||||
|
}) if server.0 == self.hostname => {
|
||||||
vec![Item {
|
vec![Item {
|
||||||
jid: Jid {
|
jid: Jid {
|
||||||
name: None,
|
name: None,
|
||||||
|
@ -143,7 +155,11 @@ impl<'a> XmppConnection<'a> {
|
||||||
node: None,
|
node: None,
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
Some(r) if r == &*self.hostname_rooms => {
|
Some(Jid {
|
||||||
|
name: None,
|
||||||
|
server,
|
||||||
|
resource: None,
|
||||||
|
}) if server.0 == self.hostname_rooms => {
|
||||||
let room_list = rooms.get_all_rooms().await;
|
let room_list = rooms.get_all_rooms().await;
|
||||||
room_list
|
room_list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
@ -4,7 +4,7 @@ use quick_xml::events::Event;
|
||||||
|
|
||||||
use lavina_core::prelude::*;
|
use lavina_core::prelude::*;
|
||||||
use lavina_core::room::RoomId;
|
use lavina_core::room::RoomId;
|
||||||
use proto_xmpp::bind::{Jid, Server};
|
use proto_xmpp::bind::{Jid, Name, Server};
|
||||||
use proto_xmpp::client::Presence;
|
use proto_xmpp::client::Presence;
|
||||||
use proto_xmpp::xml::{Ignore, ToXml};
|
use proto_xmpp::xml::{Ignore, ToXml};
|
||||||
|
|
||||||
|
@ -12,8 +12,29 @@ use crate::XmppConnection;
|
||||||
|
|
||||||
impl<'a> XmppConnection<'a> {
|
impl<'a> XmppConnection<'a> {
|
||||||
pub async fn handle_presence(&mut self, output: &mut Vec<Event<'static>>, p: Presence<Ignore>) -> Result<()> {
|
pub async fn handle_presence(&mut self, output: &mut Vec<Event<'static>>, p: Presence<Ignore>) -> Result<()> {
|
||||||
let response = if p.to.is_none() {
|
match p.to {
|
||||||
Presence::<()> {
|
None => {
|
||||||
|
self.self_presence(output).await;
|
||||||
|
}
|
||||||
|
Some(Jid {
|
||||||
|
name: Some(name),
|
||||||
|
server,
|
||||||
|
// resources in MUCs are members' personas – not implemented (yet?)
|
||||||
|
resource: Some(_),
|
||||||
|
}) if server.0 == self.hostname_rooms => {
|
||||||
|
self.muc_presence(name, output).await?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// TODO other presence cases
|
||||||
|
let response = Presence::<()>::default();
|
||||||
|
response.serialize(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn self_presence(&mut self, output: &mut Vec<Event<'static>>) {
|
||||||
|
let response = Presence::<()> {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(self.user.xmpp_name.clone()),
|
name: Some(self.user.xmpp_name.clone()),
|
||||||
server: Server(self.hostname.clone()),
|
server: Server(self.hostname.clone()),
|
||||||
|
@ -25,15 +46,14 @@ impl<'a> XmppConnection<'a> {
|
||||||
resource: Some(self.user.xmpp_resource.clone()),
|
resource: Some(self.user.xmpp_resource.clone()),
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
};
|
||||||
|
response.serialize(output);
|
||||||
}
|
}
|
||||||
} else if let Some(Jid {
|
|
||||||
name: Some(name),
|
async fn muc_presence(&mut self, name: Name, output: &mut Vec<Event<'static>>) -> Result<()> {
|
||||||
server,
|
|
||||||
resource: Some(resource),
|
|
||||||
}) = p.to
|
|
||||||
{
|
|
||||||
let a = self.user_handle.join_room(RoomId::from(name.0.clone())?).await?;
|
let a = self.user_handle.join_room(RoomId::from(name.0.clone())?).await?;
|
||||||
Presence::<()> {
|
// TODO handle bans
|
||||||
|
let response = Presence::<()> {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(self.user.xmpp_name.clone()),
|
name: Some(self.user.xmpp_name.clone()),
|
||||||
server: Server(self.hostname.clone()),
|
server: Server(self.hostname.clone()),
|
||||||
|
@ -45,9 +65,6 @@ impl<'a> XmppConnection<'a> {
|
||||||
resource: Some(self.user.xmpp_muc_name.clone()),
|
resource: Some(self.user.xmpp_muc_name.clone()),
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Presence::<()>::default()
|
|
||||||
};
|
};
|
||||||
response.serialize(output);
|
response.serialize(output);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -295,9 +295,9 @@ impl ToXml for IqError {
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub struct Iq<T> {
|
pub struct Iq<T> {
|
||||||
pub from: Option<String>,
|
pub from: Option<Jid>,
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub to: Option<String>,
|
pub to: Option<Jid>,
|
||||||
pub r#type: IqType,
|
pub r#type: IqType,
|
||||||
pub body: T,
|
pub body: T,
|
||||||
}
|
}
|
||||||
|
@ -323,9 +323,9 @@ enum IqParserInner<T: FromXml> {
|
||||||
Final(IqParserState<T>),
|
Final(IqParserState<T>),
|
||||||
}
|
}
|
||||||
struct IqParserState<T> {
|
struct IqParserState<T> {
|
||||||
pub from: Option<String>,
|
pub from: Option<Jid>,
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
pub to: Option<String>,
|
pub to: Option<Jid>,
|
||||||
pub r#type: Option<IqType>,
|
pub r#type: Option<IqType>,
|
||||||
pub body: Option<T>,
|
pub body: Option<T>,
|
||||||
}
|
}
|
||||||
|
@ -348,13 +348,15 @@ impl<T: FromXml> Parser for IqParser<T> {
|
||||||
let attr = fail_fast!(attr);
|
let attr = fail_fast!(attr);
|
||||||
if attr.key.0 == b"from" {
|
if attr.key.0 == b"from" {
|
||||||
let value = fail_fast!(std::str::from_utf8(&*attr.value));
|
let value = fail_fast!(std::str::from_utf8(&*attr.value));
|
||||||
state.from = Some(value.to_string())
|
let value = fail_fast!(Jid::from_string(value));
|
||||||
|
state.from = Some(value)
|
||||||
} else if attr.key.0 == b"id" {
|
} else if attr.key.0 == b"id" {
|
||||||
let value = fail_fast!(std::str::from_utf8(&*attr.value));
|
let value = fail_fast!(std::str::from_utf8(&*attr.value));
|
||||||
state.id = Some(value.to_string())
|
state.id = Some(value.to_string())
|
||||||
} else if attr.key.0 == b"to" {
|
} else if attr.key.0 == b"to" {
|
||||||
let value = fail_fast!(std::str::from_utf8(&*attr.value));
|
let value = fail_fast!(std::str::from_utf8(&*attr.value));
|
||||||
state.to = Some(value.to_string())
|
let value = fail_fast!(Jid::from_string(value));
|
||||||
|
state.to = Some(value)
|
||||||
} else if attr.key.0 == b"type" {
|
} else if attr.key.0 == b"type" {
|
||||||
let value = fail_fast!(IqType::from_str(&*attr.value));
|
let value = fail_fast!(IqType::from_str(&*attr.value));
|
||||||
state.r#type = Some(value);
|
state.r#type = Some(value);
|
||||||
|
@ -431,15 +433,17 @@ impl<T: ToXml> ToXml for Iq<T> {
|
||||||
let mut start = BytesStart::new(start);
|
let mut start = BytesStart::new(start);
|
||||||
let mut attrs = vec![];
|
let mut attrs = vec![];
|
||||||
if let Some(ref from) = self.from {
|
if let Some(ref from) = self.from {
|
||||||
|
let value = from.to_string().into_bytes();
|
||||||
attrs.push(Attribute {
|
attrs.push(Attribute {
|
||||||
key: QName(b"from"),
|
key: QName(b"from"),
|
||||||
value: from.as_bytes().into(),
|
value: value.into(),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
if let Some(ref to) = self.to {
|
if let Some(ref to) = self.to {
|
||||||
|
let value = to.to_string().into_bytes();
|
||||||
attrs.push(Attribute {
|
attrs.push(Attribute {
|
||||||
key: QName(b"to"),
|
key: QName(b"to"),
|
||||||
value: to.as_bytes().into(),
|
value: value.into(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
attrs.push(Attribute {
|
attrs.push(Attribute {
|
||||||
|
|
Loading…
Reference in New Issue