From 406dfdea987e56ef9557be1fff62a28095f48f77 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 27 May 2017 16:25:31 +0100 Subject: [PATCH 1/4] initialise the StanzaPlugin in the client example --- examples/client.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/client.rs b/examples/client.rs index de8fa517..290e69a7 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -2,6 +2,7 @@ extern crate xmpp; use xmpp::jid::Jid; use xmpp::client::ClientBuilder; +use xmpp::plugins::stanza::StanzaPlugin; use xmpp::plugins::messaging::{MessagingPlugin, MessageEvent}; use xmpp::plugins::presence::{PresencePlugin, Show}; use xmpp::plugins::ping::{PingPlugin, PingEvent}; @@ -15,6 +16,7 @@ fn main() { .password(pass) .connect() .unwrap(); + client.register_plugin(StanzaPlugin::new()); client.register_plugin(MessagingPlugin::new()); client.register_plugin(PresencePlugin::new()); client.register_plugin(PingPlugin::new()); From ca882fd13ad4f366a13908b3e979c0fbbbb69214 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 27 May 2017 16:25:59 +0100 Subject: [PATCH 2/4] prevent the presence plugin from generating an illegal show element --- src/plugins/presence.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/presence.rs b/src/plugins/presence.rs index 147ac28e..e63b5b3e 100644 --- a/src/plugins/presence.rs +++ b/src/plugins/presence.rs @@ -81,13 +81,13 @@ impl PresencePlugin { .build(); stanza.append_child(elem); } - let mut elem = Element::builder("show") - .ns(ns::CLIENT) - .build(); if show != Show::Available { + let mut elem = Element::builder("show") + .ns(ns::CLIENT) + .build(); elem.append_text_node(show.to_string()); + stanza.append_child(elem); } - stanza.append_child(elem); self.proxy.send(stanza); } Ok(()) From 8e7b7ae31c95592855c8d62f6da9a699862a2ca2 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 27 May 2017 16:37:21 +0100 Subject: [PATCH 3/4] simplify the presence plugin using xmpp-parsers --- examples/client.rs | 4 +- src/plugins/presence.rs | 98 +++++++++-------------------------------- 2 files changed, 23 insertions(+), 79 deletions(-) diff --git a/examples/client.rs b/examples/client.rs index 290e69a7..b136da78 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -4,7 +4,7 @@ use xmpp::jid::Jid; use xmpp::client::ClientBuilder; use xmpp::plugins::stanza::StanzaPlugin; use xmpp::plugins::messaging::{MessagingPlugin, MessageEvent}; -use xmpp::plugins::presence::{PresencePlugin, Show}; +use xmpp::plugins::presence::{PresencePlugin, Type}; use xmpp::plugins::ping::{PingPlugin, PingEvent}; use std::env; @@ -20,7 +20,7 @@ fn main() { client.register_plugin(MessagingPlugin::new()); client.register_plugin(PresencePlugin::new()); client.register_plugin(PingPlugin::new()); - client.plugin::().set_presence(Show::Available, None).unwrap(); + client.plugin::().set_presence(Type::Available, None, None).unwrap(); client.main().unwrap(); /*loop { let event = client.next_event().unwrap(); diff --git a/src/plugins/presence.rs b/src/plugins/presence.rs index e63b5b3e..344dd1f6 100644 --- a/src/plugins/presence.rs +++ b/src/plugins/presence.rs @@ -1,56 +1,9 @@ +use std::collections::BTreeMap; + use error::Error; use plugin::PluginProxy; -use minidom::Element; - -use ns; - -use std::fmt; - -use std::str::FromStr; - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum Show { - Available, - Away, - ExtendedAway, - DoNotDisturb, - Chat, - Unavailable, -} - -impl fmt::Display for Show { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - Show::Away => write!(fmt, "away"), - Show::ExtendedAway => write!(fmt, "xa"), - Show::DoNotDisturb => write!(fmt, "dnd"), - Show::Chat => write!(fmt, "chat"), - - // will never be seen inside a , maybe should crash? - Show::Available => write!(fmt, "available"), - Show::Unavailable => write!(fmt, "unavailable"), - } - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct InvalidShow; - -impl FromStr for Show { - type Err = InvalidShow; - - fn from_str(s: &str) -> Result { - Ok(match s { - "away" => Show::Away, - "xa" => Show::ExtendedAway, - "dnd" => Show::DoNotDisturb, - "chat" => Show::Chat, - - _ => { return Err(InvalidShow); } - }) - } -} +pub use xmpp_parsers::presence::{Presence, PresenceType as Type, Show}; pub struct PresencePlugin { proxy: PluginProxy, @@ -63,33 +16,24 @@ impl PresencePlugin { } } - pub fn set_presence(&self, show: Show, status: Option) -> Result<(), Error> { - if show == Show::Unavailable { - self.proxy.send(Element::builder("presence") - .ns(ns::CLIENT) - .attr("type", "unavailable") - .build()); - } - else { - let mut stanza = Element::builder("presence") - .ns(ns::CLIENT) - .build(); - if let Some(stat) = status { - let elem = Element::builder("status") - .ns(ns::CLIENT) - .append(stat) - .build(); - stanza.append_child(elem); - } - if show != Show::Available { - let mut elem = Element::builder("show") - .ns(ns::CLIENT) - .build(); - elem.append_text_node(show.to_string()); - stanza.append_child(elem); - } - self.proxy.send(stanza); - } + pub fn set_presence(&self, type_: Type, show: Option, status: Option) -> Result<(), Error> { + let presence = Presence { + from: None, + to: None, + id: None, + type_: type_, + show: show, + priority: 0i8, + statuses: { + let mut statuses = BTreeMap::new(); + if let Some(status) = status { + statuses.insert(String::new(), status); + } + statuses + }, + payloads: vec!(), + }; + self.proxy.send(presence.into()); Ok(()) } } From c48086bc9c4c6df767c5242f349a22d6d7b27eda Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 27 May 2017 16:44:32 +0100 Subject: [PATCH 4/4] rewrite the ping plugin to make it use the stanza plugin --- src/plugins/ping.rs | 61 +++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/plugins/ping.rs b/src/plugins/ping.rs index 6fffe8b9..f409a1ee 100644 --- a/src/plugins/ping.rs +++ b/src/plugins/ping.rs @@ -1,14 +1,17 @@ +use std::convert::TryFrom; + use plugin::PluginProxy; -use event::{Event, Priority, Propagation, ReceiveElement}; -use minidom::Element; +use event::{Event, Priority, Propagation}; use error::Error; use jid::Jid; -use ns; + +use plugins::stanza::Iq; +use xmpp_parsers::iq::{IqType, IqPayload}; +use xmpp_parsers::ping::Ping; #[derive(Debug)] pub struct PingEvent { pub from: Jid, - pub to: Jid, pub id: String, } @@ -26,39 +29,43 @@ impl PingPlugin { } pub fn send_ping(&self, to: &Jid) -> Result<(), Error> { - let mut elem = Element::builder("iq") - .attr("type", "get") - .attr("to", to.to_string()) - .build(); - elem.append_child(Element::builder("ping").ns(ns::PING).build()); - self.proxy.send(elem); + let to = to.clone(); + self.proxy.send(Iq { + from: None, + to: Some(to), + // TODO: use a generic way to generate ids. + id: Some(String::from("id")), + payload: IqType::Get(IqPayload::Ping(Ping).into()), + }.into()); Ok(()) } - pub fn reply_ping(&self, event: &PingEvent) { - let reply = Element::builder("iq") - .attr("type", "result") - .attr("to", event.from.to_string()) - .attr("id", event.id.to_string()) - .build(); - self.proxy.send(reply); - } - - fn handle_receive_element(&self, evt: &ReceiveElement) -> Propagation { - let elem = &evt.0; - if elem.is("iq", ns::CLIENT) && elem.attr("type") == Some("get") { - if elem.has_child("ping", ns::PING) { + fn handle_iq(&self, iq: &Iq) -> Propagation { + let iq = iq.clone(); + if let IqType::Get(payload) = iq.payload { + // TODO: use an intermediate plugin to parse this payload. + if let Ok(IqPayload::Ping(_)) = IqPayload::try_from(payload) { self.proxy.dispatch(PingEvent { // TODO: safety!!! - from: elem.attr("from").unwrap().parse().unwrap(), - to: elem.attr("to").unwrap().parse().unwrap(), - id: elem.attr("id").unwrap().parse().unwrap(), + from: iq.from.unwrap(), + id: iq.id.unwrap(), }); } } Propagation::Continue } + + fn reply_ping(&self, ping: &PingEvent) -> Propagation { + self.proxy.send(Iq { + from: None, + to: Some(ping.from.to_owned()), + id: Some(ping.id.to_owned()), + payload: IqType::Result(None), + }.into()); + Propagation::Continue + } } impl_plugin!(PingPlugin, proxy, [ - (ReceiveElement, Priority::Default) => handle_receive_element, + (Iq, Priority::Default) => handle_iq, + (PingEvent, Priority::Default) => reply_ping, ]);