1
0
mirror of https://github.com/actix/examples synced 2024-11-25 07:12:42 +01:00
examples/websockets/chat-broker/src/server.rs

117 lines
3.1 KiB
Rust
Raw Normal View History

2022-02-18 02:44:53 +01:00
use std::collections::HashMap;
use actix::prelude::*;
use actix_broker::BrokerSubscribe;
2020-04-09 02:54:28 +02:00
use crate::message::{ChatMessage, JoinRoom, LeaveRoom, ListRooms, SendMessage};
type Client = Recipient<ChatMessage>;
type Room = HashMap<usize, Client>;
2020-04-09 02:54:28 +02:00
#[derive(Default)]
pub struct WsChatServer {
rooms: HashMap<String, Room>,
}
impl WsChatServer {
fn take_room(&mut self, room_name: &str) -> Option<Room> {
let room = self.rooms.get_mut(room_name)?;
2021-10-07 04:04:59 +02:00
let room = std::mem::take(room);
Some(room)
}
2022-02-18 03:44:02 +01:00
fn add_client_to_room(&mut self, room_name: &str, id: Option<usize>, client: Client) -> usize {
2019-09-04 17:04:57 +02:00
let mut id = id.unwrap_or_else(rand::random::<usize>);
2020-04-09 02:54:28 +02:00
if let Some(room) = self.rooms.get_mut(room_name) {
loop {
if room.contains_key(&id) {
id = rand::random::<usize>();
} else {
break;
}
}
2020-04-09 02:54:28 +02:00
room.insert(id, client);
return id;
}
2020-04-09 02:54:28 +02:00
// Create a new room for the first client
let mut room: Room = HashMap::new();
2020-04-09 02:54:28 +02:00
room.insert(id, client);
self.rooms.insert(room_name.to_owned(), room);
2020-04-09 02:54:28 +02:00
id
}
2022-02-18 03:44:02 +01:00
fn send_chat_message(&mut self, room_name: &str, msg: &str, _src: usize) -> Option<()> {
let mut room = self.take_room(room_name)?;
2020-04-09 02:54:28 +02:00
for (id, client) in room.drain() {
2022-03-04 17:28:40 +01:00
if client.try_send(ChatMessage(msg.to_owned())).is_ok() {
self.add_client_to_room(room_name, Some(id), client);
}
}
2020-04-09 02:54:28 +02:00
Some(())
}
}
impl Actor for WsChatServer {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
2019-07-11 11:02:25 +02:00
self.subscribe_system_async::<LeaveRoom>(ctx);
self.subscribe_system_async::<SendMessage>(ctx);
}
}
impl Handler<JoinRoom> for WsChatServer {
type Result = MessageResult<JoinRoom>;
fn handle(&mut self, msg: JoinRoom, _ctx: &mut Self::Context) -> Self::Result {
let JoinRoom(room_name, client_name, client) = msg;
2020-04-09 02:54:28 +02:00
let id = self.add_client_to_room(&room_name, None, client);
let join_msg = format!(
"{} joined {}",
2019-09-04 17:04:57 +02:00
client_name.unwrap_or_else(|| "anon".to_string()),
room_name
);
2020-04-09 02:54:28 +02:00
self.send_chat_message(&room_name, &join_msg, id);
MessageResult(id)
}
}
impl Handler<LeaveRoom> for WsChatServer {
type Result = ();
fn handle(&mut self, msg: LeaveRoom, _ctx: &mut Self::Context) {
if let Some(room) = self.rooms.get_mut(&msg.0) {
room.remove(&msg.1);
}
}
}
impl Handler<ListRooms> for WsChatServer {
type Result = MessageResult<ListRooms>;
fn handle(&mut self, _: ListRooms, _ctx: &mut Self::Context) -> Self::Result {
MessageResult(self.rooms.keys().cloned().collect())
}
}
impl Handler<SendMessage> for WsChatServer {
type Result = ();
fn handle(&mut self, msg: SendMessage, _ctx: &mut Self::Context) {
let SendMessage(room_name, id, msg) = msg;
self.send_chat_message(&room_name, &msg, id);
}
}
impl SystemService for WsChatServer {}
impl Supervised for WsChatServer {}