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 error::Error;
|
||||
use ns;
|
||||
use plugin::{Plugin, PluginInit, PluginProxyBinding};
|
||||
use plugin::{Plugin, PluginInit, PluginProxyBinding, PluginContainer, PluginRef};
|
||||
use connection::{Connection, C2S};
|
||||
use sasl::client::Mechanism as SaslMechanism;
|
||||
use sasl::client::mechanisms::{Plain, Scram};
|
||||
|
@ -21,9 +21,7 @@ use xml::reader::XmlEvent as ReaderEvent;
|
|||
|
||||
use std::sync::{Mutex, Arc};
|
||||
|
||||
use std::collections::{HashSet, HashMap};
|
||||
|
||||
use std::any::TypeId;
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// Struct that should be moved somewhere else and cleaned up.
|
||||
#[derive(Debug)]
|
||||
|
@ -81,11 +79,12 @@ impl ClientBuilder {
|
|||
let mut credentials = self.credentials;
|
||||
credentials.channel_binding = transport.channel_bind();
|
||||
let transport = Arc::new(Mutex::new(transport));
|
||||
let plugin_container = Arc::new(PluginContainer::new());
|
||||
let mut client = Client {
|
||||
jid: self.jid,
|
||||
transport: transport.clone(),
|
||||
plugins: HashMap::new(),
|
||||
binding: PluginProxyBinding::new(dispatcher.clone()),
|
||||
binding: PluginProxyBinding::new(dispatcher.clone(), plugin_container.clone()),
|
||||
plugin_container: plugin_container,
|
||||
dispatcher: dispatcher,
|
||||
};
|
||||
client.dispatcher.register(Priority::Default, move |evt: &SendElement| {
|
||||
|
@ -103,7 +102,7 @@ impl ClientBuilder {
|
|||
pub struct Client {
|
||||
jid: Jid,
|
||||
transport: Arc<Mutex<SslTransport>>,
|
||||
plugins: HashMap<TypeId, Arc<Plugin>>,
|
||||
plugin_container: Arc<PluginContainer>,
|
||||
binding: PluginProxyBinding,
|
||||
dispatcher: Arc<Dispatcher>,
|
||||
}
|
||||
|
@ -118,11 +117,9 @@ impl Client {
|
|||
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(plugin) as Arc<Plugin>;
|
||||
let p = Arc::new(plugin);
|
||||
P::init(&self.dispatcher, p.clone());
|
||||
if self.plugins.insert(TypeId::of::<P>(), p).is_some() {
|
||||
panic!("registering a plugin that's already registered");
|
||||
}
|
||||
self.plugin_container.register(p);
|
||||
}
|
||||
|
||||
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.
|
||||
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 plugin<P: Plugin>(&self) -> PluginRef<P> {
|
||||
self.plugin_container.get::<P>().unwrap()
|
||||
}
|
||||
|
||||
/// Returns the next event and flush the send queue.
|
||||
|
|
|
@ -3,7 +3,7 @@ use jid::Jid;
|
|||
use transport::{Transport, PlainTransport};
|
||||
use error::Error;
|
||||
use ns;
|
||||
use plugin::{Plugin, PluginInit, PluginProxyBinding};
|
||||
use plugin::{Plugin, PluginInit, PluginProxyBinding, PluginContainer, PluginRef};
|
||||
use event::{Dispatcher, ReceiveElement, SendElement, Propagation, Priority, Event};
|
||||
use connection::{Connection, Component2S};
|
||||
use sha_1::{Sha1, Digest};
|
||||
|
@ -15,10 +15,6 @@ use xml::reader::XmlEvent as ReaderEvent;
|
|||
use std::fmt::Write;
|
||||
use std::sync::{Mutex, Arc};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
/// A builder for `Component`s.
|
||||
pub struct ComponentBuilder {
|
||||
jid: Jid,
|
||||
|
@ -63,11 +59,12 @@ impl ComponentBuilder {
|
|||
Component2S::init(&mut transport, &self.jid.domain, "stream_opening")?;
|
||||
let dispatcher = Arc::new(Dispatcher::new());
|
||||
let transport = Arc::new(Mutex::new(transport));
|
||||
let plugin_container = Arc::new(PluginContainer::new());
|
||||
let mut component = Component {
|
||||
jid: self.jid,
|
||||
transport: transport.clone(),
|
||||
plugins: HashMap::new(),
|
||||
binding: PluginProxyBinding::new(dispatcher.clone()),
|
||||
binding: PluginProxyBinding::new(dispatcher.clone(), plugin_container.clone()),
|
||||
plugin_container: plugin_container,
|
||||
dispatcher: dispatcher,
|
||||
};
|
||||
component.dispatcher.register(Priority::Default, move |evt: &SendElement| {
|
||||
|
@ -84,7 +81,7 @@ impl ComponentBuilder {
|
|||
pub struct Component {
|
||||
jid: Jid,
|
||||
transport: Arc<Mutex<PlainTransport>>,
|
||||
plugins: HashMap<TypeId, Arc<Plugin>>,
|
||||
plugin_container: Arc<PluginContainer>,
|
||||
binding: PluginProxyBinding,
|
||||
dispatcher: Arc<Dispatcher>,
|
||||
}
|
||||
|
@ -99,20 +96,9 @@ impl Component {
|
|||
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(plugin) as Arc<Plugin>;
|
||||
let p = Arc::new(plugin);
|
||||
P::init(&self.dispatcher, 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 {
|
||||
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!!)")
|
||||
self.plugin_container.register(p);
|
||||
}
|
||||
|
||||
pub fn register_handler<E, F>(&mut self, pri: Priority, func: F)
|
||||
|
@ -122,6 +108,11 @@ impl Component {
|
|||
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.
|
||||
pub fn main(&mut self) -> Result<(), Error> {
|
||||
self.dispatcher.flush_all();
|
||||
|
|
|
@ -2,23 +2,81 @@
|
|||
|
||||
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 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)]
|
||||
pub struct PluginProxyBinding {
|
||||
dispatcher: Arc<Dispatcher>,
|
||||
plugin_container: Arc<PluginContainer>,
|
||||
}
|
||||
|
||||
impl PluginProxyBinding {
|
||||
pub fn new(dispatcher: Arc<Dispatcher>) -> PluginProxyBinding {
|
||||
pub fn new(dispatcher: Arc<Dispatcher>, plugin_container: Arc<PluginContainer>) -> PluginProxyBinding {
|
||||
PluginProxyBinding {
|
||||
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.
|
||||
pub fn send(&self, elem: Element) {
|
||||
self.dispatch(SendElement(elem));
|
||||
|
|
Loading…
Reference in a new issue