use crate::entities::{channel::Channel, user::User};
use std::{collections::HashMap, net::SocketAddr};
use actix::{io::FramedWrite, prelude::*};
use tokio::net::TcpStream;
use tokio_util::codec::FramedRead;
pub struct Server {
pub channels: HashMap<String, Addr<Channel>>,
}
impl Server {
pub fn new() -> Self {
Self {
channels: HashMap::new(),
}
}
}
impl Actor for Server {
type Context = Context<Self>;
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct Connection(pub TcpStream, pub SocketAddr);
impl Handler<Connection> for Server {
type Result = ();
fn handle(&mut self, Connection(stream, remote): Connection, server_ctx: &mut Self::Context) {
println!("Accepted connection from {}", remote);
User::create(move |ctx| {
let (read, write) = tokio::io::split(stream);
let read = FramedRead::new(read, titanirc_codec::Decoder);
let write =
FramedWrite::new(write, titanirc_codec::Encoder::new("my.cool.server"), ctx);
ctx.add_stream(read);
User::new(server_ctx.address(), write)
});
}
}
impl Handler<crate::entities::channel::events::Join> for Server {
type Result = ResponseActFuture<Self, crate::entities::channel::events::JoinResult>;
fn handle(
&mut self,
msg: crate::entities::channel::events::Join,
_ctx: &mut Self::Context,
) -> Self::Result {
#[allow(clippy::option_if_let_else)]
let channel = if let Some(channel) = self.channels.get(&msg.channel_name) {
channel
} else {
let channel = Channel::create(|_ctx| Channel::new());
self.channels
.entry(msg.channel_name.clone())
.or_insert(channel)
};
Box::pin(
channel
.send(msg)
.into_actor(self)
.map(|v, _, _| v.map_err(|e| e.into()).and_then(|v| v)),
)
}
}
impl Handler<crate::entities::common_events::Message> for Server {
type Result = ();
fn handle(
&mut self,
msg: crate::entities::common_events::Message,
ctx: &mut Self::Context,
) -> Self::Result {
eprintln!("to: {}", msg.to);
let channel = self.channels.get(&msg.to).unwrap().clone();
ctx.spawn(
async move {
channel.send(msg).await.unwrap();
}
.into_actor(self),
);
}
}