rust/hedgewars-server/src/server/core.rs
changeset 14436 06672690d71b
parent 14413 e335b3120f59
child 14478 98ef2913ec73
equal deleted inserted replaced
14435:6843c4551cde 14436:06672690d71b
       
     1 use slab;
       
     2 use crate::utils;
       
     3 use super::{
       
     4     io::HWServerIO,
       
     5     client::HWClient, room::HWRoom, actions, handlers,
       
     6     coretypes::{ClientId, RoomId},
       
     7     actions::{Destination, PendingMessage}
       
     8 };
       
     9 use crate::protocol::messages::*;
       
    10 use rand::{RngCore, thread_rng};
       
    11 use base64::{encode};
       
    12 use log::*;
       
    13 
       
    14 type Slab<T> = slab::Slab<T>;
       
    15 
       
    16 pub struct HWServer {
       
    17     pub clients: Slab<HWClient>,
       
    18     pub rooms: Slab<HWRoom>,
       
    19     pub lobby_id: RoomId,
       
    20     pub output: Vec<(Vec<ClientId>, HWServerMessage)>,
       
    21     pub removed_clients: Vec<ClientId>,
       
    22     pub io: Box<dyn HWServerIO>
       
    23 }
       
    24 
       
    25 impl HWServer {
       
    26     pub fn new(clients_limit: usize, rooms_limit: usize, io: Box<dyn HWServerIO>) -> HWServer {
       
    27         let rooms = Slab::with_capacity(rooms_limit);
       
    28         let clients = Slab::with_capacity(clients_limit);
       
    29         let mut server = HWServer {
       
    30             clients, rooms,
       
    31             lobby_id: 0,
       
    32             output: vec![],
       
    33             removed_clients: vec![],
       
    34             io
       
    35         };
       
    36         server.lobby_id = server.add_room();
       
    37         server
       
    38     }
       
    39 
       
    40     pub fn add_client(&mut self) -> ClientId {
       
    41         let key: ClientId;
       
    42         {
       
    43             let entry = self.clients.vacant_entry();
       
    44             key = entry.key();
       
    45             let mut salt = [0u8; 18];
       
    46             thread_rng().fill_bytes(&mut salt);
       
    47 
       
    48             let client = HWClient::new(entry.key(), encode(&salt));
       
    49             entry.insert(client);
       
    50         }
       
    51         self.send(key, &Destination::ToSelf, HWServerMessage::Connected(utils::PROTOCOL_VERSION));
       
    52         key
       
    53     }
       
    54 
       
    55     pub fn client_lost(&mut self, client_id: ClientId) {
       
    56         actions::run_action(self, client_id,
       
    57                             actions::Action::ByeClient("Connection reset".to_string()));
       
    58     }
       
    59 
       
    60     pub fn add_room(&mut self) -> RoomId {
       
    61         let entry = self.rooms.vacant_entry();
       
    62         let key = entry.key();
       
    63         let room = HWRoom::new(entry.key());
       
    64         entry.insert(room);
       
    65         key
       
    66     }
       
    67 
       
    68     pub fn handle_msg(&mut self, client_id: ClientId, msg: HWProtocolMessage) {
       
    69         debug!("Handling message {:?} for client {}", msg, client_id);
       
    70         if self.clients.contains(client_id) {
       
    71             handlers::handle(self, client_id, msg);
       
    72         }
       
    73     }
       
    74 
       
    75     fn get_recipients(&self, client_id: ClientId, destination: &Destination) -> Vec<ClientId> {
       
    76         let mut ids = match *destination {
       
    77             Destination::ToSelf => vec![client_id],
       
    78             Destination::ToId(id) => vec![id],
       
    79             Destination::ToAll {room_id: Some(id), ..} =>
       
    80                 self.room_clients(id),
       
    81             Destination::ToAll {protocol: Some(proto), ..} =>
       
    82                 self.protocol_clients(proto),
       
    83             Destination::ToAll {..} =>
       
    84                 self.clients.iter().map(|(id, _)| id).collect::<Vec<_>>()
       
    85         };
       
    86         if let Destination::ToAll {skip_self: true, ..} = destination {
       
    87             if let Some(index) = ids.iter().position(|id| *id == client_id) {
       
    88                 ids.remove(index);
       
    89             }
       
    90         }
       
    91         ids
       
    92     }
       
    93 
       
    94     pub fn send(&mut self, client_id: ClientId, destination: &Destination, message: HWServerMessage) {
       
    95         let ids = self.get_recipients(client_id, &destination);
       
    96         self.output.push((ids, message));
       
    97     }
       
    98 
       
    99     pub fn react(&mut self, client_id: ClientId, actions: Vec<actions::Action>) {
       
   100         for action in actions {
       
   101             actions::run_action(self, client_id, action);
       
   102         }
       
   103     }
       
   104 
       
   105     pub fn lobby(&self) -> &HWRoom { &self.rooms[self.lobby_id] }
       
   106 
       
   107     pub fn has_room(&self, name: &str) -> bool {
       
   108         self.rooms.iter().any(|(_, r)| r.name == name)
       
   109     }
       
   110 
       
   111     pub fn find_room(&self, name: &str) -> Option<&HWRoom> {
       
   112         self.rooms.iter().find_map(|(_, r)| Some(r).filter(|r| r.name == name))
       
   113     }
       
   114 
       
   115     pub fn find_room_mut(&mut self, name: &str) -> Option<&mut HWRoom> {
       
   116         self.rooms.iter_mut().find_map(|(_, r)| Some(r).filter(|r| r.name == name))
       
   117     }
       
   118 
       
   119     pub fn find_client(&self, nick: &str) -> Option<&HWClient> {
       
   120         self.clients.iter().find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
       
   121     }
       
   122 
       
   123     pub fn find_client_mut(&mut self, nick: &str) -> Option<&mut HWClient> {
       
   124         self.clients.iter_mut().find_map(|(_, c)| Some(c).filter(|c| c.nick == nick))
       
   125     }
       
   126 
       
   127     pub fn select_clients<F>(&self, f: F) -> Vec<ClientId>
       
   128         where F: Fn(&(usize, &HWClient)) -> bool {
       
   129         self.clients.iter().filter(f)
       
   130             .map(|(_, c)| c.id).collect()
       
   131     }
       
   132 
       
   133     pub fn room_clients(&self, room_id: RoomId) -> Vec<ClientId> {
       
   134         self.select_clients(|(_, c)| c.room_id == Some(room_id))
       
   135     }
       
   136 
       
   137     pub fn protocol_clients(&self, protocol: u16) -> Vec<ClientId> {
       
   138         self.select_clients(|(_, c)| c.protocol_number == protocol)
       
   139     }
       
   140 
       
   141     pub fn other_clients_in_room(&self, self_id: ClientId) -> Vec<ClientId> {
       
   142         let room_id = self.clients[self_id].room_id;
       
   143         self.select_clients(|(id, c)| *id != self_id && c.room_id == room_id )
       
   144     }
       
   145 
       
   146     pub fn client_and_room(&mut self, client_id: ClientId) -> (&mut HWClient, Option<&mut HWRoom>) {
       
   147         let c = &mut self.clients[client_id];
       
   148         if let Some(room_id) = c.room_id {
       
   149             (c, Some(&mut self.rooms[room_id]))
       
   150         } else {
       
   151             (c, None)
       
   152         }
       
   153     }
       
   154 
       
   155     pub fn room(&mut self, client_id: ClientId) -> Option<&mut HWRoom> {
       
   156         self.client_and_room(client_id).1
       
   157     }
       
   158 }