use std::sync::{Arc, RwLock};
use log::*;
use crate::message::response::get_response_error;
use crate::message::stomp_message::StompMessage;
use crate::session::stomp_session::StompSession;
use crate::workflow::context::Context;
use crate::workflow::filter::connect::ConnectFilter;
use crate::workflow::filter::disconnect::DisconnectFilter;
use crate::workflow::filter::{MessageFilter, FilterError};
use crate::workflow::filter::ack::AckFilter;
use crate::workflow::filter::log::LogFilter;
use crate::workflow::filter::receipt::ReceiptFilter;
use crate::workflow::filter::requires_auth::RequiresAuthFilter;
use crate::workflow::filter::subscribe::SubscribeFilter;
use crate::workflow::filter::send::SendFilter;
use crate::workflow::filter::admin::AdminFilter;
use crate::workflow::filter::closure::ClosureFilter;
use crate::workflow::filter::http::HttpFilter;
use crate::workflow;
lazy_static! {
pub static ref FILTER_CHAIN_STATIC: FilterChain = FilterChain {
chain: build_filter_chain()
};
}
static mut CHAIN: Vec<(Box<dyn MessageFilter + Sync>, usize)> = Vec::new();
static mut INITIALIZED: bool = false;
static DEFAULT_INSERT_POINT: usize = 6;
pub static PRE_SEND_INSERT_POINT: usize = 5;
pub fn insert_stomp_filter(filter: Box<dyn MessageFilter + Sync>) {
unsafe {
if INITIALIZED {
panic!("Cannot insert filters after the server is initialized");
}
CHAIN.push((filter, DEFAULT_INSERT_POINT));
}
}
pub fn insert_stomp_filter_at(filter: Box<dyn MessageFilter + Sync>, at: usize) {
unsafe {
if INITIALIZED {
panic!("Cannot insert filters after the server is initialized");
}
CHAIN.push((filter, at));
}
}
pub fn insert_stomp(closure: fn(&mut Context, message: &mut StompMessage) -> Result<bool, FilterError>) {
unsafe {
if INITIALIZED {
panic!("Cannot insert filters after the server is initialized");
}
insert_stomp_filter(Box::new(ClosureFilter::new(closure)));
}
}
pub struct FilterChain {
chain: Vec<Box<dyn MessageFilter + Sync>>,
}
pub fn build_filter_chain() -> Vec<Box<dyn MessageFilter + Sync>> {
let mut route: Vec<Box<dyn MessageFilter + Sync>> = vec![
Box::new(LogFilter::new()),
Box::new(RequiresAuthFilter::new()),
Box::new(ConnectFilter::new()),
Box::new(SubscribeFilter::new()),
Box::new(AckFilter::new()),
Box::new(SendFilter::new()), Box::new(HttpFilter::new()), Box::new(AdminFilter::new()),
Box::new(ReceiptFilter::new()),
Box::new(DisconnectFilter::new()),
];
unsafe {
while CHAIN.len() > 0 {
let filter = CHAIN.remove(CHAIN.len() - 1);
route.insert(filter.1,filter.0);
}
INITIALIZED = true;
}
for filter in route.iter_mut() {
filter.init();
info!("{:?}.init()", filter);
}
debug!("STOMP init finished");
route
}
pub fn route(mut message: StompMessage, session: Arc<RwLock<StompSession>>, web_socket: bool) {
let mut ctx: Context = Context::new(session.clone());
ctx.is_web_sockets = web_socket;
let mut fatal = false;
let mut abort_message = None;
for f in &FILTER_CHAIN_STATIC.chain {
match f.do_filter(&mut ctx, &mut message) {
Ok(workflow::CONTINUE) => {
},
Ok(workflow::HANDLED) => {
break;
},
Err(fe) => {
if let Some(log_message) = fe.log_message {
warn!("{}", log_message);
}
abort_message = fe.reply_message;
fatal |= fe.fatal;
break;
}
}
}
if let Some(abort_message) = abort_message {
session.read().unwrap().send_message(get_response_error(abort_message.as_str()));
}
if fatal {
session.write().unwrap().shutdown();
}
}