use std::sync::{Arc, RwLock};
use log::*;
use crate::init::CONFIG;
use crate::message::stomp_message::{Header, StompMessage};
use crate::session::stomp_session::StompSession;
pub fn get_request_header(message: &StompMessage) -> Option<&Header> {
for hdr in message.headers() {
if hdr.name.eq("heart-beat") {
return Some(hdr);
}
}
None
}
pub fn get_response_header(session: &Arc<RwLock<StompSession>>) -> Header {
let session = session.read().unwrap();
Header {
name: String::from("heart-beat"),
value: format!("{},{}", session.heart_beat_write, session.heart_beat_read)
}
}
pub fn parse_header(hdr: &Header, session: &Arc<RwLock<StompSession>>) -> Result<(), &'static str> {
let comma_idx = (*hdr.value).find(',');
match comma_idx {
Some(comma_idx) => {
let (cx, cy) = (*hdr.value).split_at(comma_idx);
if cy.len() < 2 {
return Err("ecg syntax");
}
match (cx.parse::<u32>(), cy[1..].parse::<u32>()) {
(Ok(cx), Ok(cy)) => {
let mut s = session.write().unwrap();
if cx == 0 {
s.heart_beat_read = 0;
} else if cx > CONFIG.heart_beat_read {
debug!("ecg incompat");
return Err("ecg incompat");
} else {
s.heart_beat_read = CONFIG.heart_beat_read;
}
if cy == 0 || CONFIG.heart_beat_write_max == 0 {
s.heart_beat_write = 0;
} else if cy < CONFIG.heart_beat_write_min {
debug!("ecg incompat");
return Err("ecg incompat");
} else if cy > CONFIG.heart_beat_write_max {
s.heart_beat_write = CONFIG.heart_beat_write_max;
} else {
s.heart_beat_write = cy;
}
return Ok(());
},
_ => return Err("ecg syntax"),
}
},
_ => {
return Err("ecg syntax");
},
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_header() {
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", "60000,60000");
match parse_header(&hdr, &session) {
Ok(()) => {},
Err(e) => panic!("parse failed '{}'", e),
}
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", "60000,");
match parse_header(&hdr, &session) {
Ok(()) => panic!("expected parse fail"),
Err(_e) => {},
}
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", ",60000");
match parse_header(&hdr, &session) {
Ok(()) => panic!("expected parse fail"),
Err(_e) => {},
}
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", "60000,600000");
match parse_header(&hdr, &session) {
Ok(()) => {
let session = session.read().unwrap();
assert_eq!(session.heart_beat_read, 120000); assert_eq!(session.heart_beat_write, CONFIG.heart_beat_write_max);
},
Err(_e) => {},
}
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", "60000,6000");
match parse_header(&hdr, &session) {
Ok(()) => {
let session = session.read().unwrap();
assert_eq!(session.heart_beat_read, 120000);
assert_eq!(session.heart_beat_write, CONFIG.heart_beat_write_min);
},
Err(_e) => {},
}
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", "0,0");
match parse_header(&hdr, &session) {
Ok(()) => {
let session = session.read().unwrap();
assert_eq!(session.heart_beat_read, 0);
assert_eq!(session.heart_beat_write, 0);
},
Err(_e) => {},
}
}
#[test]
fn test_parse_header_read_range() {
let session = Arc::new(RwLock::new(StompSession::new()));
let hdr = Header::new("heart-beat", "120001,60000");
match parse_header(&hdr, &session) {
Ok(()) => panic!("expect read out of range"),
Err(_e) => {},
}
}
}