60 lines
1.6 KiB
Rust
60 lines
1.6 KiB
Rust
|
use std::collections::HashMap;
|
||
|
|
||
|
use axum::extract::ws::WebSocket;
|
||
|
use tokio::sync::mpsc;
|
||
|
use tokio::sync::oneshot;
|
||
|
|
||
|
use super::room;
|
||
|
|
||
|
pub enum RoomServiceRequest {
|
||
|
Exists(String, oneshot::Sender<bool>),
|
||
|
Join(String, WebSocket),
|
||
|
Remove(String),
|
||
|
}
|
||
|
|
||
|
pub type RoomService = mpsc::Sender<RoomServiceRequest>;
|
||
|
|
||
|
type RoomMap = HashMap<String, room::Room>;
|
||
|
|
||
|
async fn handle_room_server_message(rooms: &mut RoomMap, req: RoomServiceRequest, tx: RoomService) {
|
||
|
match req {
|
||
|
// check whether a given room exists
|
||
|
// the sender must provide a tokio::sync::oneshot sender to receive a response
|
||
|
RoomServiceRequest::Exists(code, reply) => {
|
||
|
reply.send(rooms.get(&code).is_some()).ok();
|
||
|
},
|
||
|
// send a websocket into the given room, starting it if it doesn't exist
|
||
|
RoomServiceRequest::Join(code, ws) => {
|
||
|
let room = match rooms.get(&code) {
|
||
|
Some(rm) => rm,
|
||
|
None => {
|
||
|
let rm = room::start_room(code.clone(), tx);
|
||
|
rooms.insert(code.clone(), rm);
|
||
|
&rooms[&code]
|
||
|
}
|
||
|
};
|
||
|
|
||
|
room::add_connection(room, ws).await;
|
||
|
},
|
||
|
// remove a room (called by the room task itself once there are no more connections to it)
|
||
|
RoomServiceRequest::Remove(code) => {
|
||
|
rooms.remove(&code);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// a task to manage a hashmap holding the room task senders
|
||
|
// returns a sender to interface with the task
|
||
|
pub fn start_room_server() -> RoomService {
|
||
|
let (tx, mut rx) = mpsc::channel::<RoomServiceRequest>(10);
|
||
|
let txret = tx.clone();
|
||
|
|
||
|
tokio::spawn(async move {
|
||
|
let mut rooms: RoomMap = HashMap::new();
|
||
|
while let Some(req) = rx.recv().await {
|
||
|
handle_room_server_message(&mut rooms, req, tx.clone()).await;
|
||
|
}
|
||
|
});
|
||
|
txret
|
||
|
}
|