server.rs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. use std::collections::BTreeMap;
  2. use std::collections::BTreeSet;
  3. use std::time::{Duration, Instant};
  4. use std::sync::{Mutex, RwLock, Arc};
  5. use actix::dev::{MessageResponse, ResponseChannel};
  6. use actix::prelude::*;
  7. use actix_web::{web, Error, HttpRequest, HttpResponse};
  8. use actix_web_actors::ws;
  9. use crate::game;
  10. use crate::websocket;
  11. use crate::websocket::*;
  12. use crate::datasource;
  13. use crate::server::gamelobby::{GameLobby};
  14. use crate::server::messages::*;
  15. const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(5);
  16. const CLIENT_TIMEOUT: Duration = Duration::from_secs(10);
  17. pub async fn ws_initiate(server: web::Data<Addr<Server>>,
  18. r: HttpRequest,
  19. stream: web::Payload) -> Result<HttpResponse, Error> {
  20. println!("{:?}", r);
  21. let res = ws::start(GameConnection::new(server.as_ref().clone()), &r, stream)?;
  22. println!("{:?}", res);
  23. Ok(res)
  24. }
  25. pub struct Server {
  26. pub lobbies: BTreeMap<String, Addr<GameLobby>>,
  27. pub default_data: Arc<dyn datasource::DataSource<String>>
  28. }
  29. impl Actor for Server {
  30. type Context = Context<Self>;
  31. fn started(&mut self, ctx: &mut Self::Context) {
  32. }
  33. }
  34. impl Handler<JoinRequest> for Server {
  35. type Result = Answer;
  36. fn handle(&mut self, jr: JoinRequest, ctx: &mut Self::Context) -> Self::Result {
  37. let mb_lobby = self.lobbies.get(&jr.lobby_id);
  38. match mb_lobby {
  39. Some(lobby) => {
  40. let _sent = lobby.do_send(jr);
  41. Answer::LobbyJoined(lobby.clone())
  42. },
  43. None => {
  44. jr.p.do_send(NoSuchLobby(jr.lobby_id));
  45. Answer::NoSuchLobby
  46. }
  47. }
  48. }
  49. }
  50. impl Handler<CreateLobbyRequest> for Server {
  51. type Result = Answer;
  52. fn handle(&mut self, clr: CreateLobbyRequest, ctx: &mut Self::Context) -> Self::Result {
  53. let existing_lobby = self.lobbies.get(&clr.lobby_id);
  54. match existing_lobby {
  55. Some(_) => Answer::LobbyAlreadyExists,
  56. None => {
  57. let lobby = GameLobby::new(clr.lobby_id.clone(), self.default_data.clone());
  58. let lobby_addr = lobby.start();
  59. self.lobbies.insert(clr.lobby_id.clone(), lobby_addr.clone());
  60. Answer::LobbyCreated(lobby_addr)
  61. }
  62. }
  63. }
  64. }
  65. ///
  66. /// connection to one single client
  67. ///
  68. pub struct GameConnection {
  69. heartbeat: Instant,
  70. nick: Option<String>,
  71. game_id: Option<String>,
  72. server: Addr<Server>,
  73. game_lobby: Option<Addr<GameLobby>>
  74. }
  75. impl Actor for GameConnection {
  76. type Context = ws::WebsocketContext<Self>;
  77. fn started(&mut self, ctx: &mut Self::Context) {
  78. self.initiate_heartbeat(ctx);
  79. }
  80. }
  81. impl Handler<LobbyJoined> for GameConnection {
  82. type Result = ();
  83. fn handle(&mut self, gu: LobbyJoined, ctx: &mut Self::Context) -> Self::Result {
  84. self.game_lobby = Some(gu.0);
  85. }
  86. }
  87. impl Handler<NoSuchLobby> for GameConnection {
  88. type Result = ();
  89. fn handle(&mut self, nsl: NoSuchLobby, ctx: &mut Self::Context) -> Self::Result {
  90. self.send_message(&UpdateMessage::GameNotFound{ game_id: nsl.0 }, ctx);
  91. }
  92. }
  93. impl Handler<GameUpdate> for GameConnection {
  94. type Result = ();
  95. fn handle(&mut self, gu: GameUpdate, ctx: &mut Self::Context) -> Self::Result {
  96. self.send_message(&UpdateMessage::GameState(gu.game_data), ctx);
  97. }
  98. }
  99. impl Handler<ResultMsg> for GameConnection {
  100. type Result = ();
  101. fn handle(&mut self, rm: ResultMsg, ctx: &mut Self::Context) -> Self::Result {
  102. self.send_message(&UpdateMessage::RoundResult(rm.results), ctx);
  103. }
  104. }
  105. impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for GameConnection {
  106. fn handle(
  107. &mut self,
  108. msg: Result<ws::Message, ws::ProtocolError>,
  109. ctx: &mut Self::Context,
  110. ) {
  111. match msg {
  112. Ok(ws::Message::Ping(msg)) => {
  113. self.heartbeat = Instant::now();
  114. ctx.pong(&msg);
  115. }
  116. Ok(ws::Message::Pong(_)) => {
  117. self.heartbeat = Instant::now();
  118. }
  119. Ok(ws::Message::Text(text)) => {
  120. println!("hmmm: {:?}", text);
  121. self.received_message(&text, ctx);
  122. },
  123. Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
  124. Ok(ws::Message::Close(reason)) => {
  125. ctx.close(reason);
  126. ctx.stop();
  127. }
  128. _ => ctx.stop(),
  129. }
  130. }
  131. }
  132. impl GameConnection {
  133. pub fn new(server_addr: Addr<Server>) -> Self {
  134. GameConnection {
  135. heartbeat: Instant::now(),
  136. nick: None,
  137. game_id: None,
  138. server: server_addr,
  139. game_lobby: None
  140. }
  141. }
  142. pub fn initiate_heartbeat(&self, ctx: &mut <Self as Actor>::Context) {
  143. ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
  144. if Instant::now().duration_since(act.heartbeat) > CLIENT_TIMEOUT {
  145. //println!("Websocket Client heartbeat failed, disconnecting!");
  146. ctx.stop();
  147. return;
  148. }
  149. ctx.ping(b"");
  150. });
  151. }
  152. pub fn send_message(&self, m: &UpdateMessage, ctx: &mut <Self as Actor>::Context) {
  153. let txt = serde_json::to_string(m).unwrap();
  154. println!("{:?}", txt);
  155. ctx.text(txt);
  156. }
  157. pub fn received_message(&mut self, text: &str, ctx: &mut <Self as Actor>::Context) {
  158. let parsed: Result<ClientMessage, _> = serde_json::from_str(text);
  159. if let Ok(msg) = parsed {
  160. match msg {
  161. ClientMessage::CreateGame{game_id, nick} => {
  162. self.game_id = Some(game_id.clone());
  163. self.nick = Some(nick);
  164. self.server.do_send(CreateLobbyRequest{
  165. lobby_id: game_id.clone(),
  166. p: ctx.address()
  167. });
  168. },
  169. ClientMessage::Join{game_id, nick} => {
  170. self.server.do_send(JoinRequest{ lobby_id: game_id.clone(), nick: nick.clone(), p: ctx.address() });
  171. self.game_id = Some(game_id.clone());
  172. self.nick = Some(nick);
  173. },
  174. ClientMessage::Ready => {
  175. if let Some(lobby) = &self.game_lobby {
  176. if let Some(nick) = &self.nick {
  177. lobby.do_send(ReadyMsg(nick.clone()));
  178. }
  179. }
  180. },
  181. ClientMessage::SubmitWord{ word } => {
  182. if let Some(lobby) = &self.game_lobby {
  183. if let Some(nick) = &self.nick {
  184. lobby.do_send(SubmitWordMsg{ word: word, nick: nick.clone() });
  185. }
  186. }
  187. },
  188. ClientMessage::SubmitGuess{ guesses } => {
  189. if let Some(lobby) = &self.game_lobby {
  190. if let Some(nick) = &self.nick {
  191. lobby.do_send(SubmitGuessMsg{ guesses: guesses, nick: nick.clone() });
  192. }
  193. }
  194. }
  195. }
  196. }
  197. else {
  198. println!("error parsing json");
  199. }
  200. }
  201. }