xmpp: split wait_for_events methods
Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
e23c161c0a
commit
9d17a79813
1 changed files with 112 additions and 121 deletions
127
xmpp/src/lib.rs
127
xmpp/src/lib.rs
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue