xmpp: split wait_for_events methods

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2020-09-07 09:56:04 +02:00
commit 9d17a79813
No known key found for this signature in database
GPG key ID: DEDA74AEECA9D0F2

View file

@ -27,7 +27,7 @@ use xmpp_parsers::{
pubsub::pubsub::{Items, PubSub}, pubsub::pubsub::{Items, PubSub},
roster::{Item as RosterItem, Roster}, roster::{Item as RosterItem, Roster},
stanza_error::{DefinedCondition, ErrorType, StanzaError}, stanza_error::{DefinedCondition, ErrorType, StanzaError},
BareJid, FullJid, Jid, BareJid, Element, FullJid, Jid,
}; };
#[macro_use] #[macro_use]
extern crate log; extern crate log;
@ -236,41 +236,7 @@ impl Agent {
presence presence
} }
pub async fn wait_for_events(&mut self) -> Option<Vec<Event>> { async fn handle_iq(&mut self, iq: Iq) -> () {
if let Some(event) = self.client.next().await {
let mut events = Vec::new();
match event {
TokioXmppEvent::Online { resumed: false, .. } => {
let presence = Self::make_initial_presence(&self.disco, &self.node).into();
let _ = self.client.send_stanza(presence).await;
events.push(Event::Online);
// TODO: only send this when the ContactList feature is enabled.
let iq = Iq::from_get(
"roster",
Roster {
ver: None,
items: vec![],
},
)
.into();
let _ = self.client.send_stanza(iq).await;
// TODO: only send this when the JoinRooms feature is enabled.
let iq =
Iq::from_get("bookmarks", PubSub::Items(Items::new(ns::BOOKMARKS2))).into();
let _ = self.client.send_stanza(iq).await;
}
TokioXmppEvent::Online { resumed: true, .. } => {}
TokioXmppEvent::Disconnected(_) => {
events.push(Event::Disconnected);
}
TokioXmppEvent::Stanza(stanza) => {
if stanza.is("iq", "jabber:client") {
let iq = Iq::try_from(stanza).unwrap();
let from = iq
.from
.clone()
.unwrap_or_else(|| self.client.bound_jid().unwrap().clone());
if let IqType::Get(payload) = iq.payload { if let IqType::Get(payload) = iq.payload {
if payload.is("query", ns::DISCO_INFO) { if payload.is("query", ns::DISCO_INFO) {
let query = DiscoInfoQuery::try_from(payload); let query = DiscoInfoQuery::try_from(payload);
@ -309,33 +275,11 @@ impl Agent {
.into(); .into();
let _ = self.client.send_stanza(iq).await; let _ = self.client.send_stanza(iq).await;
} }
} else if let IqType::Result(Some(payload)) = iq.payload {
// TODO: move private iqs like this one somewhere else, for
// security reasons.
if payload.is("query", ns::ROSTER) && iq.from.is_none() {
let roster = Roster::try_from(payload).unwrap();
for item in roster.items.into_iter() {
events.push(Event::ContactAdded(item));
} }
} else if payload.is("pubsub", ns::PUBSUB) {
let new_events = pubsub::handle_iq_result(&from, payload);
events.extend(new_events);
} }
} else if let IqType::Set(_) = iq.payload {
// We MUST answer unhandled set iqs with a service-unavailable error. async fn handle_message(&mut self, message: Message) -> Vec<Event> {
let error = StanzaError::new( let mut events = vec![];
ErrorType::Cancel,
DefinedCondition::ServiceUnavailable,
"en",
"No handler defined for this kind of iq.",
);
let iq = Iq::from_error(iq.id, error)
.with_to(iq.from.unwrap())
.into();
let _ = self.client.send_stanza(iq).await;
}
} else if stanza.is("message", "jabber:client") {
let message = Message::try_from(stanza).unwrap();
let from = message.from.clone().unwrap(); let from = message.from.clone().unwrap();
let langs: Vec<&str> = self.lang.iter().map(String::as_str).collect(); let langs: Vec<&str> = self.lang.iter().map(String::as_str).collect();
match message.get_best_body(langs) { match message.get_best_body(langs) {
@ -349,8 +293,7 @@ impl Agent {
events.push(event) events.push(event)
} }
MessageType::Chat | MessageType::Normal => { MessageType::Chat | MessageType::Normal => {
let event = let event = Event::ChatMessage(from.clone().into(), body.clone());
Event::ChatMessage(from.clone().into(), body.clone());
events.push(event) events.push(event)
} }
_ => (), _ => (),
@ -363,8 +306,12 @@ impl Agent {
events.extend(new_events); events.extend(new_events);
} }
} }
} else if stanza.is("presence", "jabber:client") {
let presence = Presence::try_from(stanza).unwrap(); events
}
async fn handle_presence(&mut self, presence: Presence) -> Vec<Event> {
let mut events = vec![];
let from: BareJid = match presence.from.clone().unwrap() { let from: BareJid = match presence.from.clone().unwrap() {
Jid::Full(FullJid { node, domain, .. }) => BareJid { node, domain }, Jid::Full(FullJid { node, domain, .. }) => BareJid { node, domain },
Jid::Bare(bare) => bare, Jid::Bare(bare) => bare,
@ -381,10 +328,54 @@ impl Agent {
} }
} }
} }
} else if stanza.is("error", "http://etherx.jabber.org/streams") {
println!("Received a fatal stream error: {}", String::from(&stanza)); events
}
pub async fn wait_for_events(&mut self) -> Option<Vec<Event>> {
if let Some(event) = self.client.next().await {
let mut events = Vec::new();
match event {
TokioXmppEvent::Online { resumed: false, .. } => {
let presence = Self::make_initial_presence(&self.disco, &self.node).into();
let _ = self.client.send_stanza(presence).await;
events.push(Event::Online);
// TODO: only send this when the ContactList feature is enabled.
let iq = Iq::from_get(
"roster",
Roster {
ver: None,
items: vec![],
},
)
.into();
let _ = self.client.send_stanza(iq).await;
// TODO: only send this when the JoinRooms feature is enabled.
let iq =
Iq::from_get("bookmarks", PubSub::Items(Items::new(ns::BOOKMARKS2))).into();
let _ = self.client.send_stanza(iq).await;
}
TokioXmppEvent::Online { resumed: true, .. } => {}
TokioXmppEvent::Disconnected(_) => {
events.push(Event::Disconnected);
}
TokioXmppEvent::Stanza(elem) => {
if elem.is("iq", "jabber:client") {
let iq = Iq::try_from(elem).unwrap();
self.handle_iq(iq).await;
} else if elem.is("message", "jabber:client") {
let message = Message::try_from(elem).unwrap();
let new_events = self.handle_message(message).await;
events.extend(new_events);
} else if elem.is("presence", "jabber:client") {
let presence = Presence::try_from(elem).unwrap();
let new_events = self.handle_presence(presence).await;
events.extend(new_events);
} else if elem.is("error", "http://etherx.jabber.org/streams") {
println!("Received a fatal stream error: {}", String::from(&elem));
} else { } else {
panic!("Unknown stanza: {}", String::from(&stanza)); panic!("Unknown stanza: {}", String::from(&elem));
} }
} }
} }