diff --git a/src/main.rs b/src/main.rs index 9ce0635..8aba90c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -148,7 +148,7 @@ impl StreamHandler> for WsChatSession { "/join" => { if v.len() == 2 { self.room = v[1].to_owned(); - self.addr.do_send(server::Join { + self.addr.do_send(server::ChatMessage::Join { id: self.id, name: self.room.clone(), }); @@ -174,7 +174,7 @@ impl StreamHandler> for WsChatSession { m.to_owned() }; // send message to chat server - self.addr.do_send(server::ClientMessage { + self.addr.do_send(server::ChatMessage::ClientMessage { id: self.id, msg, room: self.room.clone(), diff --git a/src/server/mod.rs b/src/server/mod.rs index 9e9fae4..9bfb606 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,10 +1,10 @@ - //! `ChatServer` is an actor. It maintains list of connection client session. //! And manages available rooms. Peers send messages to other peers in same //! room through `ChatServer`. use actix::prelude::*; use rand::{self, rngs::ThreadRng, Rng}; +use serde::*; use std::collections::{HashMap, HashSet}; /// Chat server sends this messages to session @@ -29,33 +29,32 @@ pub struct Disconnect { } /// Send message to specific room -#[derive(Message)] +#[derive(Message, Serialize, Deserialize)] #[rtype(result = "()")] -pub struct ClientMessage { - /// Id of the client session - pub id: usize, - /// Peer message - pub msg: String, - /// Room name - pub room: String, +#[serde(tag = "type")] +pub enum ChatMessage { + ClientMessage { + /// Id of the client session + id: usize, + /// Peer message + msg: String, + /// Room name + room: String, + }, + Join { + /// Client id + id: usize, + /// Room name + name: String, + }, } /// List of available rooms +#[derive(Message)] +#[rtype(result = "Vec")] pub struct ListRooms; -impl actix::Message for ListRooms { - type Result = Vec; -} - /// Join room, if room does not exists create new one. -#[derive(Message)] -#[rtype(result = "()")] -pub struct Join { - /// Client id - pub id: usize, - /// Room name - pub name: String, -} /// `ChatServer` manages chat rooms and responsible for coordinating chat /// session. implementation is super primitive @@ -154,11 +153,36 @@ impl Handler for ChatServer { } /// Handler for Message message. -impl Handler for ChatServer { +impl Handler for ChatServer { type Result = (); - fn handle(&mut self, msg: ClientMessage, _: &mut Context) { - self.send_message(&msg.room, msg.msg.as_str(), msg.id); + fn handle(&mut self, msg: ChatMessage, _: &mut Context) { + match msg { + ChatMessage::ClientMessage { room, msg, id } => { + self.send_message(&room, msg.as_str(), id) + } + ChatMessage::Join { id, name } => { + let mut rooms = Vec::new(); + + // remove session from all rooms + for (n, sessions) in &mut self.rooms { + if sessions.remove(&id) { + rooms.push(n.to_owned()); + } + } + // send message to other users + for room in rooms { + self.send_message(&room, "Someone disconnected", 0); + } + + self.rooms + .entry(name.clone()) + .or_insert(HashSet::new()) + .insert(id); + + self.send_message(&name, "Someone connected", id); + } + } } } @@ -176,32 +200,3 @@ impl Handler for ChatServer { MessageResult(rooms) } } - -/// Join room, send disconnect message to old room -/// send join message to new room -impl Handler for ChatServer { - type Result = (); - - fn handle(&mut self, msg: Join, _: &mut Context) { - let Join { id, name } = msg; - let mut rooms = Vec::new(); - - // remove session from all rooms - for (n, sessions) in &mut self.rooms { - if sessions.remove(&id) { - rooms.push(n.to_owned()); - } - } - // send message to other users - for room in rooms { - self.send_message(&room, "Someone disconnected", 0); - } - - self.rooms - .entry(name.clone()) - .or_insert(HashSet::new()) - .insert(id); - - self.send_message(&name, "Someone connected", id); - } -}