.gitlab-ci.yml π
@@ -1,4 +1,4 @@
-image: "scorpil/rust:stable"
+image: "scorpil/rust:nightly"
before_script:
- apt-get update -yqq
lumi created
.gitlab-ci.yml | 2
examples/client.rs | 5
src/client.rs | 122 ++++++++++-------
src/event.rs | 292 +++++++++++++++++++++++++++++++++++------
src/lib.rs | 5
src/plugin.rs | 42 ++---
src/plugin_macro.rs | 26 +++
src/plugins/messaging.rs | 17 +-
src/plugins/ping.rs | 17 +-
src/plugins/presence.rs | 12 -
src/plugins/stanza.rs | 19 +-
11 files changed, 403 insertions(+), 156 deletions(-)
@@ -1,4 +1,4 @@
-image: "scorpil/rust:stable"
+image: "scorpil/rust:nightly"
before_script:
- apt-get update -yqq
@@ -19,7 +19,8 @@ fn main() {
client.register_plugin(PresencePlugin::new());
client.register_plugin(PingPlugin::new());
client.plugin::<PresencePlugin>().set_presence(Show::Available, None).unwrap();
- loop {
+ client.main().unwrap();
+ /*loop {
let event = client.next_event().unwrap();
if let Some(evt) = event.downcast::<MessageEvent>() {
println!("{:?}", evt);
@@ -28,5 +29,5 @@ fn main() {
println!("{:?}", evt);
client.plugin::<PingPlugin>().reply_ping(evt);
}
- }
+ }*/
}
@@ -1,9 +1,9 @@
+use xml;
use jid::Jid;
use transport::{Transport, SslTransport};
use error::Error;
use ns;
-use plugin::{Plugin, PluginProxyBinding};
-use event::AbstractEvent;
+use plugin::{Plugin, PluginInit, PluginProxyBinding};
use connection::{Connection, C2S};
use sasl::client::Mechanism as SaslMechanism;
use sasl::client::mechanisms::{Plain, Scram};
@@ -11,6 +11,7 @@ use sasl::common::{Credentials as SaslCredentials, Identity, Secret, ChannelBind
use sasl::common::scram::{Sha1, Sha256};
use components::sasl_error::SaslError;
use util::FromElement;
+use event::{Dispatcher, Propagation, SendElement, ReceiveElement, Priority};
use base64;
@@ -18,9 +19,11 @@ use minidom::Element;
use xml::reader::XmlEvent as ReaderEvent;
-use std::sync::mpsc::{Receiver, channel};
+use std::sync::{Mutex, Arc};
-use std::collections::HashSet;
+use std::collections::{HashSet, HashMap};
+
+use std::any::TypeId;
/// Struct that should be moved somewhere else and cleaned up.
#[derive(Debug)]
@@ -74,18 +77,22 @@ impl ClientBuilder {
let host = &self.host.unwrap_or(self.jid.domain.clone());
let mut transport = SslTransport::connect(host, self.port)?;
C2S::init(&mut transport, &self.jid.domain, "before_sasl")?;
- let (sender_out, sender_in) = channel();
- let (dispatcher_out, dispatcher_in) = channel();
+ let dispatcher = Arc::new(Mutex::new(Dispatcher::new()));
let mut credentials = self.credentials;
credentials.channel_binding = transport.channel_bind();
+ let transport = Arc::new(Mutex::new(transport));
let mut client = Client {
jid: self.jid,
- transport: transport,
- plugins: Vec::new(),
- binding: PluginProxyBinding::new(sender_out, dispatcher_out),
- sender_in: sender_in,
- dispatcher_in: dispatcher_in,
+ transport: transport.clone(),
+ plugins: HashMap::new(),
+ binding: PluginProxyBinding::new(dispatcher.clone()),
+ dispatcher: dispatcher,
};
+ client.dispatcher.lock().unwrap().register(Priority::Default, Box::new(move |evt: &SendElement| {
+ let mut t = transport.lock().unwrap();
+ t.write_element(&evt.0).unwrap();
+ Propagation::Continue
+ }));
client.connect(credentials)?;
client.bind()?;
Ok(client)
@@ -95,11 +102,10 @@ impl ClientBuilder {
/// An XMPP client.
pub struct Client {
jid: Jid,
- transport: SslTransport,
- plugins: Vec<Box<Plugin>>,
+ transport: Arc<Mutex<SslTransport>>,
+ plugins: HashMap<TypeId, Arc<Box<Plugin>>>,
binding: PluginProxyBinding,
- sender_in: Receiver<Element>,
- dispatcher_in: Receiver<AbstractEvent>,
+ dispatcher: Arc<Mutex<Dispatcher>>,
}
impl Client {
@@ -109,46 +115,55 @@ impl Client {
}
/// Registers a plugin.
- pub fn register_plugin<P: Plugin + 'static>(&mut self, mut plugin: P) {
- plugin.bind(self.binding.clone());
- self.plugins.push(Box::new(plugin));
+ pub fn register_plugin<P: Plugin + PluginInit + 'static>(&mut self, mut plugin: P) {
+ let binding = self.binding.clone();
+ plugin.bind(binding);
+ let p = Arc::new(Box::new(plugin) as Box<Plugin>);
+ {
+ let mut disp = self.dispatcher.lock().unwrap();
+ P::init(&mut disp, p.clone());
+ }
+ if self.plugins.insert(TypeId::of::<P>(), p).is_some() {
+ panic!("registering a plugin that's already registered");
+ }
}
/// Returns the plugin given by the type parameter, if it exists, else panics.
pub fn plugin<P: Plugin>(&self) -> &P {
- for plugin in &self.plugins {
- let any = plugin.as_any();
- if let Some(ret) = any.downcast_ref::<P>() {
- return ret;
- }
- }
- panic!("plugin does not exist!");
+ self.plugins.get(&TypeId::of::<P>())
+ .expect("the requested plugin was not registered")
+ .as_any()
+ .downcast_ref::<P>()
+ .expect("plugin downcast failure (should not happen!!)")
}
/// Returns the next event and flush the send queue.
- pub fn next_event(&mut self) -> Result<AbstractEvent, Error> {
- self.flush_send_queue()?;
+ pub fn main(&mut self) -> Result<(), Error> {
+ self.dispatcher.lock().unwrap().flush_all();
loop {
- if let Ok(evt) = self.dispatcher_in.try_recv() {
- return Ok(evt);
- }
- let elem = self.transport.read_element()?;
- for plugin in self.plugins.iter_mut() {
- plugin.handle(&elem);
- // TODO: handle plugin return
+ let elem = self.read_element()?;
+ {
+ let mut disp = self.dispatcher.lock().unwrap();
+ disp.dispatch(ReceiveElement(elem));
+ disp.flush_all();
}
- self.flush_send_queue()?;
}
}
- /// Flushes the send queue, sending all queued up stanzas.
- pub fn flush_send_queue(&mut self) -> Result<(), Error> { // TODO: not sure how great of an
- // idea it is to flush in this
- // mannerβ¦
- while let Ok(elem) = self.sender_in.try_recv() {
- self.transport.write_element(&elem)?;
- }
- Ok(())
+ fn reset_stream(&self) {
+ self.transport.lock().unwrap().reset_stream()
+ }
+
+ fn read_element(&self) -> Result<Element, Error> {
+ self.transport.lock().unwrap().read_element()
+ }
+
+ fn write_element(&self, elem: &Element) -> Result<(), Error> {
+ self.transport.lock().unwrap().write_element(elem)
+ }
+
+ fn read_event(&self) -> Result<xml::reader::XmlEvent, Error> {
+ self.transport.lock().unwrap().read_event()
}
fn connect(&mut self, mut credentials: SaslCredentials) -> Result<(), Error> {
@@ -188,9 +203,9 @@ impl Client {
if !auth.is_empty() {
elem.append_text_node(base64::encode(&auth));
}
- self.transport.write_element(&elem)?;
+ self.write_element(&elem)?;
loop {
- let n = self.transport.read_element()?;
+ let n = self.read_element()?;
if n.is("challenge", ns::SASL) {
let text = n.text();
let challenge = if text == "" {
@@ -206,7 +221,7 @@ impl Client {
if !response.is_empty() {
elem.append_text_node(base64::encode(&response));
}
- self.transport.write_element(&elem)?;
+ self.write_element(&elem)?;
}
else if n.is("success", ns::SASL) {
let text = n.text();
@@ -217,8 +232,11 @@ impl Client {
base64::decode(&text)?
};
mechanism.success(&data).map_err(|x| Error::SaslError(Some(x)))?;
- self.transport.reset_stream();
- C2S::init(&mut self.transport, &self.jid.domain, "after_sasl")?;
+ self.reset_stream();
+ {
+ let mut g = self.transport.lock().unwrap();
+ C2S::init(&mut *g, &self.jid.domain, "after_sasl")?;
+ }
self.wait_for_features()?;
return Ok(());
}
@@ -245,9 +263,9 @@ impl Client {
bind.append_child(res);
}
elem.append_child(bind);
- self.transport.write_element(&elem)?;
+ self.write_element(&elem)?;
loop {
- let n = self.transport.read_element()?;
+ let n = self.read_element()?;
if n.is("iq", ns::CLIENT) && n.has_child("bind", ns::BIND) {
return Ok(());
}
@@ -257,7 +275,7 @@ impl Client {
fn wait_for_features(&mut self) -> Result<StreamFeatures, Error> {
// TODO: this is very ugly
loop {
- let e = self.transport.read_event()?;
+ let e = self.read_event()?;
match e {
ReaderEvent::StartElement { .. } => {
break;
@@ -266,7 +284,7 @@ impl Client {
}
}
loop {
- let n = self.transport.read_element()?;
+ let n = self.read_element()?;
if n.is("features", ns::STREAM) {
let mut features = StreamFeatures {
sasl_mechanisms: None,
@@ -1,56 +1,262 @@
-//! Provides an abstract event type which can be downcasted into a more specific one.
-//!
-//! # Examples
-//!
-//! ```
-//! use xmpp::event::{Event, AbstractEvent};
-//!
-//! #[derive(Debug, PartialEq, Eq)]
-//! struct EventA;
-//!
-//! impl Event for EventA {}
-//!
-//! #[derive(Debug, PartialEq, Eq)]
-//! struct EventB;
-//!
-//! impl Event for EventB {}
-//!
-//! let event_a = AbstractEvent::new(EventA);
-//!
-//! assert_eq!(event_a.is::<EventA>(), true);
-//! assert_eq!(event_a.is::<EventB>(), false);
-//!
-//! assert_eq!(event_a.downcast::<EventA>(), Some(&EventA));
-//! assert_eq!(event_a.downcast::<EventB>(), None);
-//! ```
-
+use std::marker::PhantomData;
+use std::any::{TypeId, Any};
use std::fmt::Debug;
+use std::collections::BTreeMap;
+use std::cmp::Ordering;
+use std::sync::Arc;
+use std::mem;
+use std::ptr;
+use std::raw::TraitObject;
+
+use minidom::Element;
+
+/// A marker trait which marks all events.
+pub trait Event: Any + Debug {}
+
+/// A trait which can be implemented when something can handle a specific kind of event.
+pub trait EventHandler<E: Event>: Any {
+ /// Handle an event, returns whether to propagate the event to the remaining handlers.
+ fn handle(&self, event: &E) -> Propagation;
+}
+
+struct Record<P, T>(P, T);
+
+impl<P: PartialEq, T> PartialEq for Record<P, T> {
+ fn eq(&self, other: &Record<P, T>) -> bool {
+ self.0 == other.0
+ }
+}
+
+impl<P: Eq, T> Eq for Record<P, T> {}
+
+impl<P: PartialOrd, T> PartialOrd for Record<P, T> {
+ fn partial_cmp(&self, other: &Record<P, T>) -> Option<Ordering> {
+ self.0.partial_cmp(&other.0)
+ }
+}
+
+impl<P: Ord, T> Ord for Record<P, T> {
+ fn cmp(&self, other: &Record<P, T>) -> Ordering {
+ self.0.cmp(&other.0)
+ }
+}
-use std::any::Any;
+/// An enum representing whether to keep propagating an event or to stop the propagation.
+pub enum Propagation {
+ /// Stop the propagation of the event, the remaining handlers will not get invoked.
+ Stop,
+ /// Continue propagating the event.
+ Continue,
+}
+
+#[derive(Debug)]
+struct GarbageEvent;
+
+impl Event for GarbageEvent {}
-/// An abstract event.
-pub struct AbstractEvent {
- inner: Box<Any>,
+impl<E, F> EventHandler<E> for Box<F> where E: Event, F: 'static + Fn(&E) -> Propagation {
+ fn handle(&self, evt: &E) -> Propagation {
+ self(evt)
+ }
}
-impl AbstractEvent {
- /// Creates an abstract event from a concrete event.
- pub fn new<E: Event>(event: E) -> AbstractEvent {
- AbstractEvent {
- inner: Box::new(event),
+/// An event dispatcher, this takes care of dispatching events to their respective handlers.
+pub struct Dispatcher {
+ handlers: BTreeMap<TypeId, Vec<Record<Priority, Box<Any>>>>,
+ queue: Vec<(TypeId, Box<Any>)>,
+}
+
+impl Dispatcher {
+ /// Create a new `Dispatcher`.
+ pub fn new() -> Dispatcher {
+ Dispatcher {
+ handlers: BTreeMap::new(),
+ queue: Vec::new(),
}
}
- /// Downcasts this abstract event into a concrete event.
- pub fn downcast<E: Event + 'static>(&self) -> Option<&E> {
- self.inner.downcast_ref::<E>()
+ /// Register an event handler.
+ pub fn register<E, H>(&mut self, priority: Priority, handler: H) where E: Event + 'static, H: EventHandler<E> {
+ let handler: Box<EventHandler<E>> = Box::new(handler) as Box<EventHandler<E>>;
+ let ent = self.handlers.entry(TypeId::of::<E>())
+ .or_insert_with(|| Vec::new());
+ ent.push(Record(priority, Box::new(handler) as Box<Any>));
+ ent.sort();
+ }
+
+ /// Append an event to the queue.
+ pub fn dispatch<E>(&mut self, event: E) where E: Event {
+ self.queue.push((TypeId::of::<E>(), Box::new(event) as Box<Any>));
}
- /// Checks whether this abstract event is a specific concrete event.
- pub fn is<E: Event + 'static>(&self) -> bool {
- self.inner.is::<E>()
+ /// Flush all events in the queue so they can be handled by their respective handlers.
+ /// Returns whether there are still pending events.
+ pub fn flush(&mut self) -> bool {
+ let mut q = Vec::new();
+ mem::swap(&mut self.queue, &mut q);
+ 'evts: for (t, evt) in q {
+ if let Some(handlers) = self.handlers.get_mut(&t) {
+ for &mut Record(_, ref mut handler) in handlers {
+ // GarbageEvent is a garbage type.
+ // The actual passed type is NEVER of this type.
+ let h: &mut EventHandler<GarbageEvent> = unsafe {
+ let handler_obj: &mut TraitObject = mem::transmute(handler);
+ let handler_inner: *mut TraitObject = mem::transmute(handler_obj.data);
+ mem::transmute(*handler_inner)
+ };
+ let e: &&GarbageEvent = unsafe {
+ let evt_ref: &Any = &evt;
+ let evt_obj: TraitObject = mem::transmute(evt_ref);
+ mem::transmute(evt_obj.data)
+ };
+ match h.handle(e) {
+ Propagation::Stop => { continue 'evts; },
+ Propagation::Continue => (),
+ }
+ }
+ }
+ }
+ !self.queue.is_empty()
+ }
+
+ /// Flushes all events, like `flush`, but keeps doing this until there is nothing left in the
+ /// queue.
+ pub fn flush_all(&mut self) {
+ while self.flush() {}
+ }
+
+ /// Dispatch an event to the handlers right now, without going through the queue.
+ pub fn dispatch_now<E>(&mut self, event: E) where E: Event {
+ if let Some(handlers) = self.handlers.get_mut(&TypeId::of::<E>()) {
+ for &mut Record(_, ref mut handler) in handlers {
+ let h = handler.downcast_mut::<Box<EventHandler<E>>>().unwrap();
+ match h.handle(&event) {
+ Propagation::Stop => { return; },
+ Propagation::Continue => (),
+ }
+ }
+ }
}
}
-/// A marker trait which all events must implement.
-pub trait Event: Any + Debug {}
+pub struct EventProxy<T: ?Sized, E: Event> {
+ inner: Arc<Box<T>>,
+ vtable: *mut (),
+ _event_type: PhantomData<E>,
+}
+
+impl<T: ?Sized, E: Event> EventProxy<T, E> {
+ /// Unsafe because T is assumed to be a TraitObject or at least have its shape.
+ /// If it is not, things will break. In a fascinatingly horrible manner.
+ /// Some people, such as myself, find it hilarious. Most people do not.
+ /// T is also assumed to actually support EventHandler<E>, if it does not, refer to above
+ /// statement.
+ pub unsafe fn new<H: EventHandler<E>>(inner: Arc<Box<T>>) -> EventProxy<T, E> {
+ let box_with_vtable = &*ptr::null::<H>() as &EventHandler<E>;
+ let obj: TraitObject = mem::transmute(box_with_vtable);
+ EventProxy {
+ inner: inner,
+ vtable: obj.vtable,
+ _event_type: PhantomData,
+ }
+ }
+}
+
+impl<T: ?Sized, E: Event> EventHandler<E> for EventProxy<T, E> where Box<T>: 'static {
+ fn handle(&self, evt: &E) -> Propagation {
+ let inner = Arc::into_raw(self.inner.clone());
+ let obj = TraitObject { data: unsafe { mem::transmute(inner) }, vtable: self.vtable };
+ let handler: &EventHandler<E> = unsafe { mem::transmute(obj) };
+ let prop = handler.handle(evt);
+ unsafe { Arc::<Box<T>>::from_raw(mem::transmute(inner)); }
+ prop
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum Priority {
+ Max,
+ Default,
+ Min,
+}
+
+impl Default for Priority {
+ fn default() -> Priority {
+ Priority::Default
+ }
+}
+
+#[derive(Debug)]
+pub struct SendElement(pub Element);
+
+impl Event for SendElement {}
+
+#[derive(Debug)]
+pub struct ReceiveElement(pub Element);
+
+impl Event for ReceiveElement {}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ #[should_panic(expected = "success")]
+ fn test() {
+ let mut disp = Dispatcher::new();
+
+ struct MyHandler;
+ struct EvilHandler;
+ struct EventFilter;
+
+ #[derive(Debug)]
+ struct MyEvent {
+ should_be_42: u32,
+ }
+
+ impl Event for MyEvent {}
+
+ impl EventHandler<MyEvent> for MyHandler {
+ fn handle(&self, evt: &MyEvent) -> Propagation {
+ if evt.should_be_42 == 42 {
+ panic!("success");
+ }
+ else {
+ panic!("not 42");
+ }
+ }
+ }
+
+ impl EventHandler<MyEvent> for EvilHandler {
+ fn handle(&self, _: &MyEvent) -> Propagation {
+ panic!("should not be called");
+ }
+ }
+
+ impl EventHandler<MyEvent> for EventFilter {
+ fn handle(&self, evt: &MyEvent) -> Propagation {
+ if evt.should_be_42 == 42 {
+ Propagation::Continue
+ }
+ else {
+ Propagation::Stop
+ }
+ }
+ }
+
+ disp.register(Priority::Max, EventFilter);
+ disp.register(Priority::Min, EvilHandler);
+ disp.register(Priority::Default, MyHandler);
+ disp.register(Priority::Min, EvilHandler);
+
+ disp.dispatch(MyEvent {
+ should_be_42: 39,
+ });
+
+ disp.dispatch(MyEvent {
+ should_be_42: 42,
+ });
+
+ disp.flush();
+ }
+}
@@ -1,3 +1,5 @@
+#![feature(raw)]
+
extern crate xml;
extern crate openssl;
extern crate minidom;
@@ -10,8 +12,9 @@ pub mod ns;
pub mod transport;
pub mod error;
pub mod client;
-pub mod component;
+//pub mod component;
pub mod plugin;
+#[macro_use] pub mod plugin_macro;
pub mod event;
pub mod plugins;
pub mod connection;
@@ -1,10 +1,10 @@
//! Provides the plugin infrastructure.
-use event::{Event, AbstractEvent};
+use event::{Event, EventHandler, Dispatcher, SendElement, Priority};
use std::any::Any;
-use std::sync::mpsc::Sender;
+use std::sync::{Arc, Mutex};
use std::mem;
@@ -12,14 +12,12 @@ use minidom::Element;
#[derive(Clone)]
pub struct PluginProxyBinding {
- sender: Sender<Element>,
- dispatcher: Sender<AbstractEvent>,
+ dispatcher: Arc<Mutex<Dispatcher>>,
}
impl PluginProxyBinding {
- pub fn new(sender: Sender<Element>, dispatcher: Sender<AbstractEvent>) -> PluginProxyBinding {
+ pub fn new(dispatcher: Arc<Mutex<Dispatcher>>) -> PluginProxyBinding {
PluginProxyBinding {
- sender: sender,
dispatcher: dispatcher,
}
}
@@ -58,26 +56,23 @@ impl PluginProxy {
/// Dispatches an event.
pub fn dispatch<E: Event>(&self, event: E) {
self.with_binding(move |binding| {
- binding.dispatcher.send(AbstractEvent::new(event))
- .unwrap(); // TODO: may want to return the error
+ // TODO: proper error handling
+ binding.dispatcher.lock().unwrap().dispatch(event);
});
}
- /// Sends a stanza.
- pub fn send(&self, elem: Element) {
+ /// Registers an event handler.
+ pub fn register_handler<E, H>(&self, priority: Priority, handler: H) where E: Event, H: EventHandler<E> {
self.with_binding(move |binding| {
- binding.sender.send(elem).unwrap(); // TODO: as above, may want to return the error
+ // TODO: proper error handling
+ binding.dispatcher.lock().unwrap().register(priority, handler);
});
}
-}
-/// A plugin handler return value.
-///
-/// The `Continue` variant means to do nothing, the `Unload` variant means to unload the plugin.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum PluginReturn {
- Continue,
- Unload,
+ /// Sends a stanza.
+ pub fn send(&self, elem: Element) {
+ self.dispatch(SendElement(elem));
+ }
}
/// A trait whch all plugins should implement.
@@ -85,19 +80,20 @@ pub trait Plugin: Any + PluginAny {
/// Gets a mutable reference to the inner `PluginProxy`.
fn get_proxy(&mut self) -> &mut PluginProxy;
- /// Handles a received stanza.
- fn handle(&mut self, elem: &Element) -> PluginReturn;
-
#[doc(hidden)]
fn bind(&mut self, inner: PluginProxyBinding) {
self.get_proxy().bind(inner);
}
}
+pub trait PluginInit {
+ fn init(dispatcher: &mut Dispatcher, me: Arc<Box<Plugin>>);
+}
+
pub trait PluginAny {
fn as_any(&self) -> &Any;
}
-impl<T: Any + Sized> PluginAny for T {
+impl<T: Any + Sized + Plugin> PluginAny for T {
fn as_any(&self) -> &Any { self }
}
@@ -0,0 +1,26 @@
+#[macro_export]
+macro_rules! impl_plugin {
+ ($plugin:ty, $proxy:ident, [$($evt:ty => $pri:expr),*]) => {
+ impl $crate::plugin::Plugin for $plugin {
+ fn get_proxy(&mut self) -> &mut $crate::plugin::PluginProxy {
+ &mut self.$proxy
+ }
+ }
+
+ #[allow(unused_variables)]
+ impl $crate::plugin::PluginInit for $plugin {
+ fn init( dispatcher: &mut $crate::event::Dispatcher
+ , me: ::std::sync::Arc<Box<$crate::plugin::Plugin>>) {
+ $(
+ dispatcher.register($pri, unsafe {
+ $crate::event::EventProxy::new::<$plugin>(me.clone())
+ });
+ )*
+ }
+ }
+ };
+
+ ($plugin:ty, $proxy:ident, [$($evt:ty => $pri:expr),*,]) => {
+ impl_plugin!($plugin, $proxy, [$($evt => $pri),*]);
+ };
+}
@@ -1,5 +1,5 @@
-use plugin::{Plugin, PluginReturn, PluginProxy};
-use event::Event;
+use plugin::{PluginProxy};
+use event::{Event, EventHandler, ReceiveElement, Priority, Propagation};
use minidom::Element;
use error::Error;
use jid::Jid;
@@ -36,12 +36,13 @@ impl MessagingPlugin {
}
}
-impl Plugin for MessagingPlugin {
- fn get_proxy(&mut self) -> &mut PluginProxy {
- &mut self.proxy
- }
+impl_plugin!(MessagingPlugin, proxy, [
+ ReceiveElement => Priority::Default,
+]);
- fn handle(&mut self, elem: &Element) -> PluginReturn {
+impl EventHandler<ReceiveElement> for MessagingPlugin {
+ fn handle(&self, evt: &ReceiveElement) -> Propagation {
+ let elem = &evt.0;
if elem.is("message", ns::CLIENT) && elem.attr("type") == Some("chat") {
if let Some(body) = elem.get_child("body", ns::CLIENT) {
self.proxy.dispatch(MessageEvent { // TODO: safety!!!
@@ -51,6 +52,6 @@ impl Plugin for MessagingPlugin {
});
}
}
- PluginReturn::Continue
+ Propagation::Continue
}
}
@@ -1,5 +1,5 @@
-use plugin::{Plugin, PluginReturn, PluginProxy};
-use event::Event;
+use plugin::PluginProxy;
+use event::{Event, EventHandler, Priority, Propagation, ReceiveElement};
use minidom::Element;
use error::Error;
use jid::Jid;
@@ -45,12 +45,13 @@ impl PingPlugin {
}
}
-impl Plugin for PingPlugin {
- fn get_proxy(&mut self) -> &mut PluginProxy {
- &mut self.proxy
- }
+impl_plugin!(PingPlugin, proxy, [
+ ReceiveElement => Priority::Default,
+]);
- fn handle(&mut self, elem: &Element) -> PluginReturn {
+impl EventHandler<ReceiveElement> for PingPlugin {
+ fn handle(&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) {
self.proxy.dispatch(PingEvent { // TODO: safety!!!
@@ -60,6 +61,6 @@ impl Plugin for PingPlugin {
});
}
}
- PluginReturn::Continue
+ Propagation::Continue
}
}
@@ -1,5 +1,5 @@
use error::Error;
-use plugin::{Plugin, PluginProxy, PluginReturn};
+use plugin::PluginProxy;
use minidom::Element;
@@ -94,12 +94,4 @@ impl PresencePlugin {
}
}
-impl Plugin for PresencePlugin {
- fn get_proxy(&mut self) -> &mut PluginProxy {
- &mut self.proxy
- }
-
- fn handle(&mut self, _elem: &Element) -> PluginReturn {
- PluginReturn::Continue
- }
-}
+impl_plugin!(PresencePlugin, proxy, []);
@@ -1,8 +1,8 @@
use std::fmt::Debug;
use std::any::Any;
-use plugin::{Plugin, PluginReturn, PluginProxy};
-use event::Event;
+use plugin::PluginProxy;
+use event::{Event, EventHandler, ReceiveElement, Propagation, Priority};
use minidom::Element;
use jid::Jid;
use ns;
@@ -52,12 +52,14 @@ impl StanzaPlugin {
}
}
-impl Plugin for StanzaPlugin {
- fn get_proxy(&mut self) -> &mut PluginProxy {
- &mut self.proxy
- }
+impl_plugin!(StanzaPlugin, proxy, [
+ ReceiveElement => Priority::Default,
+]);
+
+impl EventHandler<ReceiveElement> for StanzaPlugin {
+ fn handle(&self, evt: &ReceiveElement) -> Propagation {
+ let elem = &evt.0;
- fn handle(&mut self, elem: &Element) -> PluginReturn {
let from = match elem.attr("from") { Some(from) => Some(from.parse().unwrap()), None => None };
let to = match elem.attr("to") { Some(to) => Some(to.parse().unwrap()), None => None };
let id = match elem.attr("id") { Some(id) => Some(id.parse().unwrap()), None => None };
@@ -89,6 +91,7 @@ impl Plugin for StanzaPlugin {
payloads: payloads,
});
}
- PluginReturn::Continue
+
+ Propagation::Continue
}
}