summaryrefslogtreecommitdiff
path: root/src/rooms.rs
blob: c8199d17e58a5267244e437e106ed5e201f4d417 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
}