victorem 0.8.2

UPD Game Server Framework
Documentation
mod version;

mod protocol;

mod id;

pub mod timer;

mod key;

use self::id::{Arranger, Filter, Generator};
use self::key as k;
use self::protocol::ProtocolChecker;
use self::timer::SleepTimer;
use self::version::VersionChecker;
use crate::data_access_layer::Cache;
use crate::entities::{CommandPacket, Exception, StatePacket};

pub struct Client {
    protocol_version: VersionChecker,
    protocol_id: ProtocolChecker,
    id: Generator,
    cache: Cache,
    id_filter: Filter,
    timer: SleepTimer,
    key_generator: k::Generator,
    key_filter: k::Filter,
}

impl Client {
    pub fn new() -> Client {
        let key = k::new_key();
        Client {
            protocol_version: VersionChecker,
            protocol_id: ProtocolChecker,
            id: Generator::new(1),
            cache: Cache::new(),
            id_filter: Filter::new(0),
            timer: SleepTimer::new(30),
            key_filter: k::Filter::new(key),
            key_generator: k::Generator::new(),
        }
    }

    fn create_command(&mut self, command: Vec<u8>) -> CommandPacket {
        CommandPacket {
            protocol_id: self.protocol_id.get(),
            protocol_version: self.protocol_version.get(),
            id: self.id.generate(),
            command,
            session_key: self.key_generator.generate(),
        }
    }

    pub fn send(&mut self, command: Vec<u8>) -> CommandPacket {
        let command = self.create_command(command);
        self.cache.add(command.clone());
        self.timer.sleep();
        command
    }

    pub fn recv(&mut self, state: StatePacket) -> Result<(Vec<u8>, Vec<CommandPacket>), Exception> {
        self.protocol_version.check(&state)?;
        self.protocol_id.check(&state)?;
        if !self.key_filter.is_valid(&state) {
            self.key_filter = k::Filter::new(state.session_key);
            self.id_filter = Filter::new(0);
        }
        self.id_filter.filter(&state)?;
        let vec = self.get_lost(state.last_received, state.sequence);
        Ok((state.state, vec))
    }

    fn get_lost(&mut self, max_id: u32, sequence: u32) -> Vec<CommandPacket> {
        let mut x = max_id;
        let mut y = 0;
        let mut ids = Vec::<u32>::new();
        let max_cached = self.cache.get_max_id();
        if max_cached != max_id {
            ids.push(max_cached);
        }
        while x > 0 && y < 32 {
            x -= 1;
            let mask = 1u32 << y;
            y += 1;
            let res = sequence & mask;
            if res > 0 {
                ids.push(x);
            }
        }
        self.cache.get_range(&ids)
    }
}

pub struct Server {
    protocol_version: VersionChecker,
    protocol_id: ProtocolChecker,
    id: Generator,
    arranger: Arranger<CommandPacket>,
    key_generator: k::Generator,
    key_filter: k::Filter,
}

impl Server {
    pub fn new() -> Server {
        let key = k::new_key();
        Server {
            protocol_version: VersionChecker,
            protocol_id: ProtocolChecker,
            id: Generator::new(1),
            arranger: Arranger::new(0),
            key_filter: k::Filter::new(key),
            key_generator: k::Generator::new(),
        }
    }

    pub fn send(&mut self, state: Vec<u8>) -> StatePacket {
        let (sequence, last_id) = self.arranger.get_lost();
        StatePacket {
            protocol_id: self.protocol_id.get(),
            protocol_version: self.protocol_version.get(),
            id: self.id.generate(),
            state: state,
            last_received: last_id,
            sequence: sequence,
            session_key: self.key_generator.generate(),
        }
    }

    pub fn recv(&mut self, command: CommandPacket) -> Result<Vec<Vec<u8>>, Exception> {
        self.protocol_version.check(&command)?;
        self.protocol_id.check(&command)?;
        if !self.key_filter.is_valid(&command) {
            self.key_filter = k::Filter::new(command.session_key);
            self.arranger = Arranger::new(0);
        }
        self.arranger.add(command)?;
        let vec = self.arranger.arrange();
        Ok(vec.into_iter().map(|v| v.command).collect())
    }
}

#[cfg(test)]
mod bll_test {
    use crate::business_logic_layer::{Client, Server};

    #[test]
    fn client_should_recv_ordered_packets() {
        let mut client = Client::new();
        let mut server = Server::new();
        let packet1 = server.send(vec![1]);
        let packet2 = server.send(vec![2]);
        let packet3 = server.send(vec![3]);
        let r_packet1 = client.recv(packet1);
        let r_packet3 = client.recv(packet3);
        let r_packet2 = client.recv(packet2);
        assert!({
            match r_packet1 {
                Err(_) => false,
                Ok((v, _)) => v == vec![1]
            }
        });

        assert!({
            match r_packet3 {
                Err(_) => false,
                Ok((v, _)) => v == vec![3]
            }
        });

        assert!({
            match r_packet2 {
                Err(crate::entities::Exception::NotOrderedPacketError) => true,
                _ => false,
            }
        });
    }

    #[test]
    fn server_should_recv_ordered_and_reliable_packets() {
        let mut client = Client::new();
        let mut server = Server::new();
        let command1 = client.send(vec![1]);
        let command2 = client.send(vec![2]);
        let command3 = client.send(vec![3]);
        assert_eq!(3, command3.id);
        let r1 = server.recv(command1);
        let r3 = server.recv(command3);
        assert!({
            match r1 {
                Err(_) => false,
                Ok(v) => v.contains(&vec![1])
            }
        });
        assert!({
            match r3 {
                Err(_) => false,
                Ok(v) => v.is_empty(),
            }
        });
        let state1 = server.send(vec![4]);
        assert_eq!(3, state1.last_received);
        assert_eq!(1, state1.sequence);
        let (b, commands) = client.recv(state1).unwrap();

        let r2 = server.recv(commands.first().unwrap().to_owned());
        assert!({
            match r2 {
                Err(_) => false,
                Ok(v) => v.len() == 2 && v.contains(&vec![2]) && v.contains(&vec![3]) && v[0] == vec![2]
            }
        });
    }

    #[test]
    fn client_should_resend_undelivered_packets() {
        let mut client = Client::new();
        let mut server = Server::new();
        let command1 = client.send(vec![1]);
        let command2 = client.send(vec![2]);
        let r1 = server.recv(command1);
        let state1 = server.send(vec![4]);
        assert_eq!(state1.last_received, 1);
        let (b, commands) = client.recv(state1).unwrap();
        assert_eq!(1, commands.len());
        assert_eq!(b, vec![4]);
        let cmd = commands.first().unwrap().to_owned();
        assert_eq!(cmd.id, 2);
        assert_eq!(cmd.command, vec![2]);
    }
}