use act_rs::{impl_pre_run_async, impl_post_run_async, impl_pre_and_post_run_async, impl_mac_task_actor, impl_mac_task_actor_built_state, ActorState};
use crossbeam::queue::ArrayQueue;
use fastwebsockets::{handshake, FragmentCollector, FragmentCollectorRead, Frame, OpCode, WebSocket, WebSocketError, WebSocketRead, WebSocketWrite};
use highly_sendable::text::SendableText;
use hyper::body::Incoming;
use hyper::Response;
use libsync::std::{CountedPipelineMessage, IncrementedPipelineMessageCounter, CountedPipelineMessageMut, PipelineMessageCounter};
use libsync::{ReceiveError, ReceiveResult};
use tokio::io::{self, AsyncWriteExt, ReadHalf, WriteHalf};
use tokio::select;
use url::Url;
use std::future::Future;
use std::sync::atomic::{AtomicI32, AtomicUsize};
use std::{marker::PhantomData, sync::Arc};
use tokio::runtime::Runtime;
use std::collections::HashMap;
use tokio::time::{Duration, Instant};
use tokio::net::TcpStream;
use hyper::{Request, body::Bytes, upgrade::Upgraded, header::{UPGRADE, CONNECTION}};
use http_body_util::Empty;
use anyhow::{Error, Result};
use hyper_util::rt::TokioIo;
use tokio::task::JoinHandle;
use super::{InternalConnectionResult, NonConnectionError, OwnedFrame, ReadWebSocketActorInputMessage, ReadWebSocketActorOutputMessage, WebSocketActorInputMessage, WebSocketActorOutputMessage, WebSocketWriterActorInternalMessage};
use super::websocket_read_and_write::{WebSocketReadHalf, WebSocketWriteHalf};
use paste::paste;
use tokio::time::timeout_at;
use libsync::crossbeam::mpmc::tokio::array_queue::{Sender, Receiver, channel, io_channels::{IOClient, IOServer, io_channels, io_channel_both}};
use super::WebSocketReader;
use crate::{ConnectionStateId, ConnectionStateMessage};
static CONNECTION_SUCCEEDED: &str = "Connection succeeded!";
static ERROR_EMPTY_URL_PROVIDED: &str = "Error: Empty URL provided.";
static DISCONNECTED_FROM_SERVER: &str = "Disconnected from server.";
static ERROR_NO_SERVER_CONNECTED: &str = "Error: No server connected.";
static CLOSE_FRAME_SENT: &str = "Close frame Sent.";
static TIME_ELAPSED_FORCED_CLOSURE_NOTICE: &str = "Close Connection Response Time Has Elapsed: Forcing closure of connection.";
static SERVER_DISCONNECTION_FORCED: &str = "Forced server disconnection";
static PING_FRAME_RECEIVED: &str = "Ping frame received - pong frame already sent";
static PING_FRAME_SENT: &str = "Ping frame sent.";
static PONG_FRAME_RECEIVED: &str = "Pong frame received.";
static CLOSE_FRAME_RECEIVED: &str = "Close frame received - Close frame already sent.";
struct SpawnExecutor;
impl<Fut> hyper::rt::Executor<Fut> for SpawnExecutor
where Fut: Future + Send + 'static,
Fut::Output: Send + 'static
{
fn execute(&self, fut: Fut)
{
tokio::task::spawn(fut);
}
}
pub struct WebSocketActorState
{
read_web_socket_actor_io_client: IOClient<ConnectionStateMessage<ReadWebSocketActorInputMessage>, ConnectionStateMessage<ReadWebSocketActorOutputMessage>>, io_server: IOServer<ConnectionStateMessage<WebSocketActorInputMessage>, ConnectionStateMessage<WebSocketActorOutputMessage>>,
connection_state_id: ConnectionStateId
}
impl WebSocketActorState
{
pub fn new(io_server: IOServer<ConnectionStateMessage<WebSocketActorInputMessage>, ConnectionStateMessage<WebSocketActorOutputMessage>>) -> Self
{
let read_web_socket_actor_io_client = WebSocketReaderActorState::spawn(io_server.output_sender_ref());
Self
{
read_web_socket_actor_io_client,
io_server,
connection_state_id: ConnectionStateId::new()
}
}
pub fn spawn() -> IOClient<ConnectionStateMessage<WebSocketActorInputMessage>, ConnectionStateMessage<WebSocketActorOutputMessage>>
{
let (io_client, io_server) = io_channel_both(50);
let state = WebSocketActorState::new(io_server);
WebSocketActor::spawn(state);
io_client
}
impl_pre_and_post_run_async!();
async fn run_async(&mut self) -> bool
{
if let Ok(message) = self.io_server.input_receiver_ref().recv().await
{
let res = self.process_received_actor_input_message(message).await;
match res
{
Ok(write_half) =>
{
self.connected_loop(write_half).await.should_continue()
}
Err(err) =>
{
err.should_continue()
}
}
}
else
{
false
}
}
async fn disconnect(&mut self, mut web_socket_writer: WebSocketWriteHalf, received_close_frame: bool, sent_close_frame: bool) -> WebSocketWriterActorInternalMessage {
if let Err(_) = self.read_web_socket_actor_io_client.input_sender_ref().send(self.connection_state_id.connection_state_message(ReadWebSocketActorInputMessage::Disconnecting)).await
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed;
}
if let Err(_) = self.io_server.output_sender_ref().send(self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::Disconnecting)).await
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed;
}
if !sent_close_frame
{
if let Err(err) = self.send_close_frame(&mut web_socket_writer).await
{
return self.on_web_socket_error_report_only(err).await;
}
if let Err(_) = self.io_server.output_sender_ref().send(self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::CloseFrameSent)).await
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed;
}
}
if !received_close_frame
{
let now = Instant::now();
let soon = now.checked_add(Duration::from_secs(10)).expect("Error: Instant problems");
loop
{
let output_receiver_recv = self.read_web_socket_actor_io_client.output_receiver_ref().recv();
match timeout_at(soon, output_receiver_recv).await
{
Ok(res) =>
{
match res
{
Ok(connected_state_message) =>
{
match connected_state_message.take_message()
{
ReadWebSocketActorOutputMessage::ReadFrame(owned_frame) =>
{
if owned_frame.opcode == OpCode::Close
{
break;
}
}
ReadWebSocketActorOutputMessage::Disconnected =>
{
break;
}
}
}
Err(_) =>
{
return WebSocketWriterActorInternalMessage::ActorChannelReceiverClosed;
}
}
},
Err(_err) =>
{
let new_id = self.connection_state_id.next();
if let Err(_) = self.read_web_socket_actor_io_client.input_sender_ref().send(new_id.connection_state_message(ReadWebSocketActorInputMessage::Disconnect)).await
{
return WebSocketWriterActorInternalMessage::ActorChannelReceiverClosed;
}
if let Err(_) = self.io_server.output_sender_ref().send(new_id.connection_state_message(WebSocketActorOutputMessage::CloseWindowElapsed)).await
{
return WebSocketWriterActorInternalMessage::ActorChannelReceiverClosed;
}
return WebSocketWriterActorInternalMessage::Disconnected;
}
}
}
}
let new_id = self.connection_state_id.next();
if let Err(_) = self.read_web_socket_actor_io_client.input_sender_ref().send(new_id.connection_state_message(ReadWebSocketActorInputMessage::Disconnect)).await
{
return WebSocketWriterActorInternalMessage::ActorChannelSenderClosed;
}
if let Err(_) = self.io_server.output_sender_ref().send(new_id.connection_state_message(WebSocketActorOutputMessage::Disconnected)).await
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed;
}
WebSocketWriterActorInternalMessage::Disconnected
}
async fn disconnect_now(&mut self) -> WebSocketWriterActorInternalMessage
{
let new_id = self.connection_state_id.next();
if let Err(_) = self.read_web_socket_actor_io_client.input_sender_ref().send(new_id.connection_state_message(ReadWebSocketActorInputMessage::Disconnect)).await
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed;
}
if let Err(_) = self.io_server.output_sender_ref().send(new_id.connection_state_message(WebSocketActorOutputMessage::Disconnected)).await
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed;
}
WebSocketWriterActorInternalMessage::Disconnected
}
async fn new_connection(&mut self, web_socket: WebSocket<TokioIo<Upgraded>>) -> InternalConnectionResult<WebSocketWriteHalf>
{
let current_id = self.connection_state_id.next();
let (read, write) = web_socket.split(tokio::io::split);
let reader = WebSocketReader::FragmentCollectorRead(FragmentCollectorRead::new(read));
let ided_message = current_id.connection_state_message(ReadWebSocketActorInputMessage::NewConnection(reader));
if let Err(_) = self.read_web_socket_actor_io_client.input_sender_ref().send(ided_message).await {
return Err(WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelSenderClosed);
}
InternalConnectionResult::Ok(write)
}
async fn process_received_actor_input_message(&mut self, ided_message: ConnectionStateMessage<WebSocketActorInputMessage>) -> InternalConnectionResult<WebSocketWriteHalf> {
let message = ided_message.take_message();
match message
{
WebSocketActorInputMessage::NewConnection(websocket) =>
{
self.new_connection(websocket).await
}
WebSocketActorInputMessage::Disconnect | WebSocketActorInputMessage::DisconnectNow | WebSocketActorInputMessage::WriteFrame(_) =>
{
Err(self.report_not_connected().await)
}
}
}
async fn report_not_connected(&mut self) -> WebSocketWriterActorInternalMessage {
let ided_message = self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::NonConnectionError(NonConnectionError::NotConnected));
if let Err(_) = self.io_server.output_sender_ref().send(ided_message).await
{
return WebSocketWriterActorInternalMessage::ActorChannelSenderClosed;
}
WebSocketWriterActorInternalMessage::NonConnectionError
}
async fn connected_loop(&mut self, mut web_socket_writer: WebSocketWriteHalf) -> WebSocketWriterActorInternalMessage {
enum ConnectedInput
{
WebSocketClientReaderActorOuput(Result<ConnectionStateMessage<ReadWebSocketActorOutputMessage>, ReceiveError>),
InputReceiverInput(Result<ConnectionStateMessage<WebSocketActorInputMessage>, ReceiveError>)
}
loop
{
let res;
let read_web_socket_actor_io_client_output_receiver_recv = self.read_web_socket_actor_io_client.output_receiver_ref().recv();
let input_receiver_recv = self.io_server.input_receiver_ref().recv();
select!
{
biased;
connected_res = read_web_socket_actor_io_client_output_receiver_recv =>
{
res = ConnectedInput::WebSocketClientReaderActorOuput(connected_res);
}
connected_res = input_receiver_recv =>
{
res = ConnectedInput::InputReceiverInput(connected_res);
}
else =>
{
return WebSocketWriterActorInternalMessage::ActorChannelReceiverClosed;
}
}
match res
{
ConnectedInput::WebSocketClientReaderActorOuput(reader_ouput_res) =>
{
match reader_ouput_res
{
Ok(connection_state_message) =>
{
let message_id = connection_state_message.id();
match connection_state_message.take_message()
{
ReadWebSocketActorOutputMessage::ReadFrame(owned_frame) =>
{
if self.connection_state_id != message_id
{
continue;
}
{
let opcode = owned_frame.opcode;
if let Err(err) = self.write_frame(&mut web_socket_writer, owned_frame).await
{
return self.on_web_socket_error(err, web_socket_writer).await
}
if opcode == OpCode::Close
{
return self.disconnect(web_socket_writer, true, false).await;
}
else if opcode == OpCode::Pong
{
if let Err(_) = self.io_server.output_sender_ref().send(self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::PongFrameSent)).await
{
return WebSocketWriterActorInternalMessage::ActorChannelSenderClosed;
}
}
}
}
ReadWebSocketActorOutputMessage::Disconnected =>
{
if self.connection_state_id != message_id
{
continue;
}
let error_text = SendableText::Str("Unexpected reader error: connection closed.");
if let Err(_) = self.io_server.output_sender_ref().send(self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::ConnectionError(error_text))).await
{
return WebSocketWriterActorInternalMessage::ActorChannelSenderClosed;
}
return WebSocketWriterActorInternalMessage::Disconnected;
}
}
}
Err(_) =>
{
return WebSocketWriterActorInternalMessage::WebSocketReaderActorChannelReceiverClosed;
}
}
},
ConnectedInput::InputReceiverInput(input_receiver_res) =>
{
match input_receiver_res
{
Ok(connection_state_message) =>
{
let message_id = connection_state_message.id();
match connection_state_message.take_message()
{
WebSocketActorInputMessage::NewConnection(web_socket) =>
{
match self.new_connection(web_socket).await
{
Ok(res) =>
{
web_socket_writer = res;
}
Err(err) =>
{
return err;
}
}
}
WebSocketActorInputMessage::Disconnect =>
{
return self.disconnect(web_socket_writer, false, false).await;
}
WebSocketActorInputMessage::WriteFrame(frame) =>
{
if self.connection_state_id != message_id
{
continue;
}
let opcode = frame.opcode;
if let Err(err) = self.write_frame(&mut web_socket_writer, frame).await
{
return self.on_web_socket_error(err, web_socket_writer).await;
}
if opcode == OpCode::Close
{
return self.disconnect(web_socket_writer, false, true).await;
}
}
WebSocketActorInputMessage::DisconnectNow =>
{
return self.disconnect_now().await;
}
}
}
Err(_) =>
{
return WebSocketWriterActorInternalMessage::ActorChannelReceiverClosed;
}
}
}
}
}
}
async fn write_frame(&self, web_socket_writer: &mut WebSocketWriteHalf, mut of: OwnedFrame) -> Result<(), WebSocketError>
{
let frame = of.new_frame_to_be_written();
web_socket_writer.write_frame(frame).await?;
Ok(())
}
async fn send_close_frame(&self, web_socket_writer: &mut WebSocketWriteHalf) -> Result<(), WebSocketError>
{
println!("--> send_close_frame(_) <--");
web_socket_writer.write_frame(Frame::close_raw(vec![].into())).await
}
async fn on_web_socket_error(&mut self, error: WebSocketError, _web_socket_writer: WebSocketWriteHalf) -> WebSocketWriterActorInternalMessage {
self.on_web_socket_error_report_only(error).await
}
async fn on_web_socket_error_report_only(&mut self, error: WebSocketError) -> WebSocketWriterActorInternalMessage {
if let Err(_) = self.io_server.output_sender_ref().send(self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::ConnectionError(SendableText::String(error.to_string())))).await
{
return WebSocketWriterActorInternalMessage::ActorChannelSenderClosed;
}
WebSocketWriterActorInternalMessage::ConnectionError
}
async fn on_non_connection_error(&mut self, non_connection_error: NonConnectionError) -> WebSocketWriterActorInternalMessage {
let ided_message = self.connection_state_id.connection_state_message(WebSocketActorOutputMessage::NonConnectionError(non_connection_error));
if let Err(_) = self.io_server.output_sender_ref().send(ided_message).await
{
return WebSocketWriterActorInternalMessage::ActorChannelSenderClosed;
}
WebSocketWriterActorInternalMessage::NonConnectionError
}
}
impl_mac_task_actor!(WebSocketActor);
struct WebSocketReaderActorState
{
write_frame_processor_actor_io_sender: Sender<ConnectionStateMessage<WebSocketActorOutputMessage>>, connection_state_id: ConnectionStateId,
obligated_send_frame_holder: Arc<ArrayQueue<OwnedFrame>>, io_server: IOServer<ConnectionStateMessage<ReadWebSocketActorInputMessage>, ConnectionStateMessage<ReadWebSocketActorOutputMessage>>
}
impl WebSocketReaderActorState
{
pub fn new(write_frame_processor_actor_io_sender: &Sender<ConnectionStateMessage<WebSocketActorOutputMessage>>) -> (IOClient<ConnectionStateMessage<ReadWebSocketActorInputMessage>, ConnectionStateMessage<ReadWebSocketActorOutputMessage>>, Self)
{
let (io_client, io_server) = io_channels(4, 10);
(io_client,
Self
{
write_frame_processor_actor_io_sender: write_frame_processor_actor_io_sender.clone(),
connection_state_id: ConnectionStateId::new(),
obligated_send_frame_holder: Arc::new(ArrayQueue::new(1)),
io_server
})
}
pub fn spawn(write_frame_processor_actor_io_sender: &Sender<ConnectionStateMessage<WebSocketActorOutputMessage>>) -> IOClient<ConnectionStateMessage<ReadWebSocketActorInputMessage>, ConnectionStateMessage<ReadWebSocketActorOutputMessage>> {
let (io_client, state) = WebSocketReaderActorState::new(write_frame_processor_actor_io_sender);
WebSocketReaderActor::spawn(state);
io_client
}
impl_pre_and_post_run_async!();
async fn run_async(&mut self) -> bool
{
match self.io_server.input_receiver_ref().recv().await
{
Ok(message) =>
{
match message.set_id_take_message(&mut self.connection_state_id) {
ReadWebSocketActorInputMessage::NewConnection(reader) =>
{
let message = WebSocketActorOutputMessage::NewConnection;
let ided_message = self.connection_state_id.connection_state_message(message);
if let Err(_err) = self.write_frame_processor_actor_io_sender.send(ided_message).await
{
return false;
}
self.connected_loop(reader).await
}
ReadWebSocketActorInputMessage::Disconnect | ReadWebSocketActorInputMessage::Disconnecting => { true },
}
}
Err(_) => {
return false
}
}
}
async fn connected_loop(&mut self, mut reader: WebSocketReader) -> bool
{
enum SelectResult<'f>
{
ReadFrame(Result<Frame<'f>, WebSocketError>),
Connection(ReceiveResult<ConnectionStateMessage<ReadWebSocketActorInputMessage>>)
}
let mut is_disconnecting = false;
let obligated_send_frame_holder = self.obligated_send_frame_holder.clone();
let mut is_obligated_send_frame = false;
let mut send_fn = |obligated_send_frame: Frame|
{
is_obligated_send_frame = true;
let mut of = OwnedFrame::new();
of.copy_all_from_read_frame(&obligated_send_frame);
let _ = obligated_send_frame_holder.push(of).expect("Error: The obligated_send_frame_holder should've been checked.");
async
{
Result::<(), WebSocketError>::Ok(())
}
};
loop
{
let connection_future = self.io_server.input_receiver_ref().recv();
let read_frame_future = reader.read_frame(&mut send_fn);
let select_result;
select!
{
biased;
res = connection_future =>
{
select_result = SelectResult::Connection(res);
}
res = read_frame_future =>
{
select_result = SelectResult::ReadFrame(res);
}
else =>
{
return false;
}
}
if let Some(mut of) = obligated_send_frame_holder.pop()
{
println!("WebSocketReaderActor: connected_loop - obligated_send_frame_holder.pop()");
println!("{:?}", of);
match of.opcode
{
OpCode::Close =>
{
of.clear_payload();
let message = ReadWebSocketActorOutputMessage::ReadFrame(of);
let ided_message = ConnectionStateMessage::new(self.connection_state_id, message);
if let Err(_err) = self.io_server.output_sender_ref().send(ided_message).await
{
return false;
}
}
OpCode::Ping =>
{
if is_disconnecting
{
continue;
}
of.pong_setup();
of.clear_payload();
let message = ReadWebSocketActorOutputMessage::ReadFrame(of);
let ided_message = ConnectionStateMessage::new(self.connection_state_id, message);
if let Err(_err) = self.io_server.output_sender_ref().send(ided_message).await
{
return false;
}
}
OpCode::Continuation | OpCode::Text | OpCode::Binary | OpCode::Pong =>
{
let opcode = of.opcode;
let message = WebSocketActorOutputMessage::ReadFrame(of);
let ided_message = self.connection_state_id.connection_state_message(message);
if let Err(_err) = self.write_frame_processor_actor_io_sender.send(ided_message).await
{
return false;
}
let message = WebSocketActorOutputMessage::ConnectionError(SendableText::String(format!("Error: This is not an obligated frame: {:?}", opcode)));
let ided_message = ConnectionStateMessage::new(self.connection_state_id, message);
if let Err(_err) = self.write_frame_processor_actor_io_sender.send(ided_message).await
{
return false;
}
return true;
}
}
}
match select_result
{
SelectResult::ReadFrame(frame_res) =>
{
match frame_res
{
Ok(frame) =>
{
let mut of = OwnedFrame::new();
of.copy_all_from_read_frame(&frame);
println!("WebSocketReaderActor: SelectResult::ReadFrame");
println!("{:?}", of);
let message = WebSocketActorOutputMessage::ReadFrame(of);
let ided_message = self.connection_state_id.connection_state_message(message);
if let Err(_err) = self.write_frame_processor_actor_io_sender.send(ided_message).await
{
return false;
}
}
Err(_err) =>
{
let message = ReadWebSocketActorOutputMessage::Disconnected;
let ided_message = self.connection_state_id.connection_state_message(message);
if let Err(_err) = self.io_server.output_sender_ref().send(ided_message).await
{
return false;
}
return true;
}
}
}
SelectResult::Connection(input_result) =>
{
if let Ok(message) = input_result
{
match message.set_id_take_message(&mut self.connection_state_id) {
ReadWebSocketActorInputMessage::NewConnection(new_reader) =>
{
let message = WebSocketActorOutputMessage::NewConnection;
let ided_message = self.connection_state_id.connection_state_message(message);
if let Err(_err) = self.write_frame_processor_actor_io_sender.send(ided_message).await
{
return false;
}
reader = new_reader;
is_disconnecting = false;
}
ReadWebSocketActorInputMessage::Disconnecting =>
{
is_disconnecting = true;
}
ReadWebSocketActorInputMessage::Disconnect =>
{
return true;
}
}
}
else
{
return false;
}
}
}
}
}
}
impl_mac_task_actor!(WebSocketReaderActor);