mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
abstract plugin logic into PluginContainer
This commit is contained in:
parent
1b6b67b332
commit
6efc77b423
3 changed files with 90 additions and 41 deletions
|
@ -3,7 +3,7 @@ use jid::Jid;
|
||||||
use transport::{Transport, SslTransport};
|
use transport::{Transport, SslTransport};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use ns;
|
use ns;
|
||||||
use plugin::{Plugin, PluginInit, PluginProxyBinding};
|
use plugin::{Plugin, PluginInit, PluginProxyBinding, PluginContainer, PluginRef};
|
||||||
use connection::{Connection, C2S};
|
use connection::{Connection, C2S};
|
||||||
use sasl::client::Mechanism as SaslMechanism;
|
use sasl::client::Mechanism as SaslMechanism;
|
||||||
use sasl::client::mechanisms::{Plain, Scram};
|
use sasl::client::mechanisms::{Plain, Scram};
|
||||||
|
@ -21,9 +21,7 @@ use xml::reader::XmlEvent as ReaderEvent;
|
||||||
|
|
||||||
use std::sync::{Mutex, Arc};
|
use std::sync::{Mutex, Arc};
|
||||||
|
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use std::any::TypeId;
|
|
||||||
|
|
||||||
/// Struct that should be moved somewhere else and cleaned up.
|
/// Struct that should be moved somewhere else and cleaned up.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -81,11 +79,12 @@ impl ClientBuilder {
|
||||||
let mut credentials = self.credentials;
|
let mut credentials = self.credentials;
|
||||||
credentials.channel_binding = transport.channel_bind();
|
credentials.channel_binding = transport.channel_bind();
|
||||||
let transport = Arc::new(Mutex::new(transport));
|
let transport = Arc::new(Mutex::new(transport));
|
||||||
|
let plugin_container = Arc::new(PluginContainer::new());
|
||||||
let mut client = Client {
|
let mut client = Client {
|
||||||
jid: self.jid,
|
jid: self.jid,
|
||||||
transport: transport.clone(),
|
transport: transport.clone(),
|
||||||
plugins: HashMap::new(),
|
binding: PluginProxyBinding::new(dispatcher.clone(), plugin_container.clone()),
|
||||||
binding: PluginProxyBinding::new(dispatcher.clone()),
|
plugin_container: plugin_container,
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
};
|
};
|
||||||
client.dispatcher.register(Priority::Default, move |evt: &SendElement| {
|
client.dispatcher.register(Priority::Default, move |evt: &SendElement| {
|
||||||
|
@ -103,7 +102,7 @@ impl ClientBuilder {
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
jid: Jid,
|
jid: Jid,
|
||||||
transport: Arc<Mutex<SslTransport>>,
|
transport: Arc<Mutex<SslTransport>>,
|
||||||
plugins: HashMap<TypeId, Arc<Plugin>>,
|
plugin_container: Arc<PluginContainer>,
|
||||||
binding: PluginProxyBinding,
|
binding: PluginProxyBinding,
|
||||||
dispatcher: Arc<Dispatcher>,
|
dispatcher: Arc<Dispatcher>,
|
||||||
}
|
}
|
||||||
|
@ -118,11 +117,9 @@ impl Client {
|
||||||
pub fn register_plugin<P: Plugin + PluginInit + 'static>(&mut self, mut plugin: P) {
|
pub fn register_plugin<P: Plugin + PluginInit + 'static>(&mut self, mut plugin: P) {
|
||||||
let binding = self.binding.clone();
|
let binding = self.binding.clone();
|
||||||
plugin.bind(binding);
|
plugin.bind(binding);
|
||||||
let p = Arc::new(plugin) as Arc<Plugin>;
|
let p = Arc::new(plugin);
|
||||||
P::init(&self.dispatcher, p.clone());
|
P::init(&self.dispatcher, p.clone());
|
||||||
if self.plugins.insert(TypeId::of::<P>(), p).is_some() {
|
self.plugin_container.register(p);
|
||||||
panic!("registering a plugin that's already registered");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_handler<E, F>(&mut self, pri: Priority, func: F)
|
pub fn register_handler<E, F>(&mut self, pri: Priority, func: F)
|
||||||
|
@ -133,12 +130,8 @@ impl Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the plugin given by the type parameter, if it exists, else panics.
|
/// Returns the plugin given by the type parameter, if it exists, else panics.
|
||||||
pub fn plugin<P: Plugin>(&self) -> &P {
|
pub fn plugin<P: Plugin>(&self) -> PluginRef<P> {
|
||||||
self.plugins.get(&TypeId::of::<P>())
|
self.plugin_container.get::<P>().unwrap()
|
||||||
.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.
|
/// Returns the next event and flush the send queue.
|
||||||
|
|
|
@ -3,7 +3,7 @@ use jid::Jid;
|
||||||
use transport::{Transport, PlainTransport};
|
use transport::{Transport, PlainTransport};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use ns;
|
use ns;
|
||||||
use plugin::{Plugin, PluginInit, PluginProxyBinding};
|
use plugin::{Plugin, PluginInit, PluginProxyBinding, PluginContainer, PluginRef};
|
||||||
use event::{Dispatcher, ReceiveElement, SendElement, Propagation, Priority, Event};
|
use event::{Dispatcher, ReceiveElement, SendElement, Propagation, Priority, Event};
|
||||||
use connection::{Connection, Component2S};
|
use connection::{Connection, Component2S};
|
||||||
use sha_1::{Sha1, Digest};
|
use sha_1::{Sha1, Digest};
|
||||||
|
@ -15,10 +15,6 @@ use xml::reader::XmlEvent as ReaderEvent;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::sync::{Mutex, Arc};
|
use std::sync::{Mutex, Arc};
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use std::any::TypeId;
|
|
||||||
|
|
||||||
/// A builder for `Component`s.
|
/// A builder for `Component`s.
|
||||||
pub struct ComponentBuilder {
|
pub struct ComponentBuilder {
|
||||||
jid: Jid,
|
jid: Jid,
|
||||||
|
@ -63,11 +59,12 @@ impl ComponentBuilder {
|
||||||
Component2S::init(&mut transport, &self.jid.domain, "stream_opening")?;
|
Component2S::init(&mut transport, &self.jid.domain, "stream_opening")?;
|
||||||
let dispatcher = Arc::new(Dispatcher::new());
|
let dispatcher = Arc::new(Dispatcher::new());
|
||||||
let transport = Arc::new(Mutex::new(transport));
|
let transport = Arc::new(Mutex::new(transport));
|
||||||
|
let plugin_container = Arc::new(PluginContainer::new());
|
||||||
let mut component = Component {
|
let mut component = Component {
|
||||||
jid: self.jid,
|
jid: self.jid,
|
||||||
transport: transport.clone(),
|
transport: transport.clone(),
|
||||||
plugins: HashMap::new(),
|
binding: PluginProxyBinding::new(dispatcher.clone(), plugin_container.clone()),
|
||||||
binding: PluginProxyBinding::new(dispatcher.clone()),
|
plugin_container: plugin_container,
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
};
|
};
|
||||||
component.dispatcher.register(Priority::Default, move |evt: &SendElement| {
|
component.dispatcher.register(Priority::Default, move |evt: &SendElement| {
|
||||||
|
@ -84,7 +81,7 @@ impl ComponentBuilder {
|
||||||
pub struct Component {
|
pub struct Component {
|
||||||
jid: Jid,
|
jid: Jid,
|
||||||
transport: Arc<Mutex<PlainTransport>>,
|
transport: Arc<Mutex<PlainTransport>>,
|
||||||
plugins: HashMap<TypeId, Arc<Plugin>>,
|
plugin_container: Arc<PluginContainer>,
|
||||||
binding: PluginProxyBinding,
|
binding: PluginProxyBinding,
|
||||||
dispatcher: Arc<Dispatcher>,
|
dispatcher: Arc<Dispatcher>,
|
||||||
}
|
}
|
||||||
|
@ -99,20 +96,9 @@ impl Component {
|
||||||
pub fn register_plugin<P: Plugin + PluginInit + 'static>(&mut self, mut plugin: P) {
|
pub fn register_plugin<P: Plugin + PluginInit + 'static>(&mut self, mut plugin: P) {
|
||||||
let binding = self.binding.clone();
|
let binding = self.binding.clone();
|
||||||
plugin.bind(binding);
|
plugin.bind(binding);
|
||||||
let p = Arc::new(plugin) as Arc<Plugin>;
|
let p = Arc::new(plugin);
|
||||||
P::init(&self.dispatcher, p.clone());
|
P::init(&self.dispatcher, p.clone());
|
||||||
if self.plugins.insert(TypeId::of::<P>(), p).is_some() {
|
self.plugin_container.register(p);
|
||||||
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 {
|
|
||||||
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!!)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_handler<E, F>(&mut self, pri: Priority, func: F)
|
pub fn register_handler<E, F>(&mut self, pri: Priority, func: F)
|
||||||
|
@ -122,6 +108,11 @@ impl Component {
|
||||||
self.dispatcher.register(pri, func);
|
self.dispatcher.register(pri, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the plugin given by the type parameter, if it exists, else panics.
|
||||||
|
pub fn plugin<P: Plugin>(&self) -> PluginRef<P> {
|
||||||
|
self.plugin_container.get::<P>().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the next event and flush the send queue.
|
/// Returns the next event and flush the send queue.
|
||||||
pub fn main(&mut self) -> Result<(), Error> {
|
pub fn main(&mut self) -> Result<(), Error> {
|
||||||
self.dispatcher.flush_all();
|
self.dispatcher.flush_all();
|
||||||
|
|
|
@ -2,23 +2,81 @@
|
||||||
|
|
||||||
use event::{Event, Dispatcher, SendElement, Priority, Propagation};
|
use event::{Event, Dispatcher, SendElement, Priority, Propagation};
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::{Any, TypeId};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use std::sync::{RwLock, Arc};
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use std::convert::AsRef;
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use minidom::Element;
|
use minidom::Element;
|
||||||
|
|
||||||
|
pub struct PluginContainer {
|
||||||
|
plugins: RwLock<HashMap<TypeId, Arc<Plugin>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginContainer {
|
||||||
|
pub fn new() -> PluginContainer {
|
||||||
|
PluginContainer {
|
||||||
|
plugins: RwLock::new(HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register<P: Plugin + 'static>(&self, plugin: Arc<P>) {
|
||||||
|
let mut guard = self.plugins.write().unwrap();
|
||||||
|
if guard.insert(TypeId::of::<P>(), plugin as Arc<Plugin>).is_some() {
|
||||||
|
panic!("registering a plugin that's already registered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<P: Plugin>(&self) -> Option<PluginRef<P>> {
|
||||||
|
let guard = self.plugins.read().unwrap();
|
||||||
|
let arc = guard.get(&TypeId::of::<P>());
|
||||||
|
arc.map(|arc| PluginRef {
|
||||||
|
inner: arc.clone(),
|
||||||
|
_marker: PhantomData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PluginRef<P: Plugin> {
|
||||||
|
inner: Arc<Plugin>,
|
||||||
|
_marker: PhantomData<P>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Plugin> Deref for PluginRef<P> {
|
||||||
|
type Target = P;
|
||||||
|
|
||||||
|
fn deref(&self) -> &P {
|
||||||
|
self.inner.as_any().downcast_ref::<P>().expect("plugin downcast failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Plugin> AsRef<P> for PluginRef<P> {
|
||||||
|
fn as_ref(&self) -> &P {
|
||||||
|
self.inner.as_any().downcast_ref::<P>().expect("plugin downcast failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct PluginProxyBinding {
|
pub struct PluginProxyBinding {
|
||||||
dispatcher: Arc<Dispatcher>,
|
dispatcher: Arc<Dispatcher>,
|
||||||
|
plugin_container: Arc<PluginContainer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginProxyBinding {
|
impl PluginProxyBinding {
|
||||||
pub fn new(dispatcher: Arc<Dispatcher>) -> PluginProxyBinding {
|
pub fn new(dispatcher: Arc<Dispatcher>, plugin_container: Arc<PluginContainer>) -> PluginProxyBinding {
|
||||||
PluginProxyBinding {
|
PluginProxyBinding {
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
|
plugin_container: plugin_container,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +130,13 @@ impl PluginProxy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tries to get another plugin.
|
||||||
|
pub fn plugin<P: Plugin>(&self) -> Option<PluginRef<P>> {
|
||||||
|
self.with_binding(|binding| {
|
||||||
|
binding.plugin_container.get::<P>()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Sends a stanza.
|
/// Sends a stanza.
|
||||||
pub fn send(&self, elem: Element) {
|
pub fn send(&self, elem: Element) {
|
||||||
self.dispatch(SendElement(elem));
|
self.dispatch(SendElement(elem));
|
||||||
|
|
Loading…
Reference in a new issue