use futures_util::{SinkExt, StreamExt};
use tokio_tungstenite::tungstenite::Message;
use super::WebSocket;
use tokio::sync::mpsc;
use super::frames::write_frames;
use crate::Frame;
use crate::engine::{self, Data, Packet as EnginePacket};
use crate::session::Input;
pub(super) async fn run_direct(
input: mpsc::Sender,
mut socket: WebSocket,
mut outbound: mpsc::Receiver>,
) {
loop {
tokio::select! {
_ = input.closed() => break,
incoming = socket.next() => {
let Some(Ok(message)) = incoming else {
break;
};
match message {
Message::Text(text) => {
let Some(packet) = engine::decode_packet(&text) else {
break;
};
if input.try_send(Input::Packets(vec![packet])).is_err() {
break;
}
}
Message::Binary(data) => {
if input
.try_send(Input::Packets(vec![EnginePacket::Message(Data::Binary(
data.to_vec(),
))]))
.is_err()
{
break;
}
}
Message::Ping(_) => {
if !matches!(tokio::time::timeout(std::time::Duration::from_secs(5), socket.flush()).await, Ok(Ok(()))) {
break;
}
}
Message::Pong(_) | Message::Frame(_) => {}
Message::Close(_) => break,
}
}
frames = outbound.recv() => {
match frames {
Some(frames) => {
if !write_frames(&mut socket, frames).await {
break;
}
}
None => break,
}
}
}
}
let _ = tokio::time::timeout(std::time::Duration::from_secs(5), input.send(Input::Close)).await;
let _ = tokio::time::timeout(
std::time::Duration::from_secs(5),
SinkExt::close(&mut socket),
)
.await;
}