server.rs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. use std::collections::BTreeMap;
  2. use std::time::{Duration, Instant};
  3. use std::sync::{Arc};
  4. use actix::prelude::*;
  5. use actix_web::{web, Error, HttpRequest, HttpResponse};
  6. use actix_web_actors::ws;
  7. use log::{debug, error};
  8. use crate::datasource;
  9. use crate::server::protocol::*;
  10. use crate::server::gamelobby::{GameLobby};
  11. use crate::server::messages::*;
  12. const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
  13. const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
  14. pub async fn ws_initiate(server: web::Data<Addr<Server>>,
  15. r: HttpRequest,
  16. stream: web::Payload) -> Result<HttpResponse, Error> {
  17. let res = ws::start(GameConnection::new(server.as_ref().clone()), &r, stream)?;
  18. Ok(res)
  19. }
  20. pub struct Server {
  21. pub lobbies: BTreeMap<String, Addr<GameLobby>>,
  22. pub default_data: Arc<dyn datasource::DataSource<String>>
  23. }
  24. impl Actor for Server {
  25. type Context = Context<Self>;
  26. fn started(&mut self, _ctx: &mut Self::Context) {
  27. }
  28. }
  29. impl Handler<JoinRequest> for Server {
  30. type Result = ();
  31. fn handle(&mut self, jr: JoinRequest, _ctx: &mut Self::Context) -> Self::Result {
  32. let mb_lobby = self.lobbies.get(&jr.lobby_id);
  33. match mb_lobby {
  34. Some(lobby) => {
  35. let _sent = lobby.do_send(jr);
  36. },
  37. None => {
  38. jr.p.do_send(NoSuchLobby(jr.lobby_id));
  39. }
  40. }
  41. }
  42. }
  43. impl Handler<CreateLobbyRequest> for Server {
  44. type Result = ();
  45. fn handle(&mut self, clr: CreateLobbyRequest, ctx: &mut Self::Context) -> Self::Result {
  46. let existing_lobby = self.lobbies.get(&clr.lobby_id);
  47. match existing_lobby {
  48. Some(_) => {},
  49. None => {
  50. let lobby = GameLobby::new(clr.lobby_id.clone(), self.default_data.clone(), ctx.address());
  51. let lobby_addr = lobby.start();
  52. self.lobbies.insert(clr.lobby_id.clone(), lobby_addr.clone());
  53. self.handle(JoinRequest {
  54. lobby_id: clr.lobby_id,
  55. nick: clr.nick,
  56. p: clr.p
  57. }, ctx);
  58. }
  59. }
  60. }
  61. }
  62. impl Handler<LobbyFinished> for Server {
  63. type Result = ();
  64. fn handle(&mut self, lf: LobbyFinished, _ctx: &mut Self::Context) -> Self::Result {
  65. self.lobbies.remove(&lf.0);
  66. }
  67. }
  68. ///
  69. /// connection to one single client
  70. ///
  71. pub struct GameConnection {
  72. heartbeat: Instant,
  73. nick: Option<String>,
  74. game_id: Option<String>,
  75. server: Addr<Server>,
  76. game_lobby: Option<Addr<GameLobby>>
  77. }
  78. impl Actor for GameConnection {
  79. type Context = ws::WebsocketContext<Self>;
  80. fn started(&mut self, ctx: &mut Self::Context) {
  81. self.initiate_heartbeat(ctx);
  82. }
  83. }
  84. impl Handler<LobbyJoined> for GameConnection {
  85. type Result = ();
  86. fn handle(&mut self, gu: LobbyJoined, _ctx: &mut Self::Context) -> Self::Result {
  87. self.game_lobby = Some(gu.lobby);
  88. self.game_id = Some(gu.game_id);
  89. self.nick = Some(gu.nick);
  90. }
  91. }
  92. impl Handler<NoSuchLobby> for GameConnection {
  93. type Result = ();
  94. fn handle(&mut self, nsl: NoSuchLobby, ctx: &mut Self::Context) -> Self::Result {
  95. self.send_message(&UpdateMessage::GameNotFound{ game_id: nsl.0 }, ctx);
  96. }
  97. }
  98. impl Handler<GameAlreadyStartedMsg> for GameConnection {
  99. type Result = ();
  100. fn handle(&mut self, gas: GameAlreadyStartedMsg, ctx: &mut Self::Context) -> Self::Result {
  101. self.send_message(&UpdateMessage::GameAlreadyStarted{ game_id: gas.0 }, ctx);
  102. }
  103. }
  104. impl Handler<NickAlreadyExistsMsg> for GameConnection {
  105. type Result = ();
  106. fn handle(&mut self, naem: NickAlreadyExistsMsg, ctx: &mut Self::Context) -> Self::Result {
  107. self.send_message(&UpdateMessage::NickAlreadyExists{ game_id: naem.game_id, nick: naem.nick }, ctx);
  108. }
  109. }
  110. impl Handler<GameUpdate> for GameConnection {
  111. type Result = ();
  112. fn handle(&mut self, gu: GameUpdate, ctx: &mut Self::Context) -> Self::Result {
  113. self.send_message(&UpdateMessage::GameState(gu.game_data), ctx);
  114. }
  115. }
  116. impl Handler<PlayerListUpdate> for GameConnection {
  117. type Result = ();
  118. fn handle(&mut self, plu: PlayerListUpdate, ctx: &mut Self::Context) -> Self::Result {
  119. self.send_message(&UpdateMessage::PlayerList(plu.player_list), ctx);
  120. }
  121. }
  122. impl Handler<ResultMsg> for GameConnection {
  123. type Result = ();
  124. fn handle(&mut self, rm: ResultMsg, ctx: &mut Self::Context) -> Self::Result {
  125. self.send_message(&UpdateMessage::RoundResult(rm.results), ctx);
  126. }
  127. }
  128. impl Handler<StopMsg> for GameConnection {
  129. type Result = ();
  130. fn handle(&mut self, _sm: StopMsg, ctx: &mut Self::Context) -> Self::Result {
  131. self.leave_lobby(ctx);
  132. ctx.stop();
  133. }
  134. }
  135. impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for GameConnection {
  136. fn handle(
  137. &mut self,
  138. msg: Result<ws::Message, ws::ProtocolError>,
  139. ctx: &mut Self::Context,
  140. ) {
  141. match msg {
  142. Ok(ws::Message::Ping(msg)) => {
  143. self.heartbeat = Instant::now();
  144. ctx.pong(&msg);
  145. }
  146. Ok(ws::Message::Pong(_)) => {
  147. self.heartbeat = Instant::now();
  148. }
  149. Ok(ws::Message::Text(text)) => {
  150. debug!("received client message: {}", text);
  151. self.received_message(&text, ctx);
  152. },
  153. Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
  154. Ok(ws::Message::Close(reason)) => {
  155. self.leave_lobby(ctx);
  156. ctx.close(reason);
  157. ctx.stop();
  158. }
  159. _ => ctx.stop(),
  160. }
  161. }
  162. }
  163. impl GameConnection {
  164. pub fn new(server_addr: Addr<Server>) -> Self {
  165. GameConnection {
  166. heartbeat: Instant::now(),
  167. nick: None,
  168. game_id: None,
  169. server: server_addr,
  170. game_lobby: None
  171. }
  172. }
  173. pub fn initiate_heartbeat(&self, ctx: &mut <Self as Actor>::Context) {
  174. ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
  175. if Instant::now().duration_since(act.heartbeat) > CLIENT_TIMEOUT {
  176. ctx.address().do_send(StopMsg);
  177. return;
  178. }
  179. ctx.ping(b"");
  180. });
  181. }
  182. pub fn send_message(&self, m: &UpdateMessage, ctx: &mut <Self as Actor>::Context) {
  183. let txt = serde_json::to_string(m).unwrap();
  184. debug!("sending message to client {}", txt);
  185. ctx.text(txt);
  186. }
  187. pub fn received_message(&mut self, text: &str, ctx: &mut <Self as Actor>::Context) {
  188. let parsed: Result<ClientMessage, _> = serde_json::from_str(text);
  189. if let Ok(msg) = parsed {
  190. match msg {
  191. ClientMessage::CreateGame{game_id, nick} => {
  192. if nick != "" && game_id != "" {
  193. self.game_id = Some(game_id.clone());
  194. self.nick = Some(nick.clone());
  195. self.server.do_send(CreateLobbyRequest {
  196. lobby_id: game_id.clone(),
  197. nick: nick.clone(),
  198. p: ctx.address()
  199. });
  200. }
  201. },
  202. ClientMessage::Join{game_id, nick} => {
  203. if nick != "" {
  204. self.server.do_send(JoinRequest{ lobby_id: game_id.clone(), nick: nick.clone(), p: ctx.address() });
  205. self.game_id = Some(game_id.clone());
  206. self.nick = Some(nick);
  207. }
  208. },
  209. ClientMessage::LeaveLobby => {
  210. self.leave_lobby(ctx);
  211. },
  212. ClientMessage::Ready => {
  213. if let Some(lobby) = &self.game_lobby {
  214. if let Some(nick) = &self.nick {
  215. lobby.do_send(ReadyMsg(nick.clone()));
  216. }
  217. }
  218. },
  219. ClientMessage::Unready => {
  220. if let Some(lobby) = &self.game_lobby {
  221. if let Some(nick) = &self.nick {
  222. lobby.do_send(UnreadyMsg(nick.clone()));
  223. }
  224. }
  225. },
  226. ClientMessage::Reveal => {
  227. if let Some(lobby) = &self.game_lobby {
  228. if let Some(nick) = &self.nick {
  229. lobby.do_send(RevealMsg(nick.clone()));
  230. }
  231. }
  232. },
  233. ClientMessage::SubmitWord{ word } => {
  234. if let Some(lobby) = &self.game_lobby {
  235. if let Some(nick) = &self.nick {
  236. lobby.do_send(SubmitWordMsg{ word: word, nick: nick.clone() });
  237. }
  238. }
  239. },
  240. ClientMessage::SubmitGuess{ guesses } => {
  241. if let Some(lobby) = &self.game_lobby {
  242. if let Some(nick) = &self.nick {
  243. lobby.do_send(SubmitGuessMsg{ guesses: guesses, nick: nick.clone() });
  244. }
  245. }
  246. }
  247. }
  248. }
  249. else {
  250. error!("error parsing json: {}", text);
  251. }
  252. }
  253. pub fn leave_lobby(&mut self, ctx: &mut <Self as Actor>::Context) {
  254. if let Some(lobby) = &self.game_lobby {
  255. if let Some(nick) = &self.nick {
  256. lobby.do_send(LeaveMsg(nick.clone()));
  257. self.send_message(&UpdateMessage::LeftLobby{ nick: nick.clone() }, ctx);
  258. }
  259. }
  260. }
  261. }