This commit is contained in:
Víctor Martínez 2021-03-07 15:04:03 +01:00
parent 76f3a81d07
commit 7bef1322a3
8 changed files with 45 additions and 35 deletions

1
Cargo.lock generated
View file

@ -125,6 +125,7 @@ dependencies = [
"actix-web",
"actix-web-actors",
"derive_more",
"serde_json",
"uuid",
]

View file

@ -15,3 +15,4 @@ actix-web = "3"
actix-web-actors = "3.0.0"
uuid = { version = "0.8", features = ["serde", "v4"] }
derive_more = "0.99.11"
serde_json = "1.0.64"

View file

@ -3,14 +3,14 @@ use std::collections::{HashMap, HashSet};
use uuid::Uuid;
use crate::messages::{
chat_server::{ClientMessage, Connect, Disconnect, JoinRoom},
chat_server::{ClientMessage, Connect, CreateRoom, Disconnect, JoinRoom},
chat_session::Message,
};
use crate::models::SessionId;
use crate::models::{RoomId, SessionId};
pub struct ChatServer {
sessions: HashMap<SessionId, Recipient<Message>>,
rooms: HashMap<String, HashSet<SessionId>>,
rooms: HashMap<RoomId, HashSet<SessionId>>,
}
impl ChatServer {
@ -21,7 +21,7 @@ impl ChatServer {
}
}
pub fn send_message(&self, room: &str, message: &str, skip_id: &Uuid) {
pub fn send_message(&self, room: &Uuid, message: &str, skip_id: &Uuid) {
self.rooms.get(room).map(|sessions| {
sessions.iter().for_each(|id| {
if id != skip_id {
@ -68,10 +68,25 @@ impl Handler<ClientMessage> for ChatServer {
fn handle(&mut self, msg: ClientMessage, _ctx: &mut Self::Context) -> Self::Result {
let ClientMessage { session, room, msg } = msg;
self.send_message(&room, &msg, &session);
}
}
impl Handler<CreateRoom> for ChatServer {
type Result = MessageResult<CreateRoom>;
fn handle(&mut self, msg: CreateRoom, _ctx: &mut Self::Context) -> Self::Result {
let CreateRoom { session } = msg;
let room_id = RoomId::new_v4();
self.rooms.insert(
room_id,
vec![session].into_iter().collect::<HashSet<Uuid>>(),
);
MessageResult(room_id)
}
}
impl Handler<JoinRoom> for ChatServer {
type Result = ();
fn handle(
@ -93,10 +108,8 @@ impl Handler<JoinRoom> for ChatServer {
}
self.rooms
.entry(room.clone())
.or_insert_with(HashSet::new)
.insert(session);
self.send_message(&room, "Someone connected", &session);
.get_mut(&room)
.map(|sessions| sessions.insert(session))
.map(|_| self.send_message(&room, "Someone connected", &session));
}
}

View file

@ -4,9 +4,10 @@ use crate::{
actors::chat_server::ChatServer,
commands::Command,
messages::{
chat_server::{ClientMessage, Connect, Disconnect, JoinRoom},
chat_server::{ClientMessage, Connect, Disconnect},
chat_session::Message,
},
models::{RoomId, SessionId},
};
use actix::{
fut, ActorContext, ActorFuture, ContextFutureSpawner, Handler, Running, StreamHandler,
@ -14,11 +15,10 @@ use actix::{
};
use actix::{Actor, Addr, AsyncContext};
use actix_web_actors::ws::{self, WebsocketContext};
use uuid::Uuid;
pub struct WsChatSession {
pub id: Option<Uuid>,
pub room: Option<String>,
pub id: Option<SessionId>,
pub room: Option<RoomId>,
pub addr: Addr<ChatServer>,
}
@ -31,15 +31,8 @@ impl WsChatSession {
}
}
pub fn execute(&self, cmd: Command, ctx: &mut WebsocketContext<Self>) {
pub fn execute(&self, cmd: Command, _ctx: &mut WebsocketContext<Self>) {
match cmd {
Command::Join(name) => {
self.addr.do_send(JoinRoom {
session: self.id.unwrap().clone(),
room: name,
});
ctx.text("Joined!");
}
Command::Msg(msg) => {
self.addr.do_send(ClientMessage {
session: self.id.clone().unwrap(),
@ -100,6 +93,7 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WsChatSession {
};
match msg {
// TODO: Deserialize string to json first, then check action type
ws::Message::Text(msg) => match Command::from_str(&msg) {
Ok(cmd) => self.execute(cmd, ctx),
Err(err) => ctx.text(err.to_string()),

View file

@ -9,21 +9,14 @@ pub struct CommandError {
}
pub enum Command {
Join(String),
Msg(String),
}
// TODO: IMPLEMENT MORE COMMANDS
impl FromStr for Command {
type Err = CommandError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let words: Vec<&str> = s.trim().split_whitespace().into_iter().collect();
let first = words.first().map(|&v| v).unwrap_or("");
if first == "/join" {
let name = words.last().map(|&v| v).unwrap_or("");
Ok(Command::Join(name.into()))
} else {
Ok(Command::Msg(s.into()))
}
Ok(Command::Msg(s.into()))
}
}

View file

@ -1,21 +1,28 @@
use super::chat_session::Message;
use crate::models::SessionId;
use actix::{Message as ActixMessage, Recipient};
use uuid::Uuid;
use crate::models::{RoomId, SessionId};
use super::chat_session::Message;
#[derive(ActixMessage)]
#[rtype(result = "()")]
pub struct ClientMessage {
pub session: SessionId,
pub room: String,
pub room: RoomId,
pub msg: String,
}
#[derive(ActixMessage)]
#[rtype(result = "Uuid")]
pub struct CreateRoom {
pub session: SessionId,
}
#[derive(ActixMessage)]
#[rtype(result = "()")]
pub struct JoinRoom {
pub session: SessionId,
pub room: String,
pub room: RoomId,
}
#[derive(ActixMessage)]

View file

@ -1,3 +1,4 @@
pub mod ws_messages;
use actix::Addr;
use uuid::Uuid;

View file