use crate::general::ConnectionReader;
use crate::message::{Message, MessageHeader, MessageType};
const BUFFER_SIZE: usize = 4096;
pub async fn recv<F, C>(
client_id: u32,
user_id: u32,
mut con: C,
send_queue: tokio::sync::mpsc::UnboundedSender<Message>,
close_user: F,
) where
C: ConnectionReader + Send,
F: std::future::Future<Output = ()>,
{
loop {
let mut buf = vec![0; BUFFER_SIZE];
match con.read(&mut buf).await {
Ok(n) => {
let message_type = if n > 0 {
MessageType::Data
} else {
MessageType::EOF
};
buf.truncate(n);
let header = MessageHeader::new(user_id, message_type, n as u64);
let msg = Message::new(header, buf);
if let Err(e) = send_queue.send(msg) {
error!(
"[{}][{}] Forwarding message to client: {}",
client_id, user_id, e
);
break;
}
if n == 0 {
break;
}
}
Err(e) => {
error!("[{}][{}] Reading from User-Con: {}", client_id, user_id, e);
break;
}
}
}
close_user.await;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::general::mocks::MockReader;
#[tokio::test]
async fn valid_read() {
let mut reader = MockReader::new();
reader.add_bytes(&vec![0, 1, 2, 3, 4, 5, 6]);
reader.close();
let called = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
async fn close_con(tmp: std::sync::Arc<std::sync::atomic::AtomicBool>) {
tmp.store(true, std::sync::atomic::Ordering::SeqCst);
}
let (queue_tx, mut queue_rx) = tokio::sync::mpsc::unbounded_channel();
let client_id = 12;
let user_id = 5;
recv(
client_id,
user_id,
reader,
queue_tx,
close_con(called.clone()),
)
.await;
assert_eq!(
Some(Message::new(
MessageHeader::new(user_id, MessageType::Data, 7),
vec![0, 1, 2, 3, 4, 5, 6]
)),
queue_rx.recv().await
);
assert_eq!(
Some(Message::new(
MessageHeader::new(user_id, MessageType::EOF, 0),
vec![]
)),
queue_rx.recv().await
);
assert_eq!(true, called.load(std::sync::atomic::Ordering::SeqCst));
}
}