diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/src/main.rs b/src/main.rs index 2f7d52c..3dd7f39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ use types::*; use tokio::sync::RwLock; const FONT_FILE: &[u8] = include_bytes!("../assets/VT323-Regular.ttf"); +const AREA_LIMIT: usize = 150*150; fn main() -> Result<(), Box<dyn Error>> { let conf = Config { @@ -32,7 +33,7 @@ fn main() -> Result<(), Box<dyn Error>> { #[tokio::main] async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { let rooms: RoomMap = Arc::new(RwLock::new(HashMap::new())); - let public_rooms = Arc::new(RwLock::new(Vec::new())); + let public_rooms = Arc::new(RwLock::new(HashMap::new())); use warp::*; let index = path::end().and(fs::file(conf.index_pg.clone())); @@ -44,8 +45,9 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { path!("rlist").and_then(move || { let pubs = pubs.clone(); async move { - Ok::<_,std::convert::Infallible>( - reply::json(&pubs.read().await.as_slice()) + let map = pubs.read().await; + Ok::<_,std::convert::Infallible>( + reply::json(&*map) ) }}) }; @@ -67,26 +69,36 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { rinfo.get("ralwayssafe1move"), rinfo.get("rlimit").and_then(|l| l.parse::<usize>().ok()), ) { + if w.get()*h.get() > AREA_LIMIT { + return Err(reject::custom(BoardTooBig)) + } let board_conf = minesweeper::BoardConf { w, h, mine_ratio: (num,denom), always_safe_first_move: asfm.is_some() }; - let name = rinfo.get("rname").map(|r| r.to_owned()).unwrap_or(format!("{w}x{h} room")); - let mut rooms = rooms.write().await; let uid = types::RoomId::new_in(&rooms); + let name = { + let n = rinfo.get("rname").map(|r| r.to_owned()).unwrap(); + if n.is_empty() { uid.to_string() } else { n } + }; let players = PlayerMap::default(); let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel(); let handle = tokio::spawn(gameloop(cmd_rx, players.clone(), board_conf)); - rooms.insert(uid.clone(), Arc::new(RwLock::new(Room { + let room_conf = RoomConf { name, - players, - peer_limit: match limit { Some(i) => i, None => usize::MAX }, + player_cap: match limit { Some(i) => i, None => usize::MAX }, public: access.is_some(), + board_conf, + }; + let new_room = Room { + conf: room_conf, + players, driver: handle, cmd_stream: cmd_tx, - board_conf, - }))); + }; if access.is_some() { - pubs.write().await.push(uid.clone()); + pubs.write().await.insert(uid.clone(), serde_json::to_string(&new_room.conf).unwrap()); } + rooms.insert(uid.clone(), Arc::new(RwLock::new(new_room))); + Ok( hyper::Response::builder() .status(hyper::StatusCode::SEE_OTHER) @@ -205,10 +217,16 @@ use warp::{ reject::{ Reject, Rejection }, reply::{ self, Reply }, http::StatusC struct BadFormData; impl Reject for BadFormData {} +#[derive(Debug)] +struct BoardTooBig; +impl Reject for BoardTooBig {} + async fn error_handler(err: Rejection) -> Result<impl Reply, std::convert::Infallible> { if err.is_not_found() { Ok(reply::with_status("No such file", StatusCode::NOT_FOUND)) } else if let Some(_e) = err.find::<BadFormData>() { Ok(reply::with_status("Bad form data", StatusCode::BAD_REQUEST)) + } else if let Some(_e) = err.find::<BoardTooBig>() { + Ok(reply::with_status("Board too big", StatusCode::BAD_REQUEST)) } else { println!("unhandled rejection: {err:?}"); Ok(reply::with_status("Server error", StatusCode::INTERNAL_SERVER_ERROR)) |