mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
add an ibb plugin
This commit is contained in:
parent
64c8027936
commit
1378ca3724
3 changed files with 178 additions and 0 deletions
|
@ -6,6 +6,7 @@ use xmpp::plugins::stanza::StanzaPlugin;
|
|||
use xmpp::plugins::unhandled_iq::UnhandledIqPlugin;
|
||||
use xmpp::plugins::messaging::{MessagingPlugin, MessageEvent};
|
||||
use xmpp::plugins::presence::{PresencePlugin, Type};
|
||||
use xmpp::plugins::ibb::IbbPlugin;
|
||||
use xmpp::plugins::ping::{PingPlugin, PingEvent};
|
||||
use xmpp::event::{Priority, Propagation};
|
||||
|
||||
|
@ -22,6 +23,7 @@ fn main() {
|
|||
client.register_plugin(UnhandledIqPlugin::new());
|
||||
client.register_plugin(MessagingPlugin::new());
|
||||
client.register_plugin(PresencePlugin::new());
|
||||
client.register_plugin(IbbPlugin::new());
|
||||
client.register_plugin(PingPlugin::new());
|
||||
client.register_handler(Priority::Max, |e: &MessageEvent| {
|
||||
println!("{:?}", e);
|
||||
|
|
175
src/plugins/ibb.rs
Normal file
175
src/plugins/ibb.rs
Normal file
|
@ -0,0 +1,175 @@
|
|||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::{Mutex, Arc};
|
||||
|
||||
use plugin::PluginProxy;
|
||||
use event::{Event, Priority, Propagation};
|
||||
use jid::Jid;
|
||||
|
||||
use plugins::stanza::Iq;
|
||||
use xmpp_parsers::iq::{IqType, IqPayload};
|
||||
use xmpp_parsers::ibb::{IBB, Stanza};
|
||||
use xmpp_parsers::stanza_error::{StanzaError, ErrorType, DefinedCondition};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Session {
|
||||
stanza: Stanza,
|
||||
block_size: u16,
|
||||
cur_seq: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IbbOpen {
|
||||
pub session: Session,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IbbData {
|
||||
pub session: Session,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IbbClose {
|
||||
pub session: Session,
|
||||
}
|
||||
|
||||
impl Event for IbbOpen {}
|
||||
impl Event for IbbData {}
|
||||
impl Event for IbbClose {}
|
||||
|
||||
fn generate_error(type_: ErrorType, defined_condition: DefinedCondition, text: &str) -> StanzaError {
|
||||
StanzaError {
|
||||
type_: type_,
|
||||
defined_condition: defined_condition,
|
||||
texts: {
|
||||
let mut texts = BTreeMap::new();
|
||||
texts.insert(String::new(), String::from(text));
|
||||
texts
|
||||
},
|
||||
by: None,
|
||||
other: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IbbPlugin {
|
||||
proxy: PluginProxy,
|
||||
sessions: Arc<Mutex<HashMap<(Jid, String), Session>>>,
|
||||
}
|
||||
|
||||
impl IbbPlugin {
|
||||
pub fn new() -> IbbPlugin {
|
||||
IbbPlugin {
|
||||
proxy: PluginProxy::new(),
|
||||
sessions: Arc::new(Mutex::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ibb(&self, from: Jid, ibb: IBB) -> Result<(), StanzaError> {
|
||||
let mut sessions = self.sessions.lock().unwrap();
|
||||
match ibb {
|
||||
IBB::Open { block_size, sid, stanza } => {
|
||||
match sessions.entry((from.clone(), sid.clone())) {
|
||||
Entry::Vacant(_) => Ok(()),
|
||||
Entry::Occupied(_) => Err(generate_error(
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::NotAcceptable,
|
||||
"This session is already open."
|
||||
)),
|
||||
}?;
|
||||
let session = Session {
|
||||
stanza,
|
||||
block_size,
|
||||
cur_seq: 65535u16,
|
||||
};
|
||||
sessions.insert((from, sid), session.clone());
|
||||
self.proxy.dispatch(IbbOpen {
|
||||
session: session,
|
||||
});
|
||||
},
|
||||
IBB::Data { seq, sid, data } => {
|
||||
let entry = match sessions.entry((from, sid)) {
|
||||
Entry::Occupied(entry) => Ok(entry),
|
||||
Entry::Vacant(_) => Err(generate_error(
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::ItemNotFound,
|
||||
"This session doesn’t exist."
|
||||
)),
|
||||
}?;
|
||||
let mut session = entry.into_mut();
|
||||
if session.stanza != Stanza::Iq {
|
||||
return Err(generate_error(
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::NotAcceptable,
|
||||
"Wrong stanza type."
|
||||
))
|
||||
}
|
||||
let cur_seq = session.cur_seq.wrapping_add(1);
|
||||
if seq != cur_seq {
|
||||
return Err(generate_error(
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::NotAcceptable,
|
||||
"Wrong seq number."
|
||||
))
|
||||
}
|
||||
session.cur_seq = cur_seq;
|
||||
self.proxy.dispatch(IbbData {
|
||||
session: session.clone(),
|
||||
data,
|
||||
});
|
||||
},
|
||||
IBB::Close { sid } => {
|
||||
let entry = match sessions.entry((from, sid)) {
|
||||
Entry::Occupied(entry) => Ok(entry),
|
||||
Entry::Vacant(_) => Err(generate_error(
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::ItemNotFound,
|
||||
"This session doesn’t exist."
|
||||
)),
|
||||
}?;
|
||||
let session = entry.remove();
|
||||
self.proxy.dispatch(IbbClose {
|
||||
session,
|
||||
});
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_iq(&self, iq: &Iq) -> Propagation {
|
||||
let iq = iq.clone();
|
||||
if let IqType::Set(payload) = iq.payload {
|
||||
let from = iq.from.unwrap();
|
||||
let id = iq.id.unwrap();
|
||||
// TODO: use an intermediate plugin to parse this payload.
|
||||
let payload = match IqPayload::try_from(payload) {
|
||||
Ok(IqPayload::IBB(ibb)) => {
|
||||
match self.handle_ibb(from.clone(), ibb) {
|
||||
Ok(_) => IqType::Result(None),
|
||||
Err(error) => IqType::Error(error),
|
||||
}
|
||||
},
|
||||
Err(err) => IqType::Error(generate_error(
|
||||
ErrorType::Cancel,
|
||||
DefinedCondition::NotAcceptable,
|
||||
format!("{:?}", err).as_ref()
|
||||
)),
|
||||
Ok(_) => return Propagation::Continue,
|
||||
};
|
||||
self.proxy.send(Iq {
|
||||
from: None,
|
||||
to: Some(from),
|
||||
id: Some(id),
|
||||
payload: payload,
|
||||
}.into());
|
||||
Propagation::Stop
|
||||
} else {
|
||||
Propagation::Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_plugin!(IbbPlugin, proxy, [
|
||||
(Iq, Priority::Default) => handle_iq,
|
||||
]);
|
|
@ -1,6 +1,7 @@
|
|||
pub mod messaging;
|
||||
pub mod presence;
|
||||
pub mod ping;
|
||||
pub mod ibb;
|
||||
pub mod stanza;
|
||||
pub mod stanza_debug;
|
||||
pub mod unhandled_iq;
|
||||
|
|
Loading…
Reference in a new issue