use crate::client::connections::UserCon;
use crate::client::user_con;
use crate::general::ConnectionReader;
use crate::streams::mpsc;
use crate::Details;
use crate::{
client::Handler,
message::{Message, MessageHeader, MessageType},
};
use crate::{connections::Connections, metrics::Metrics};
use std::sync::Arc;
#[derive(Debug)]
enum ReceiveError {
DeserializingHeader,
ReceivingMessage(std::io::Error),
}
struct SingleOptions<'a, R> {
server_con: &'a mut R,
send_queue: &'a tokio::sync::mpsc::UnboundedSender<Message>,
client_cons: &'a Arc<Connections<mpsc::StreamWriter<Message>>>,
head_buf: &'a mut [u8; 13],
}
async fn receive_single<R, H, M>(
opts: SingleOptions<'_, R>,
handler: Arc<H>,
metrics: &M,
) -> Result<(), ReceiveError>
where
R: ConnectionReader + Sized + Send + Sync,
H: Handler + Send + Sync + 'static,
M: Metrics + Send + Sync,
{
let header = match opts.server_con.read_full(opts.head_buf).await {
Ok(_) => match MessageHeader::deserialize(&opts.head_buf) {
Some(s) => s,
None => return Err(ReceiveError::DeserializingHeader),
},
Err(e) => return Err(ReceiveError::ReceivingMessage(e)),
};
let id = header.get_id();
let kind = header.get_kind();
match kind {
MessageType::Close => {
opts.client_cons.remove(id);
debug!("Closing Connection: {}", id);
return Ok(());
}
MessageType::Data | MessageType::EOF => {}
MessageType::Connect => {
let mut details_buf = vec![0; header.get_length() as usize];
let details = match opts.server_con.read_full(&mut details_buf).await {
Ok(_) => match Details::deserialize(&mut details_buf) {
Ok(d) => d,
Err(e) => {
error!("Parsing Connection-Details: {:?}", e);
return Ok(());
}
},
Err(e) => {
error!("Reading Connection-Details: {:?}", e);
return Ok(());
}
};
let (tx, stream_rx) = mpsc::stream();
opts.client_cons.set(id, tx);
let handle_rx = user_con::OwnedReceiver::new(stream_rx);
let handle_tx =
user_con::OwnedSender::new(id, opts.send_queue.clone(), opts.client_cons.clone());
let handle_con = UserCon::new(handle_rx, handle_tx);
tokio::task::spawn(H::new_con(handler, id, details, handle_con));
debug!("Established new Connection: {}", id);
return Ok(());
}
_ => {
error!("Unexpected Message-Type: {:?}", kind);
return Ok(());
}
};
metrics.received_msg();
metrics.recv_bytes(header.get_length());
let data_length = header.get_length() as usize;
let mut buf = vec![0; data_length];
let msg = match opts.server_con.read_full(&mut buf).await {
Ok(_) => Message::new(header, buf),
Err(e) => {
error!("Receiving Data: {}", e);
opts.client_cons.remove(id);
return Ok(());
}
};
let con_queue = match opts.client_cons.get_clone(id) {
Some(q) => q,
None => {
error!("Received Data for non-existing Connection: {}", id);
return Ok(());
}
};
if let Err(e) = con_queue.send(msg) {
error!("Adding to Queue for {}: {}", id, e);
return Ok(());
}
Ok(())
}
pub async fn receiver<R, H, M>(
mut server_con: R,
send_queue: tokio::sync::mpsc::UnboundedSender<Message>,
client_cons: std::sync::Arc<Connections<mpsc::StreamWriter<Message>>>,
handler: Arc<H>,
metrics: Arc<M>,
) where
R: ConnectionReader + Sized + Send + Sync,
H: Handler + Send + Sync + 'static,
M: Metrics + Send + Sync,
{
let mut head_buf = [0; 13];
loop {
let opts = SingleOptions {
server_con: &mut server_con,
send_queue: &send_queue,
client_cons: &client_cons,
head_buf: &mut head_buf,
};
if let Err(e) = receive_single(opts, handler.clone(), metrics.as_ref()).await {
error!("Receiving: {:?}", e);
break;
}
}
}
#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr};
use super::*;
use crate::client::mocks as client_mocks;
use crate::general::mocks;
use crate::metrics::Empty;
#[tokio::test]
async fn valid_sends_data_to_correct_handler() {
let id = 13;
let mut tmp_reader = mocks::MockReader::new();
tmp_reader.add_message(Message::new(
MessageHeader::new(id, MessageType::Data, 10),
vec![3; 10],
));
let (queue_tx, _) = tokio::sync::mpsc::unbounded_channel();
let client_cons = std::sync::Arc::new(Connections::<mpsc::StreamWriter<Message>>::new());
let (client_tx, mut client_rx) = mpsc::stream();
client_cons.set(id, client_tx);
let mut head_buf = [0; 13];
let result = receive_single(
SingleOptions {
server_con: &mut tmp_reader,
send_queue: &queue_tx,
client_cons: &client_cons,
head_buf: &mut head_buf,
},
Arc::new(client_mocks::EmptyHandler::new()),
&Empty::new(),
)
.await;
assert_eq!(true, result.is_ok());
assert_eq!(
Ok(Message::new(
MessageHeader::new(id, MessageType::Data, 10),
vec![3; 10],
)),
client_rx.recv().await
);
}
#[tokio::test]
async fn valid_establish_connection() {
let id = 13;
let details = Details::new(IpAddr::V4(Ipv4Addr::from([0, 0, 0, 0]))).serialize();
let mut tmp_reader = mocks::MockReader::new();
tmp_reader.add_message(Message::new(
MessageHeader::new(id, MessageType::Connect, details.len() as u64),
details,
));
let (queue_tx, _) = tokio::sync::mpsc::unbounded_channel();
let client_cons = std::sync::Arc::new(Connections::<mpsc::StreamWriter<Message>>::new());
let mut head_buf = [0; 13];
let result = receive_single(
SingleOptions {
server_con: &mut tmp_reader,
send_queue: &queue_tx,
client_cons: &client_cons,
head_buf: &mut head_buf,
},
Arc::new(client_mocks::EmptyHandler::new()),
&Empty::new(),
)
.await;
assert_eq!(true, result.is_ok());
let connection_queue = client_cons.get_clone(id);
assert_eq!(true, connection_queue.is_some());
}
}