rust/hedgewars-server/src/handlers.rs
changeset 15520 fd3a20e9d095
parent 15519 b3157d218ae2
child 15522 4a0b06b03199
equal deleted inserted replaced
15519:b3157d218ae2 15520:fd3a20e9d095
    10     inanteroom::LoginResult,
    10     inanteroom::LoginResult,
    11     strings::*,
    11     strings::*,
    12 };
    12 };
    13 use crate::{
    13 use crate::{
    14     core::{
    14     core::{
       
    15         anteroom::HwAnteroom,
    15         room::RoomSave,
    16         room::RoomSave,
    16         server::HwServer,
    17         server::HwServer,
    17         types::{ClientId, GameCfg, Replay, RoomId, TeamInfo},
    18         types::{ClientId, GameCfg, Replay, RoomId, TeamInfo},
    18     },
    19     },
    19     protocol::messages::{
    20     protocol::messages::{
    75                         convert(*lo) == byte & 0x0f && convert(*hi) == (byte & 0xf0) >> 4
    76                         convert(*lo) == byte & 0x0f && convert(*hi) == (byte & 0xf0) >> 4
    76                     } else {
    77                     } else {
    77                         unreachable!()
    78                         unreachable!()
    78                     }
    79                     }
    79                 })
    80                 })
       
    81         }
       
    82     }
       
    83 }
       
    84 
       
    85 pub struct ServerState {
       
    86     pub server: HwServer,
       
    87     pub anteroom: HwAnteroom,
       
    88 }
       
    89 
       
    90 impl ServerState {
       
    91     pub fn new(clients_limit: usize, rooms_limit: usize) -> Self {
       
    92         Self {
       
    93             server: HwServer::new(clients_limit, rooms_limit),
       
    94             anteroom: HwAnteroom::new(clients_limit),
    80         }
    95         }
    81     }
    96     }
    82 }
    97 }
    83 
    98 
    84 #[derive(Debug)]
    99 #[derive(Debug)]
   234         }
   249         }
   235     }
   250     }
   236 }
   251 }
   237 
   252 
   238 pub fn handle(
   253 pub fn handle(
   239     server: &mut HwServer,
   254     state: &mut ServerState,
   240     client_id: ClientId,
   255     client_id: ClientId,
   241     response: &mut Response,
   256     response: &mut Response,
   242     message: HwProtocolMessage,
   257     message: HwProtocolMessage,
   243 ) {
   258 ) {
   244     match message {
   259     match message {
   245         HwProtocolMessage::Ping => response.add(Pong.send_self()),
   260         HwProtocolMessage::Ping => response.add(Pong.send_self()),
   246         HwProtocolMessage::Pong => (),
   261         HwProtocolMessage::Pong => (),
   247         _ => {
   262         _ => {
   248             if server.anteroom.clients.contains(client_id) {
   263             if state.anteroom.clients.contains(client_id) {
   249                 match inanteroom::handle(server, client_id, response, message) {
   264                 match inanteroom::handle(state, client_id, response, message) {
   250                     LoginResult::Unchanged => (),
   265                     LoginResult::Unchanged => (),
   251                     LoginResult::Complete => {
   266                     LoginResult::Complete => {
   252                         if let Some(client) = server.anteroom.remove_client(client_id) {
   267                         if let Some(client) = state.anteroom.remove_client(client_id) {
   253                             server.add_client(client_id, client);
   268                             state.server.add_client(client_id, client);
   254                             common::get_lobby_join_data(server, response);
   269                             common::get_lobby_join_data(&state.server, response);
   255                         }
   270                         }
   256                     }
   271                     }
   257                     LoginResult::Exit => {
   272                     LoginResult::Exit => {
   258                         server.anteroom.remove_client(client_id);
   273                         state.anteroom.remove_client(client_id);
   259                         response.remove_client(client_id);
   274                         response.remove_client(client_id);
   260                     }
   275                     }
   261                 }
   276                 }
   262             } else if server.has_client(client_id) {
   277             } else if state.server.has_client(client_id) {
   263                 match message {
   278                 match message {
   264                     HwProtocolMessage::Quit(Some(msg)) => {
   279                     HwProtocolMessage::Quit(Some(msg)) => {
   265                         common::remove_client(server, response, "User quit: ".to_string() + &msg);
   280                         common::remove_client(
       
   281                             &mut state.server,
       
   282                             response,
       
   283                             "User quit: ".to_string() + &msg,
       
   284                         );
   266                     }
   285                     }
   267                     HwProtocolMessage::Quit(None) => {
   286                     HwProtocolMessage::Quit(None) => {
   268                         common::remove_client(server, response, "User quit".to_string());
   287                         common::remove_client(&mut state.server, response, "User quit".to_string());
   269                     }
   288                     }
   270                     HwProtocolMessage::Info(nick) => {
   289                     HwProtocolMessage::Info(nick) => {
   271                         if let Some(client) = server.find_client(&nick) {
   290                         if let Some(client) = state.server.find_client(&nick) {
   272                             let admin_sign = if client.is_admin() { "@" } else { "" };
   291                             let admin_sign = if client.is_admin() { "@" } else { "" };
   273                             let master_sign = if client.is_master() { "+" } else { "" };
   292                             let master_sign = if client.is_master() { "+" } else { "" };
   274                             let room_info = match client.room_id {
   293                             let room_info = match client.room_id {
   275                                 Some(room_id) => {
   294                                 Some(room_id) => {
   276                                     let room = server.room(room_id);
   295                                     let room = state.server.room(room_id);
   277                                     let status = match room.game_info {
   296                                     let status = match room.game_info {
   278                                         Some(_) if client.teams_in_game == 0 => "(spectating)",
   297                                         Some(_) if client.teams_in_game == 0 => "(spectating)",
   279                                         Some(_) => "(playing)",
   298                                         Some(_) => "(playing)",
   280                                         None => "",
   299                                         None => "",
   281                                     };
   300                                     };
   297                         } else {
   316                         } else {
   298                             response.add(server_chat(USER_OFFLINE.to_string()).send_self())
   317                             response.add(server_chat(USER_OFFLINE.to_string()).send_self())
   299                         }
   318                         }
   300                     }
   319                     }
   301                     HwProtocolMessage::ToggleServerRegisteredOnly => {
   320                     HwProtocolMessage::ToggleServerRegisteredOnly => {
   302                         if !server.is_admin(client_id) {
   321                         if !state.server.is_admin(client_id) {
   303                             response.warn(ACCESS_DENIED);
   322                             response.warn(ACCESS_DENIED);
   304                         } else {
   323                         } else {
   305                             server.set_is_registered_only(!server.is_registered_only());
   324                             state
   306                             let msg = if server.is_registered_only() {
   325                                 .server
       
   326                                 .set_is_registered_only(!state.server.is_registered_only());
       
   327                             let msg = if state.server.is_registered_only() {
   307                                 REGISTERED_ONLY_ENABLED
   328                                 REGISTERED_ONLY_ENABLED
   308                             } else {
   329                             } else {
   309                                 REGISTERED_ONLY_DISABLED
   330                                 REGISTERED_ONLY_DISABLED
   310                             };
   331                             };
   311                             response.add(server_chat(msg.to_string()).send_all());
   332                             response.add(server_chat(msg.to_string()).send_all());
   312                         }
   333                         }
   313                     }
   334                     }
   314                     HwProtocolMessage::Global(msg) => {
   335                     HwProtocolMessage::Global(msg) => {
   315                         if !server.is_admin(client_id) {
   336                         if !state.server.is_admin(client_id) {
   316                             response.warn(ACCESS_DENIED);
   337                             response.warn(ACCESS_DENIED);
   317                         } else {
   338                         } else {
   318                             response.add(global_chat(msg).send_all())
   339                             response.add(global_chat(msg).send_all())
   319                         }
   340                         }
   320                     }
   341                     }
   321                     HwProtocolMessage::SuperPower => {
   342                     HwProtocolMessage::SuperPower => {
   322                         if server.enable_super_power(client_id) {
   343                         if state.server.enable_super_power(client_id) {
   323                             response.add(server_chat(SUPER_POWER.to_string()).send_self())
   344                             response.add(server_chat(SUPER_POWER.to_string()).send_self())
   324                         } else {
   345                         } else {
   325                             response.warn(ACCESS_DENIED);
   346                             response.warn(ACCESS_DENIED);
   326                         }
   347                         }
   327                     }
   348                     }
   334                         #[cfg(not(feature = "official-server"))]
   355                         #[cfg(not(feature = "official-server"))]
   335                         {
   356                         {
   336                             response.warn(REPLAY_NOT_SUPPORTED);
   357                             response.warn(REPLAY_NOT_SUPPORTED);
   337                         }
   358                         }
   338                     }
   359                     }
   339                     _ => match server.client(client_id).room_id {
   360                     _ => match state.server.client(client_id).room_id {
   340                         None => inlobby::handle(server, client_id, response, message),
   361                         None => inlobby::handle(&mut state.server, client_id, response, message),
   341                         Some(room_id) => {
   362                         Some(room_id) => {
   342                             inroom::handle(server, client_id, response, room_id, message)
   363                             inroom::handle(&mut state.server, client_id, response, room_id, message)
   343                         }
   364                         }
   344                     },
   365                     },
   345                 }
   366                 }
   346             }
   367             }
   347         }
   368         }
   348     }
   369     }
   349 }
   370 }
   350 
   371 
   351 pub fn handle_client_accept(
   372 pub fn handle_client_accept(
   352     server: &mut HwServer,
   373     state: &mut ServerState,
   353     client_id: ClientId,
   374     client_id: ClientId,
   354     response: &mut Response,
   375     response: &mut Response,
   355     addr: [u8; 4],
   376     addr: [u8; 4],
   356     is_local: bool,
   377     is_local: bool,
   357 ) {
   378 ) {
   358     let ban_reason = Some(addr)
   379     let ban_reason = Some(addr)
   359         .filter(|_| !is_local)
   380         .filter(|_| !is_local)
   360         .and_then(|a| server.anteroom.find_ip_ban(a));
   381         .and_then(|a| state.anteroom.find_ip_ban(a));
   361     if let Some(reason) = ban_reason {
   382     if let Some(reason) = ban_reason {
   362         response.add(HwServerMessage::Bye(reason).send_self());
   383         response.add(HwServerMessage::Bye(reason).send_self());
   363         response.remove_client(client_id);
   384         response.remove_client(client_id);
   364     } else {
   385     } else {
   365         let mut salt = [0u8; 18];
   386         let mut salt = [0u8; 18];
   366         thread_rng().fill_bytes(&mut salt);
   387         thread_rng().fill_bytes(&mut salt);
   367 
   388 
   368         server
   389         state
   369             .anteroom
   390             .anteroom
   370             .add_client(client_id, encode(&salt), is_local);
   391             .add_client(client_id, encode(&salt), is_local);
   371 
   392 
   372         response.add(HwServerMessage::Connected(utils::SERVER_VERSION).send_self());
   393         response.add(HwServerMessage::Connected(utils::SERVER_VERSION).send_self());
   373     }
   394     }
   374 }
   395 }
   375 
   396 
   376 pub fn handle_client_loss(server: &mut HwServer, client_id: ClientId, response: &mut Response) {
   397 pub fn handle_client_loss(state: &mut ServerState, client_id: ClientId, response: &mut Response) {
   377     if server.anteroom.remove_client(client_id).is_none() {
   398     if state.anteroom.remove_client(client_id).is_none() {
   378         common::remove_client(server, response, "Connection reset".to_string());
   399         common::remove_client(&mut state.server, response, "Connection reset".to_string());
   379     }
   400     }
   380 }
   401 }
   381 
   402 
   382 pub fn handle_io_result(
   403 pub fn handle_io_result(
   383     server: &mut HwServer,
   404     state: &mut ServerState,
   384     client_id: ClientId,
   405     client_id: ClientId,
   385     response: &mut Response,
   406     response: &mut Response,
   386     io_result: IoResult,
   407     io_result: IoResult,
   387 ) {
   408 ) {
   388     match io_result {
   409     match io_result {
   389         IoResult::AccountRegistered(is_registered) => {
   410         IoResult::AccountRegistered(is_registered) => {
   390             if !is_registered && server.is_registered_only() {
   411             if !is_registered && state.server.is_registered_only() {
   391                 response.add(Bye(REGISTRATION_REQUIRED.to_string()).send_self());
   412                 response.add(Bye(REGISTRATION_REQUIRED.to_string()).send_self());
   392                 response.remove_client(client_id);
   413                 response.remove_client(client_id);
   393             } else if is_registered {
   414             } else if is_registered {
   394                 let salt = server.anteroom.clients[client_id].server_salt.clone();
   415                 let salt = state.anteroom.clients[client_id].server_salt.clone();
   395                 response.add(AskPassword(salt).send_self());
   416                 response.add(AskPassword(salt).send_self());
   396             } else if let Some(client) = server.anteroom.remove_client(client_id) {
   417             } else if let Some(client) = state.anteroom.remove_client(client_id) {
   397                 server.add_client(client_id, client);
   418                 state.server.add_client(client_id, client);
   398                 common::get_lobby_join_data(server, response);
   419                 common::get_lobby_join_data(&state.server, response);
   399             }
   420             }
   400         }
   421         }
   401         IoResult::Account(Some(info)) => {
   422         IoResult::Account(Some(info)) => {
   402             response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self());
   423             response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self());
   403             if let Some(mut client) = server.anteroom.remove_client(client_id) {
   424             if let Some(mut client) = state.anteroom.remove_client(client_id) {
   404                 client.is_registered = info.is_registered;
   425                 client.is_registered = info.is_registered;
   405                 client.is_admin = info.is_admin;
   426                 client.is_admin = info.is_admin;
   406                 client.is_contributor = info.is_contributor;
   427                 client.is_contributor = info.is_contributor;
   407                 server.add_client(client_id, client);
   428                 state.server.add_client(client_id, client);
   408                 common::get_lobby_join_data(server, response);
   429                 common::get_lobby_join_data(&state.server, response);
   409             }
   430             }
   410         }
   431         }
   411         IoResult::Account(None) => {
   432         IoResult::Account(None) => {
   412             response.error(AUTHENTICATION_FAILED);
   433             response.error(AUTHENTICATION_FAILED);
   413             response.remove_client(client_id);
   434             response.remove_client(client_id);
   414         }
   435         }
   415         IoResult::Replay(Some(replay)) => {
   436         IoResult::Replay(Some(replay)) => {
   416             let client = server.client(client_id);
   437             let client = state.server.client(client_id);
   417             let protocol = client.protocol_number;
   438             let protocol = client.protocol_number;
   418             let start_msg = if protocol < 58 {
   439             let start_msg = if protocol < 58 {
   419                 RoomJoined(vec![client.nick.clone()])
   440                 RoomJoined(vec![client.nick.clone()])
   420             } else {
   441             } else {
   421                 ReplayStart
   442                 ReplayStart
   439         }
   460         }
   440         IoResult::SaveRoom(_, false) => {
   461         IoResult::SaveRoom(_, false) => {
   441             response.warn(ROOM_CONFIG_SAVE_FAILED);
   462             response.warn(ROOM_CONFIG_SAVE_FAILED);
   442         }
   463         }
   443         IoResult::LoadRoom(room_id, Some(contents)) => {
   464         IoResult::LoadRoom(room_id, Some(contents)) => {
   444             if let Some(ref mut room) = server.rooms.get_mut(room_id) {
   465             if let Some(ref mut room) = state.server.rooms.get_mut(room_id) {
   445                 match room.set_saves(&contents) {
   466                 match room.set_saves(&contents) {
   446                     Ok(_) => response.add(server_chat(ROOM_CONFIG_LOADED.to_string()).send_self()),
   467                     Ok(_) => response.add(server_chat(ROOM_CONFIG_LOADED.to_string()).send_self()),
   447                     Err(e) => {
   468                     Err(e) => {
   448                         warn!("Error while deserializing the room configs: {}", e);
   469                         warn!("Error while deserializing the room configs: {}", e);
   449                         response.warn(ROOM_CONFIG_DESERIALIZE_FAILED);
   470                         response.warn(ROOM_CONFIG_DESERIALIZE_FAILED);