158 lines
5.0 KiB
Rust
158 lines
5.0 KiB
Rust
|
use super::{Message, Msg, MsgData, SessionMsg};
|
||
|
use std::{
|
||
|
collections::HashMap,
|
||
|
sync::mpsc::{channel, Receiver, Sender},
|
||
|
thread::spawn,
|
||
|
};
|
||
|
use uuid::Uuid;
|
||
|
|
||
|
#[derive(Clone)]
|
||
|
pub enum ClientMsg {
|
||
|
OpenSession(Option<String>, Sender<Message>),
|
||
|
}
|
||
|
|
||
|
impl Msg for ClientMsg {
|
||
|
fn to_msgdata(&self) -> MsgData {
|
||
|
MsgData::Client(self.clone())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct Client {
|
||
|
router_tx: Sender<Message>,
|
||
|
client_rx: Receiver<Message>,
|
||
|
requests: HashMap<Uuid, Sender<Message>>,
|
||
|
}
|
||
|
|
||
|
impl Client {
|
||
|
fn new(router_tx: Sender<Message>, client_rx: Receiver<Message>) -> Self {
|
||
|
Self {
|
||
|
router_tx: router_tx,
|
||
|
client_rx: client_rx,
|
||
|
requests: HashMap::new(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn start(router_tx: Sender<Message>) -> Sender<Message> {
|
||
|
let (client_tx, client_rx) = channel();
|
||
|
spawn(move || {
|
||
|
let mut client = Self::new(router_tx, client_rx);
|
||
|
client.listen();
|
||
|
});
|
||
|
client_tx
|
||
|
}
|
||
|
|
||
|
fn listen(&mut self) {
|
||
|
loop {
|
||
|
let msg = self.client_rx.recv().unwrap();
|
||
|
match self.requests.get(&msg.get_id()) {
|
||
|
Some(tx) => match msg.get_message() {
|
||
|
MsgData::Session(sess) => match sess {
|
||
|
SessionMsg::Opened(_) => tx.send(msg).unwrap(),
|
||
|
_ => {}
|
||
|
},
|
||
|
_ => {}
|
||
|
},
|
||
|
None => match msg.get_message() {
|
||
|
MsgData::Client(req) => match req {
|
||
|
ClientMsg::OpenSession(id, tx) => {
|
||
|
let sess = SessionMsg::Get(id.clone());
|
||
|
self.requests.insert(msg.get_id(), tx.clone());
|
||
|
self.router_tx.send(msg.reply(&sess)).unwrap();
|
||
|
}
|
||
|
},
|
||
|
_ => {}
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod messages {
|
||
|
use super::{super::SessionData, *};
|
||
|
use std::time::Duration;
|
||
|
use uuid::Uuid;
|
||
|
|
||
|
fn setup_client() -> (Sender<Message>, Receiver<Message>) {
|
||
|
let (tx, rx) = channel();
|
||
|
let client_tx = Client::start(tx);
|
||
|
(client_tx, rx)
|
||
|
}
|
||
|
|
||
|
fn opensession(id: &str) -> (Message, Receiver<Message>) {
|
||
|
let (tx, rx) = channel();
|
||
|
let sess = ClientMsg::OpenSession(Some(id.to_string()), tx);
|
||
|
let msg = Message::new(&sess);
|
||
|
(msg, rx)
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn open_session() {
|
||
|
let (tx, rx) = setup_client();
|
||
|
let sess_id = Uuid::new_v4().to_string();
|
||
|
let (sess_msg, _) = opensession(&sess_id);
|
||
|
tx.send(sess_msg.clone()).unwrap();
|
||
|
let result1 = rx.recv().unwrap();
|
||
|
assert_eq!(result1.get_id(), sess_msg.get_id());
|
||
|
match result1.get_message() {
|
||
|
MsgData::Session(req) => match req {
|
||
|
SessionMsg::Get(sess_data) => match sess_data {
|
||
|
Some(id) => assert_eq!(id.to_string(), sess_id),
|
||
|
_ => unreachable!("Should have returned some data."),
|
||
|
},
|
||
|
_ => unreachable!("Should have been a get session message."),
|
||
|
},
|
||
|
_ => unreachable!("Should have been a Session message."),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn respond_session() {
|
||
|
let (tx, _rx) = setup_client();
|
||
|
let (sess_msg, client_rx) = opensession(&Uuid::new_v4().to_string());
|
||
|
tx.send(sess_msg.clone()).unwrap();
|
||
|
let expected = Uuid::new_v4();
|
||
|
let right = SessionData::new(expected.clone());
|
||
|
let exp_msg = SessionMsg::Opened(right);
|
||
|
tx.send(sess_msg.reply(&exp_msg)).unwrap();
|
||
|
let result = client_rx.recv().unwrap();
|
||
|
assert_eq!(sess_msg.get_id(), result.get_id(), "Different message ids.");
|
||
|
match result.get_message() {
|
||
|
MsgData::Session(req) => match req {
|
||
|
SessionMsg::Opened(sess) => assert_eq!(
|
||
|
sess.to_string(),
|
||
|
expected.to_string(),
|
||
|
"Different sesssion ids."
|
||
|
),
|
||
|
_ => unreachable!("Should have been an opened session."),
|
||
|
},
|
||
|
_ => unreachable!("Should have been a session message."),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn does_not_react_if_not_requested() {
|
||
|
let (tx, rx) = setup_client();
|
||
|
let sess = SessionData::new(Uuid::new_v4());
|
||
|
let exp_msg = SessionMsg::Opened(sess);
|
||
|
tx.send(Message::new(&exp_msg)).unwrap();
|
||
|
match rx.recv_timeout(Duration::from_millis(500)) {
|
||
|
Err(_) => {}
|
||
|
_ => unreachable!("Should not receive anything."),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[test]
|
||
|
fn ignores_other_session_messages() {
|
||
|
let (tx, _rx) = setup_client();
|
||
|
let (sess_msg, client_rx) = opensession(&Uuid::new_v4().to_string());
|
||
|
tx.send(sess_msg.clone()).unwrap();
|
||
|
let req = SessionMsg::Get(None);
|
||
|
tx.send(sess_msg.reply(&req)).unwrap();
|
||
|
match client_rx.recv_timeout(Duration::from_millis(500)) {
|
||
|
Err(_) => {}
|
||
|
_ => unreachable!("Should not return anything."),
|
||
|
}
|
||
|
}
|
||
|
}
|