server.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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 = ();
  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. },
  42. None => {
  43. jr.p.do_send(NoSuchLobby(jr.lobby_id));
  44. }
  45. }
  46. }
  47. }
  48. impl Handler<CreateLobbyRequest> for Server {
  49. type Result = ();
  50. fn handle(&mut self, clr: CreateLobbyRequest, ctx: &mut Self::Context) -> Self::Result {
  51. let existing_lobby = self.lobbies.get(&clr.lobby_id);
  52. match existing_lobby {
  53. Some(_) => {},
  54. None => {
  55. let lobby = GameLobby::new(clr.lobby_id.clone(), self.default_data.clone(), ctx.address());
  56. let lobby_addr = lobby.start();
  57. self.lobbies.insert(clr.lobby_id.clone(), lobby_addr.clone());
  58. self.handle(JoinRequest {
  59. lobby_id: clr.lobby_id,
  60. nick: clr.nick,
  61. p: clr.p
  62. }, ctx);
  63. }
  64. }
  65. }
  66. }
  67. impl Handler<LobbyFinished> for Server {
  68. type Result = ();
  69. fn handle(&mut self, lf: LobbyFinished, ctx: &mut Self::Context) -> Self::Result {
  70. self.lobbies.remove(&lf.0);
  71. }
  72. }
  73. ///
  74. /// connection to one single client
  75. ///
  76. pub struct GameConnection {
  77. heartbeat: Instant,
  78. nick: Option<String>,
  79. game_id: Option<String>,
  80. server: Addr<Server>,
  81. game_lobby: Option<Addr<GameLobby>>
  82. }
  83. impl Actor for GameConnection {
  84. type Context = ws::WebsocketContext<Self>;
  85. fn started(&mut self, ctx: &mut Self::Context) {
  86. self.initiate_heartbeat(ctx);
  87. }
  88. }
  89. impl Handler<LobbyJoined> for GameConnection {
  90. type Result = ();
  91. fn handle(&mut self, gu: LobbyJoined, ctx: &mut Self::Context) -> Self::Result {
  92. self.game_lobby = Some(gu.lobby);
  93. self.game_id = Some(gu.game_id);
  94. self.nick = Some(gu.nick);
  95. }
  96. }
  97. impl Handler<NoSuchLobby> for GameConnection {
  98. type Result = ();
  99. fn handle(&mut self, nsl: NoSuchLobby, ctx: &mut Self::Context) -> Self::Result {
  100. self.send_message(&UpdateMessage::GameNotFound{ game_id: nsl.0 }, ctx);
  101. }
  102. }
  103. impl Handler<GameUpdate> for GameConnection {
  104. type Result = ();
  105. fn handle(&mut self, gu: GameUpdate, ctx: &mut Self::Context) -> Self::Result {
  106. self.send_message(&UpdateMessage::GameState(gu.game_data), ctx);
  107. }
  108. }
  109. impl Handler<ResultMsg> for GameConnection {
  110. type Result = ();
  111. fn handle(&mut self, rm: ResultMsg, ctx: &mut Self::Context) -> Self::Result {
  112. self.send_message(&UpdateMessage::RoundResult(rm.results), ctx);
  113. }
  114. }
  115. impl Handler<StopMsg> for GameConnection {
  116. type Result = ();
  117. fn handle(&mut self, _sm: StopMsg, ctx: &mut Self::Context) -> Self::Result {
  118. self.leave_lobby(ctx);
  119. ctx.stop();
  120. }
  121. }
  122. impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for GameConnection {
  123. fn handle(
  124. &mut self,
  125. msg: Result<ws::Message, ws::ProtocolError>,
  126. ctx: &mut Self::Context,
  127. ) {
  128. match msg {
  129. Ok(ws::Message::Ping(msg)) => {
  130. self.heartbeat = Instant::now();
  131. ctx.pong(&msg);
  132. }
  133. Ok(ws::Message::Pong(_)) => {
  134. self.heartbeat = Instant::now();
  135. }
  136. Ok(ws::Message::Text(text)) => {
  137. println!("hmmm: {:?}", text);
  138. self.received_message(&text, ctx);
  139. },
  140. Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
  141. Ok(ws::Message::Close(reason)) => {
  142. self.leave_lobby(ctx);
  143. ctx.close(reason);
  144. ctx.stop();
  145. }
  146. _ => ctx.stop(),
  147. }
  148. }
  149. }
  150. impl GameConnection {
  151. pub fn new(server_addr: Addr<Server>) -> Self {
  152. GameConnection {
  153. heartbeat: Instant::now(),
  154. nick: None,
  155. game_id: None,
  156. server: server_addr,
  157. game_lobby: None
  158. }
  159. }
  160. pub fn initiate_heartbeat(&self, ctx: &mut <Self as Actor>::Context) {
  161. ctx.run_interval(HEARTBEAT_INTERVAL, |act, ctx| {
  162. if Instant::now().duration_since(act.heartbeat) > CLIENT_TIMEOUT {
  163. ctx.address().do_send(StopMsg);
  164. return;
  165. }
  166. ctx.ping(b"");
  167. });
  168. }
  169. pub fn send_message(&self, m: &UpdateMessage, ctx: &mut <Self as Actor>::Context) {
  170. let txt = serde_json::to_string(m).unwrap();
  171. println!("{:?}", txt);
  172. ctx.text(txt);
  173. }
  174. pub fn received_message(&mut self, text: &str, ctx: &mut <Self as Actor>::Context) {
  175. let parsed: Result<ClientMessage, _> = serde_json::from_str(text);
  176. if let Ok(msg) = parsed {
  177. match msg {
  178. ClientMessage::CreateGame{game_id, nick} => {
  179. if nick != "" && game_id != "" {
  180. self.game_id = Some(game_id.clone());
  181. self.nick = Some(nick.clone());
  182. self.server.do_send(CreateLobbyRequest {
  183. lobby_id: game_id.clone(),
  184. nick: nick.clone(),
  185. p: ctx.address()
  186. });
  187. }
  188. },
  189. ClientMessage::Join{game_id, nick} => {
  190. if nick != "" {
  191. self.server.do_send(JoinRequest{ lobby_id: game_id.clone(), nick: nick.clone(), p: ctx.address() });
  192. self.game_id = Some(game_id.clone());
  193. self.nick = Some(nick);
  194. }
  195. },
  196. ClientMessage::LeaveLobby => {
  197. self.leave_lobby(ctx);
  198. },
  199. ClientMessage::Ready => {
  200. if let Some(lobby) = &self.game_lobby {
  201. if let Some(nick) = &self.nick {
  202. lobby.do_send(ReadyMsg(nick.clone()));
  203. }
  204. }
  205. },
  206. ClientMessage::SubmitWord{ word } => {
  207. if let Some(lobby) = &self.game_lobby {
  208. if let Some(nick) = &self.nick {
  209. lobby.do_send(SubmitWordMsg{ word: word, nick: nick.clone() });
  210. }
  211. }
  212. },
  213. ClientMessage::SubmitGuess{ guesses } => {
  214. if let Some(lobby) = &self.game_lobby {
  215. if let Some(nick) = &self.nick {
  216. lobby.do_send(SubmitGuessMsg{ guesses: guesses, nick: nick.clone() });
  217. }
  218. }
  219. }
  220. }
  221. }
  222. else {
  223. println!("error parsing json");
  224. }
  225. }
  226. pub fn leave_lobby(&mut self, ctx: &mut <Self as Actor>::Context) {
  227. if let Some(lobby) = &self.game_lobby {
  228. if let Some(nick) = &self.nick {
  229. lobby.do_send(LeaveMsg(nick.clone()));
  230. self.send_message(&UpdateMessage::LeftLobby{ nick: nick.clone() }, ctx);
  231. }
  232. }
  233. }
  234. }