ChatKit-server/server/src/client_management/client.rs

197 lines
4.9 KiB
Rust

use std::net::SocketAddr;
use crate::network::{Connection, ConnectionOuput};
use crate::prelude::ObservableMessage;
use actix::{Actor, Addr, Context, Handler, Message, MessageResponse, WeakAddr, Recipient, Running, ArbiterHandle, AsyncContext};
use serde_json::{from_str, to_string};
use foundation::ClientDetails;
use crate::network::ConnectionMessage;
use uuid::Uuid;
use foundation::messages::client::{ClientStreamIn, ClientStreamOut};
use crate::client_management::client::ClientObservableMessage::UpdateRequest;
use crate::network::ConnectionMessage::SendData;
use crate::prelude::ObservableMessage::Subscribe;
/// Message sent ot the clients delegate
#[derive(Message)]
#[rtype(result = "()")]
pub enum ClientMessage {
SendUpdate(Vec<ClientDetails>),
sendMessage {
from: Uuid,
content: String,
},
}
#[derive(Message)]
#[rtype(result = "ClientDetailsResponse")]
pub struct ClientDataMessage;
#[derive(MessageResponse)]
pub struct ClientDetailsResponse(pub ClientDetails);
/// messages the client will send to itself
enum SelfMessage {
ReceivedMessage(ClientStreamIn)
}
/// message that is sent to all observers of the current client.
#[derive(Message, Clone)]
#[rtype(result = "()")]
pub enum ClientObservableMessage {
SendMessageRequest(WeakAddr<Client>, Uuid, String),
UpdateRequest(WeakAddr<Client>),
}
/// # Client
/// This represents a connected client.
/// it will handle received message from a connection.
pub struct Client {
connection: Addr<Connection>,
details: ClientDetails,
observers: Vec<Recipient<ClientObservableMessage>>
}
impl Client {
pub(crate) fn new(
connection: Addr<Connection>,
details: ClientDetails,
) -> Addr<Self> {
Client {
connection,
details,
observers: Vec::default(),
}
.start()
}
fn handle_request(
&mut self,
ctx: &mut Context<Client>,
sender: Addr<Connection>,
addr: SocketAddr,
data: String
) {
use ClientStreamIn::{Update, SendMessage, SendGlobalMessage, Disconnect};
let msg = from_str::<ClientStreamIn>(data.as_str()).expect("[Client] failed to decode incoming message");
match msg {
Update => self.handle_update(ctx),
SendMessage { to, content } => self.handle_send(ctx, to, content),
SendGlobalMessage { content } => self.handle_global_send(ctx, content),
Disconnect => self.handle_disconnect(ctx),
_ => todo!()
}
}
#[inline]
fn handle_update(&self,
ctx: &mut Context<Client>,
) {
self.broadcast(UpdateRequest(ctx.address().downgrade()));
}
#[inline]
fn handle_send(&self, ctx: &mut Context<Client>, uuid: Uuid, content: String) {
todo!()
}
#[inline]
fn handle_global_send(&self, p0: &mut Context<Client>, p1: String) {
todo!()
}
#[inline]
fn handle_disconnect(&self, ctx: &mut Context<Client>) {
todo!()
}
#[inline]
fn broadcast(&self, message: ClientObservableMessage) {
for recp in &self.observers {
recp.do_send(message.clone());
}
}
}
impl Actor for Client {
type Context = Context<Self>;
// tells the client that it has been connected.
fn started(&mut self, ctx: &mut Self::Context) {
use ClientStreamOut::Connected;
use ConnectionMessage::{SendData};
println!("[Client] started");
self.connection.do_send(Subscribe(ctx.address().recipient()));
self.connection.do_send(SendData(to_string::<ClientStreamOut>(&Connected).unwrap()));
}
}
impl Handler<ClientDataMessage> for Client {
type Result = ClientDetailsResponse;
fn handle(&mut self, msg: ClientDataMessage, ctx: &mut Self::Context) -> Self::Result {
ClientDetailsResponse(self.details.clone())
}
}
// Handles incoming messages to the client.
impl Handler<ClientMessage> for Client {
type Result = ();
fn handle(
&mut self,
msg: ClientMessage,
_ctx: &mut Self::Context,
) -> Self::Result {
use ClientMessage::SendUpdate;
use ClientStreamOut::{ConnectedClients};
match msg {
SendUpdate(clients) => self.connection.do_send(
SendData(to_string::<ClientStreamOut>(
&ConnectedClients { clients }
).expect("[Client] Failed to encode string"))),
_ => todo!(),
}
}
}
// Handles outputs from the connection.
impl Handler<ConnectionOuput> for Client {
type Result = ();
fn handle(
&mut self,
msg: ConnectionOuput,
ctx: &mut Self::Context
) -> Self::Result {
use ConnectionOuput::RecvData;
match msg {
RecvData(sender, addr, data) => self.handle_request(ctx, sender, addr, data),
_ => todo!()
}
}
}
impl Handler<ObservableMessage<ClientObservableMessage>> for Client {
type Result = ();
fn handle(&mut self, msg: ObservableMessage<ClientObservableMessage>, ctx: &mut Self::Context) -> Self::Result {
use ObservableMessage::{Subscribe,Unsubscribe};
match msg {
Subscribe(r) => {
println!("[Client] adding subscriber");
self.observers.push(r);
}
Unsubscribe(r) => {
println!("[Client] removing subscriber");
self.observers = self
.observers
.clone()
.into_iter()
.filter(|a| a != &r)
.collect();
}
}
}
}