<commit_before>// Copyright (c) 2016 Fedor Gogolev <knsd@knsd.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::{Read, BufRead, Error as IoError, ErrorKind};
use std::string::{FromUtf8Error};
use std::collections::{HashMap};
use std::cell::{RefCell};
use std::rc::{Rc};

use num::{Zero};
use num::bigint::{BigInt, ToBigInt, Sign};
use byteorder::{ReadBytesExt, LittleEndian, BigEndian, Error as ByteorderError};
use from_ascii::{FromAscii, ParseIntError, ParseFloatError};

use string::{unescape, Error as UnescapeError};
use value::{Value};

use opcodes::*;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        EmptyMarker
        StackTooSmall
        EmptyStack
        InvalidValueOnStack
        InvalidGetValue
        InvalidPutValue
        NotImplemented

        Read(err: ByteorderError) {
            from()
        }
        Io(err: IoError) {
            from()
        }
        UnknownOpcode(opcode: u8) {}

        InvalidInt {
            from(ParseIntError)
        }
        InvalidLong
        InvalidFloat {
            from(ParseFloatError)
        }

        InvalidString {
            from(FromUtf8Error)
        }
        UnescapeError(err: UnescapeError) {
            from()
        }

        InvalidProto(proto: u8)
        NegativeLength {}

        #[doc(hidden)]
        __Nonexhaustive
    }
}

#[derive(Debug, PartialEq)]
pub enum BooleanOrInt {
    Boolean(bool),
    Int(i64),
}

macro_rules! rc {
    ($term: expr) => (Rc::new(RefCell::new($term)))
}

fn read_exact<R>(rd: &mut R, mut buf: &mut [u8]) -> Result<(), IoError> where R: Read {
    while !buf.is_empty() {
        match rd.read(buf) {
            Ok(0) => break,
            Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(IoError::new(ErrorKind::Other,
                       "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

fn read_until_newline<R>(rd: &mut R) -> Result<Vec<u8>, Error> where R: Read + BufRead {
    let mut buf = Vec::new();
    try!(rd.read_until('\n' as u8, &mut buf));

    // Skip last symbol — \n
    match buf.split_last() {
        Some((&b'\n', init)) => Ok(init.to_vec()),
        _ => Err(Error::InvalidString),
    }
}

fn read_decimal_int<R>(rd: &mut R) -> Result<BooleanOrInt, Error> where R: Read + BufRead {
    let s = try!(read_until_newline(rd));
    let val = match &s[..] {
        b"00" => BooleanOrInt::Boolean(false),
        b"01" => BooleanOrInt::Boolean(true),
        _ => BooleanOrInt::Int(try!(i64::from_ascii(&s)))
    };
    Ok(val)
}

fn read_decimal_long<R>(rd: &mut R) -> Result<BigInt, Error> where R: Read + BufRead {
    let s = try!(read_until_newline(rd));
    let init = match s.split_last() {
        None => return Err(Error::InvalidString),
        Some((&b'L', init)) => init,
        Some(_) => &s[..],
    };

    match BigInt::parse_bytes(&init, 10) {
        Some(i) => Ok(i),
        None => Err(Error::InvalidLong)
    }
}

fn read_long<R>(rd: &mut R, length: usize) -> Result<BigInt, Error> where R: Read + BufRead {
    let mut buf = vec![0; length];
    try!(read_exact(rd, buf.as_mut()));

    let mut n = BigInt::from_bytes_le(Sign::Plus, &buf);

    let last = match buf.last_mut() {
        None => return Err(Error::InvalidLong),
        Some(last) => last,
    };

    if *last > 127 {
        n = n - (1.to_bigint().unwrap() << (length * 8))
    }

    Ok(n)
}

pub struct Machine {
    stack: Vec<Value>,
    memo: HashMap<usize, Value>,
    marker: Option<usize>,
}

impl Machine {
    pub fn new() -> Self {
        Machine {
            stack: Vec::new(),
            memo: HashMap::new(),
            marker: None,
        }
    }

    fn split_off(&mut self) -> Result<Vec<Value>, Error> {
        let at = match self.marker {
            None => return Err(Error::EmptyMarker),
            Some(marker) => marker,
        };

        if at > self.stack.len() {
            return Err(Error::StackTooSmall);
        }

        Ok(self.stack.split_off(at))
    }

    fn pop(&mut self) -> Result<Value, Error> {
        match self.stack.pop() {
            None => Err(Error::EmptyStack),
            Some(value) => Ok(value),
        }
    }

    fn handle_get(&mut self, i: usize) -> Result<(), Error> {
        let value = match self.memo.get(&i) {
            None => return Err(Error::InvalidGetValue),
            Some(ref v) => (*v).clone(),
        };
        self.stack.push(value);
        Ok(())
    }

    fn handle_put(&mut self, i: usize) -> Result<(), Error> {
        let value = match self.stack.last() {
            None => return Err(Error::EmptyStack),
            Some(ref v) => (*v).clone(),
        };
        self.memo.insert(i, value);
        Ok(())
    }

    pub fn execute<R>(&mut self, rd: &mut R) -> Result<bool, Error> where R: Read + BufRead {
        macro_rules! ensure_not_negative {
            ($n: expr) => ({
                if $n < Zero::zero() {
                    return Err(Error::NegativeLength)
                }
            })
        }

        let marker = try!(rd.read_u8());
        match marker {
            PROTO => {
                let version = try!(rd.read_u8());
                if version < 2 {
                    return Err(Error::InvalidProto(version))
                }
            },
            STOP => return Ok(true),

            INT => {
                self.stack.push(match try!(read_decimal_int(rd)) {
                    BooleanOrInt::Boolean(v) => Value::Bool(v),
                    BooleanOrInt::Int(v) => Value::Long(BigInt::from(v)),
                })
            },
            BININT => self.stack.push(Value::Int(try!(rd.read_i32::<LittleEndian>()) as isize)),
            BININT1 => self.stack.push(Value::Int(try!(rd.read_u8()) as isize)),
            BININT2 => self.stack.push(Value::Int(try!(rd.read_u16::<LittleEndian>()) as isize)),
            LONG => self.stack.push(Value::Long(BigInt::from(try!(read_decimal_long(rd))))),
            LONG1 => {
                let length = try!(rd.read_u8());
                self.stack.push(Value::Long(BigInt::from(try!(read_long(rd, length as usize)))))
            }
            LONG4 => {
                let length = try!(rd.read_i32::<LittleEndian>());
                self.stack.push(Value::Long(BigInt::from(try!(read_long(rd, length as usize)))))
            }

            STRING => self.stack.push(Value::String(try!(unescape(&try!(read_until_newline(rd)), false)))),
            BINSTRING => {
                let length = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(length);

                let mut buf = vec![0; length as usize];
                try!(read_exact(rd, &mut buf));
                self.stack.push(Value::String(buf))
            },
            SHORT_BINSTRING => {
                let length = try!(rd.read_u8());
                let mut buf = vec![0; length as usize];
                try!(read_exact(rd, &mut buf));
                self.stack.push(Value::String(buf))
            },

            NONE => self.stack.push(Value::None),
            NEWTRUE => self.stack.push(Value::Bool(true)),
            NEWFALSE => self.stack.push(Value::Bool(false)),

            UNICODE => {
                let buf = try!(unescape(&try!(read_until_newline(rd)), true));
                self.stack.push(Value::Unicode(try!(String::from_utf8(buf))))
            },
            BINUNICODE => {
                let length = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(length);
                let mut buf = vec![0; length as usize];
                try!(read_exact(rd, buf.as_mut()));
                self.stack.push(Value::Unicode(try!(String::from_utf8(buf))))
            },

            FLOAT => {
                let s = try!(read_until_newline(rd));
                self.stack.push(Value::Float(try!(f64::from_ascii(&s))))
            },
            BINFLOAT => {
                self.stack.push(Value::Float(try!(rd.read_f64::<BigEndian>())))
            },

            EMPTY_LIST => {
                self.stack.push(Value::List(rc!(Vec::new())))
            },
            APPEND => {
                let v = try!(self.pop());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::List(ref mut list)) => (*list.borrow_mut()).push(v),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            APPENDS => {
                let values = try!(self.split_off());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::List(ref mut list)) => (*list.borrow_mut()).extend(values),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            LIST => {
                let values = try!(self.split_off());
                self.stack.push(Value::List(rc!(values)));
            },

            EMPTY_TUPLE => self.stack.push(Value::Tuple(rc!(Vec::new()))),
            TUPLE => {
                let values = try!(self.split_off());
                self.stack.push(Value::Tuple(rc!(values)));
            },
            TUPLE1 => {
                let v1 = try!(self.pop());
                self.stack.push(Value::Tuple(rc!(vec![v1])))
            },
            TUPLE2 => {
                let v1 = try!(self.pop());
                let v2 = try!(self.pop());
                self.stack.push(Value::Tuple(rc!(vec![v1, v2])))
            },
            TUPLE3 => {
                let v1 = try!(self.pop());
                let v2 = try!(self.pop());
                let v3 = try!(self.pop());
                self.stack.push(Value::Tuple(rc!(vec![v1, v2, v3])))
            }

            EMPTY_DICT => self.stack.push(Value::Dict(rc!(Vec::new()))),
            DICT => {
                let mut values = try!(self.split_off());
                let mut dict = Vec::new();

                for i in 0 .. values.len() / 2 { // TODO: Check panic
                    let key = values.remove(2 * i);
                    let value = values.remove(2 * i + 1);
                    dict.push((key, value));
                }
                self.stack.push(Value::Dict(rc!(dict)));
            },
            SETITEM => {
                let value = try!(self.pop());
                let key = try!(self.pop());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::Dict(ref mut dict)) => (*dict.borrow_mut()).push((key, value)),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            SETITEMS => {
                let mut values = try!(self.split_off());

                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::Dict(ref mut dict_ref)) => {
                        for i in 0 .. values.len() / 2 { // TODO: Check panic
                                let key = values.remove(2 * i);
                                let value = values.remove(2 * i + 1);
                                (*dict_ref.borrow_mut()).push((key, value));
                            }
                    },
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },

            POP => {
                try!(self.pop());
            },
            DUP => {
                let value = match self.stack.last() {
                    None => return Err(Error::EmptyStack),
                    Some(ref v) => (*v).clone(),
                };
                self.stack.push(value)
            },
            MARK => {
                self.marker = Some(self.stack.len())
            },
            POP_MARK => {
                try!(self.split_off());
            },

            GET => {
                let n = match try!(read_decimal_int(rd)) {
                    BooleanOrInt::Int(n) => n,
                    BooleanOrInt::Boolean(false) => 0,
                    BooleanOrInt::Boolean(true) => 1,
                };
                ensure_not_negative!(n);
                try!(self.handle_get(n as usize))
            }
            BINGET => {
                try!(self.handle_get(try!(rd.read_u8()) as usize))
            }
            LONG_BINGET => {
                let n = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(n);
                try!(self.handle_get(n as usize))
            }

            PUT => {
                let n = match try!(read_decimal_int(rd)) {
                    BooleanOrInt::Int(n) => n,
                    BooleanOrInt::Boolean(false) => 0,
                    BooleanOrInt::Boolean(true) => 1,
                };
                ensure_not_negative!(n);
                try!(self.handle_put(n as usize))
            }
            BINPUT => {
                try!(self.handle_put(try!(rd.read_u8()) as usize))
            }
            LONG_BINPUT => {
                let n = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(n);
                try!(self.handle_put(n as usize))
            }

            c => return Err(Error::UnknownOpcode(c)),
        }
        Ok(false)
    }
}

pub fn unpickle<R>(rd: &mut R) -> Result<Value, Error> where R: Read + BufRead {
    let mut machine = Machine::new();
    loop {
        if try!(machine.execute(rd)) {
            break
        }
    }
    Ok(try!(machine.pop()))
}
<commit_msg>Eliminate marker<commit_after>// Copyright (c) 2016 Fedor Gogolev <knsd@knsd.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::io::{Read, BufRead, Error as IoError, ErrorKind};
use std::string::{FromUtf8Error};
use std::collections::{HashMap};
use std::cell::{RefCell};
use std::rc::{Rc};

use num::{Zero};
use num::bigint::{BigInt, ToBigInt, Sign};
use byteorder::{ReadBytesExt, LittleEndian, BigEndian, Error as ByteorderError};
use from_ascii::{FromAscii, ParseIntError, ParseFloatError};

use string::{unescape, Error as UnescapeError};
use value::{Value};

use opcodes::*;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        EmptyMarker
        StackTooSmall
        EmptyStack
        InvalidValueOnStack
        InvalidGetValue
        InvalidPutValue
        NotImplemented

        Read(err: ByteorderError) {
            from()
        }
        Io(err: IoError) {
            from()
        }
        UnknownOpcode(opcode: u8) {}

        InvalidInt {
            from(ParseIntError)
        }
        InvalidLong
        InvalidFloat {
            from(ParseFloatError)
        }

        InvalidString {
            from(FromUtf8Error)
        }
        UnescapeError(err: UnescapeError) {
            from()
        }

        InvalidProto(proto: u8)
        NegativeLength {}

        #[doc(hidden)]
        __Nonexhaustive
    }
}

#[derive(Debug, PartialEq)]
pub enum BooleanOrInt {
    Boolean(bool),
    Int(i64),
}

macro_rules! rc {
    ($term: expr) => (Rc::new(RefCell::new($term)))
}

fn read_exact<R>(rd: &mut R, mut buf: &mut [u8]) -> Result<(), IoError> where R: Read {
    while !buf.is_empty() {
        match rd.read(buf) {
            Ok(0) => break,
            Ok(n) => { let tmp = buf; buf = &mut tmp[n..]; }
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            Err(e) => return Err(e),
        }
    }
    if !buf.is_empty() {
        Err(IoError::new(ErrorKind::Other,
                       "failed to fill whole buffer"))
    } else {
        Ok(())
    }
}

fn read_until_newline<R>(rd: &mut R) -> Result<Vec<u8>, Error> where R: Read + BufRead {
    let mut buf = Vec::new();
    try!(rd.read_until('\n' as u8, &mut buf));

    // Skip last symbol — \n
    match buf.split_last() {
        Some((&b'\n', init)) => Ok(init.to_vec()),
        _ => Err(Error::InvalidString),
    }
}

fn read_decimal_int<R>(rd: &mut R) -> Result<BooleanOrInt, Error> where R: Read + BufRead {
    let s = try!(read_until_newline(rd));
    let val = match &s[..] {
        b"00" => BooleanOrInt::Boolean(false),
        b"01" => BooleanOrInt::Boolean(true),
        _ => BooleanOrInt::Int(try!(i64::from_ascii(&s)))
    };
    Ok(val)
}

fn read_decimal_long<R>(rd: &mut R) -> Result<BigInt, Error> where R: Read + BufRead {
    let s = try!(read_until_newline(rd));
    let init = match s.split_last() {
        None => return Err(Error::InvalidString),
        Some((&b'L', init)) => init,
        Some(_) => &s[..],
    };

    match BigInt::parse_bytes(&init, 10) {
        Some(i) => Ok(i),
        None => Err(Error::InvalidLong)
    }
}

fn read_long<R>(rd: &mut R, length: usize) -> Result<BigInt, Error> where R: Read + BufRead {
    let mut buf = vec![0; length];
    try!(read_exact(rd, buf.as_mut()));

    let mut n = BigInt::from_bytes_le(Sign::Plus, &buf);

    let last = match buf.last_mut() {
        None => return Err(Error::InvalidLong),
        Some(last) => last,
    };

    if *last > 127 {
        n = n - (1.to_bigint().unwrap() << (length * 8))
    }

    Ok(n)
}

pub struct Machine {
    stack: Vec<Value>,
    memo: HashMap<usize, Value>,
    marker: Option<usize>,
}

impl Machine {
    pub fn new() -> Self {
        Machine {
            stack: Vec::new(),
            memo: HashMap::new(),
            marker: None,
        }
    }

    fn split_off(&mut self) -> Result<Vec<Value>, Error> {
        let at = match self.marker {
            None => return Err(Error::EmptyMarker),
            Some(marker) => marker,
        };

        if at > self.stack.len() {
            return Err(Error::StackTooSmall);
        }

        Ok(self.stack.split_off(at))
    }

    fn pop(&mut self) -> Result<Value, Error> {
        match self.stack.pop() {
            None => Err(Error::EmptyStack),
            Some(value) => Ok(value),
        }
    }

    fn handle_get(&mut self, i: usize) -> Result<(), Error> {
        let value = match self.memo.get(&i) {
            None => return Err(Error::InvalidGetValue),
            Some(ref v) => (*v).clone(),
        };
        self.stack.push(value);
        Ok(())
    }

    fn handle_put(&mut self, i: usize) -> Result<(), Error> {
        let value = match self.stack.last() {
            None => return Err(Error::EmptyStack),
            Some(ref v) => (*v).clone(),
        };
        self.memo.insert(i, value);
        Ok(())
    }

    pub fn execute<R>(&mut self, rd: &mut R) -> Result<bool, Error> where R: Read + BufRead {
        macro_rules! ensure_not_negative {
            ($n: expr) => ({
                if $n < Zero::zero() {
                    return Err(Error::NegativeLength)
                }
            })
        }

        match try!(rd.read_u8()) {
            PROTO => {
                let version = try!(rd.read_u8());
                if version < 2 {
                    return Err(Error::InvalidProto(version))
                }
            },
            STOP => return Ok(true),

            INT => {
                self.stack.push(match try!(read_decimal_int(rd)) {
                    BooleanOrInt::Boolean(v) => Value::Bool(v),
                    BooleanOrInt::Int(v) => Value::Long(BigInt::from(v)),
                })
            },
            BININT => self.stack.push(Value::Int(try!(rd.read_i32::<LittleEndian>()) as isize)),
            BININT1 => self.stack.push(Value::Int(try!(rd.read_u8()) as isize)),
            BININT2 => self.stack.push(Value::Int(try!(rd.read_u16::<LittleEndian>()) as isize)),
            LONG => self.stack.push(Value::Long(BigInt::from(try!(read_decimal_long(rd))))),
            LONG1 => {
                let length = try!(rd.read_u8());
                self.stack.push(Value::Long(BigInt::from(try!(read_long(rd, length as usize)))))
            }
            LONG4 => {
                let length = try!(rd.read_i32::<LittleEndian>());
                self.stack.push(Value::Long(BigInt::from(try!(read_long(rd, length as usize)))))
            }

            STRING => self.stack.push(Value::String(try!(unescape(&try!(read_until_newline(rd)), false)))),
            BINSTRING => {
                let length = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(length);

                let mut buf = vec![0; length as usize];
                try!(read_exact(rd, &mut buf));
                self.stack.push(Value::String(buf))
            },
            SHORT_BINSTRING => {
                let length = try!(rd.read_u8());
                let mut buf = vec![0; length as usize];
                try!(read_exact(rd, &mut buf));
                self.stack.push(Value::String(buf))
            },

            NONE => self.stack.push(Value::None),
            NEWTRUE => self.stack.push(Value::Bool(true)),
            NEWFALSE => self.stack.push(Value::Bool(false)),

            UNICODE => {
                let buf = try!(unescape(&try!(read_until_newline(rd)), true));
                self.stack.push(Value::Unicode(try!(String::from_utf8(buf))))
            },
            BINUNICODE => {
                let length = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(length);
                let mut buf = vec![0; length as usize];
                try!(read_exact(rd, buf.as_mut()));
                self.stack.push(Value::Unicode(try!(String::from_utf8(buf))))
            },

            FLOAT => {
                let s = try!(read_until_newline(rd));
                self.stack.push(Value::Float(try!(f64::from_ascii(&s))))
            },
            BINFLOAT => {
                self.stack.push(Value::Float(try!(rd.read_f64::<BigEndian>())))
            },

            EMPTY_LIST => {
                self.stack.push(Value::List(rc!(Vec::new())))
            },
            APPEND => {
                let v = try!(self.pop());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::List(ref mut list)) => (*list.borrow_mut()).push(v),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            APPENDS => {
                let values = try!(self.split_off());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::List(ref mut list)) => (*list.borrow_mut()).extend(values),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            LIST => {
                let values = try!(self.split_off());
                self.stack.push(Value::List(rc!(values)));
            },

            EMPTY_TUPLE => self.stack.push(Value::Tuple(rc!(Vec::new()))),
            TUPLE => {
                let values = try!(self.split_off());
                self.stack.push(Value::Tuple(rc!(values)));
            },
            TUPLE1 => {
                let v1 = try!(self.pop());
                self.stack.push(Value::Tuple(rc!(vec![v1])))
            },
            TUPLE2 => {
                let v1 = try!(self.pop());
                let v2 = try!(self.pop());
                self.stack.push(Value::Tuple(rc!(vec![v1, v2])))
            },
            TUPLE3 => {
                let v1 = try!(self.pop());
                let v2 = try!(self.pop());
                let v3 = try!(self.pop());
                self.stack.push(Value::Tuple(rc!(vec![v1, v2, v3])))
            }

            EMPTY_DICT => self.stack.push(Value::Dict(rc!(Vec::new()))),
            DICT => {
                let mut values = try!(self.split_off());
                let mut dict = Vec::new();

                for i in 0 .. values.len() / 2 { // TODO: Check panic
                    let key = values.remove(2 * i);
                    let value = values.remove(2 * i + 1);
                    dict.push((key, value));
                }
                self.stack.push(Value::Dict(rc!(dict)));
            },
            SETITEM => {
                let value = try!(self.pop());
                let key = try!(self.pop());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::Dict(ref mut dict)) => (*dict.borrow_mut()).push((key, value)),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            SETITEMS => {
                let mut values = try!(self.split_off());

                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::Dict(ref mut dict_ref)) => {
                        for i in 0 .. values.len() / 2 { // TODO: Check panic
                                let key = values.remove(2 * i);
                                let value = values.remove(2 * i + 1);
                                (*dict_ref.borrow_mut()).push((key, value));
                            }
                    },
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },

            POP => {
                try!(self.pop());
            },
            DUP => {
                let value = match self.stack.last() {
                    None => return Err(Error::EmptyStack),
                    Some(ref v) => (*v).clone(),
                };
                self.stack.push(value)
            },
            MARK => {
                self.marker = Some(self.stack.len())
            },
            POP_MARK => {
                try!(self.split_off());
            },

            GET => {
                let n = match try!(read_decimal_int(rd)) {
                    BooleanOrInt::Int(n) => n,
                    BooleanOrInt::Boolean(false) => 0,
                    BooleanOrInt::Boolean(true) => 1,
                };
                ensure_not_negative!(n);
                try!(self.handle_get(n as usize))
            }
            BINGET => {
                try!(self.handle_get(try!(rd.read_u8()) as usize))
            }
            LONG_BINGET => {
                let n = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(n);
                try!(self.handle_get(n as usize))
            }

            PUT => {
                let n = match try!(read_decimal_int(rd)) {
                    BooleanOrInt::Int(n) => n,
                    BooleanOrInt::Boolean(false) => 0,
                    BooleanOrInt::Boolean(true) => 1,
                };
                ensure_not_negative!(n);
                try!(self.handle_put(n as usize))
            }
            BINPUT => {
                try!(self.handle_put(try!(rd.read_u8()) as usize))
            }
            LONG_BINPUT => {
                let n = try!(rd.read_i32::<LittleEndian>());
                ensure_not_negative!(n);
                try!(self.handle_put(n as usize))
            }

            c => return Err(Error::UnknownOpcode(c)),
        }
        Ok(false)
    }
}

pub fn unpickle<R>(rd: &mut R) -> Result<Value, Error> where R: Read + BufRead {
    let mut machine = Machine::new();
    loop {
        if try!(machine.execute(rd)) {
            break
        }
    }
    Ok(try!(machine.pop()))
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use glib::types::{StaticType, Type};
use device::Device;
use display::Display;
use object::Object;
use ffi;

/// GdkDeviceManager — Functions for handling input devices
///
/// Description
///
/// In addition to a single pointer and keyboard for user interface input, GDK contains support
/// for a variety of input devices, including graphics tablets, touchscreens and multiple
/// pointers/keyboards interacting simultaneously with the user interface. Such input devices
/// often have additional features, such as sub-pixel positioning information and additional
/// device-dependent information.
///
/// In order to query the device hierarchy and be aware of changes in the device hierarchy
/// (such as virtual devices being created or removed, or physical devices being plugged or
/// unplugged), GDK provides DeviceManager.
///
/// By default, and if the platform supports it, GDK is aware of multiple keyboard/pointer pairs
/// and multitouch devices. This behavior can be changed by calling
/// DeviceManager::disable_multidevice() before Display::open(). There should rarely be a need to
/// do that though, since GDK defaults to a compatibility mode in which it will emit just one
/// enter/leave event pair for all devices on a window. To enable per-device enter/leave events
/// and other multi-pointer interaction features, Window::set_support_multidevice() must be called
/// on gdk::Windows (or gtk::Widget::set_support_multidevice() on widgets) window. See the
/// Window::set_support_multidevice() documentation for more information.
///
/// On X11, multi-device support is implemented through XInput 2. Unless
/// DeviceManager::disable_multidevice() is called, the XInput 2 GdkDeviceManager implementation
/// will be used as the input source. Otherwise either the core or XInput 1 implementations will
/// be used.
///
/// For simple applications that don’t have any special interest in input devices, the so-called
/// "client pointer" provides a reasonable approximation to a simple setup with a single pointer
/// and keyboard. The device that has been set as the client pointer can be accessed via
/// DeviceManager::get_client_pointer().
///
/// Conceptually, in multidevice mode there are 2 device types. Virtual devices (or master devices)
/// are represented by the pointer cursors and keyboard foci that are seen on the screen. Physical
/// devices (or slave devices) represent the hardware that is controlling the virtual devices, and
/// thus have no visible cursor on the screen.
///
/// Virtual devices are always paired, so there is a keyboard device for every pointer device.
/// Associations between devices may be inspected through Device::get_associated_device().
///
/// There may be several virtual devices, and several physical devices could be controlling each of
/// these virtual devices. Physical devices may also be “floating”, which means they are not attached
/// to any virtual device.
///
/// #Master and slave devices
///
/// ```ignore
/// carlos@sacarino:~$ xinput list
/// ⎡ Virtual core pointer                          id=2    [master pointer  (3)]
/// ⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
/// ⎜   ↳ Wacom ISDv4 E6 Pen stylus                 id=10   [slave  pointer  (2)]
/// ⎜   ↳ Wacom ISDv4 E6 Finger touch               id=11   [slave  pointer  (2)]
/// ⎜   ↳ SynPS/2 Synaptics TouchPad                id=13   [slave  pointer  (2)]
/// ⎜   ↳ TPPS/2 IBM TrackPoint                     id=14   [slave  pointer  (2)]
/// ⎜   ↳ Wacom ISDv4 E6 Pen eraser                 id=16   [slave  pointer  (2)]
/// ⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
///     ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
///     ↳ Power Button                              id=6    [slave  keyboard (3)]
///     ↳ Video Bus                                 id=7    [slave  keyboard (3)]
///     ↳ Sleep Button                              id=8    [slave  keyboard (3)]
///     ↳ Integrated Camera                         id=9    [slave  keyboard (3)]
///     ↳ AT Translated Set 2 keyboard              id=12   [slave  keyboard (3)]
///     ↳ ThinkPad Extra Buttons                    id=15   [slave  keyboard (3)]
/// ```
///
/// By default, GDK will automatically listen for events coming from all master devices, setting the
/// Device for all events coming from input devices. Events containing device information are
/// GDK_MOTION_NOTIFY, GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_3BUTTON_PRESS, GDK_BUTTON_RELEASE,
/// GDK_SCROLL, GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_ENTER_NOTIFY, GDK_LEAVE_NOTIFY, GDK_FOCUS_CHANGE,
/// GDK_PROXIMITY_IN, GDK_PROXIMITY_OUT, GDK_DRAG_ENTER, GDK_DRAG_LEAVE, GDK_DRAG_MOTION,
/// GDK_DRAG_STATUS, GDK_DROP_START, GDK_DROP_FINISHED and GDK_GRAB_BROKEN. When dealing with an event
/// on a master device, it is possible to get the source (slave) device that the event originated from
/// via Event::get_source_device().
///
/// On a standard session, all physical devices are connected by default to the "Virtual Core
/// Pointer/Keyboard" master devices, hence routing all events through these. This behavior is only
/// modified by device grabs, where the slave device is temporarily detached for as long as the grab is
/// held, and more permanently by user modifications to the device hierarchy.
///
/// On certain application specific setups, it may make sense to detach a physical device from its
/// master pointer, and mapping it to an specific window. This can be achieved by the combination of
/// Device::grab() and Device::set_mode().
///
/// In order to listen for events coming from devices other than a virtual device,
/// Window::set_device_events() must be called. Generally, this function can be used to modify the event
/// mask for any given device.
///
/// Input devices may also provide additional information besides X/Y. For example, graphics tablets may
/// also provide pressure and X/Y tilt information. This information is device-dependent, and may be
/// queried through Device::get_axis(). In multidevice mode, virtual devices will change axes in order to
/// always represent the physical device that is routing events through it. Whenever the physical device
/// changes, the “n-axes” property will be notified, and Device::list_axes() will return the new device
/// axes.
///
/// Devices may also have associated “keys” or macro buttons. Such keys can be globally set to map into
/// normal X keyboard events. The mapping is set using Device::set_key().
pub type DeviceManager = Object<ffi::GdkDeviceManager>;

impl StaticType for DeviceManager {
    fn static_type() -> Type { unsafe { from_glib(ffi::gdk_device_manager_get_type()) } }
}

impl DeviceManager {
    /// Disables multidevice support in GDK. This call must happen prior to Display::open(),
    /// gtk::init(), gtk::init_with_args() or gtk::init_check() in order to take effect.
    ///
    /// Most common GTK+ applications won’t ever need to call this. Only applications that do
    /// mixed GDK/Xlib calls could want to disable multidevice support if such Xlib code deals
    /// with input devices in any way and doesn’t observe the presence of XInput 2.
    pub fn disable_multidevice() {
        unsafe { ffi::gdk_disable_multidevice() }
    }

    /// Gets the Display associated to `self`.
    pub fn get_display(&self) -> Option<Display> {
        unsafe { from_glib_none(ffi::gdk_device_manager_get_display(self.to_glib_none().0)) }
    }

    /// Returns the client pointer, that is, the master pointer that acts as the core pointer
    /// for this application. In X11, window managers may change this depending on the
    /// interaction pattern under the presence of several pointers.
    ///
    /// You should use this function seldomly, only in code that isn’t triggered by a Event and
    /// there aren’t other means to get a meaningful Device to operate on.
    pub fn get_client_pointer(&self) -> Device {
        unsafe {
            from_glib_none(
                ffi::gdk_device_manager_get_client_pointer(self.to_glib_none().0))
        }
    }
}
<commit_msg>Mark the non-rust 'code' snippet as text<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib::translate::*;
use glib::types::{StaticType, Type};
use device::Device;
use display::Display;
use object::Object;
use ffi;

/// GdkDeviceManager — Functions for handling input devices
///
/// Description
///
/// In addition to a single pointer and keyboard for user interface input, GDK contains support
/// for a variety of input devices, including graphics tablets, touchscreens and multiple
/// pointers/keyboards interacting simultaneously with the user interface. Such input devices
/// often have additional features, such as sub-pixel positioning information and additional
/// device-dependent information.
///
/// In order to query the device hierarchy and be aware of changes in the device hierarchy
/// (such as virtual devices being created or removed, or physical devices being plugged or
/// unplugged), GDK provides DeviceManager.
///
/// By default, and if the platform supports it, GDK is aware of multiple keyboard/pointer pairs
/// and multitouch devices. This behavior can be changed by calling
/// DeviceManager::disable_multidevice() before Display::open(). There should rarely be a need to
/// do that though, since GDK defaults to a compatibility mode in which it will emit just one
/// enter/leave event pair for all devices on a window. To enable per-device enter/leave events
/// and other multi-pointer interaction features, Window::set_support_multidevice() must be called
/// on gdk::Windows (or gtk::Widget::set_support_multidevice() on widgets) window. See the
/// Window::set_support_multidevice() documentation for more information.
///
/// On X11, multi-device support is implemented through XInput 2. Unless
/// DeviceManager::disable_multidevice() is called, the XInput 2 GdkDeviceManager implementation
/// will be used as the input source. Otherwise either the core or XInput 1 implementations will
/// be used.
///
/// For simple applications that don’t have any special interest in input devices, the so-called
/// "client pointer" provides a reasonable approximation to a simple setup with a single pointer
/// and keyboard. The device that has been set as the client pointer can be accessed via
/// DeviceManager::get_client_pointer().
///
/// Conceptually, in multidevice mode there are 2 device types. Virtual devices (or master devices)
/// are represented by the pointer cursors and keyboard foci that are seen on the screen. Physical
/// devices (or slave devices) represent the hardware that is controlling the virtual devices, and
/// thus have no visible cursor on the screen.
///
/// Virtual devices are always paired, so there is a keyboard device for every pointer device.
/// Associations between devices may be inspected through Device::get_associated_device().
///
/// There may be several virtual devices, and several physical devices could be controlling each of
/// these virtual devices. Physical devices may also be “floating”, which means they are not attached
/// to any virtual device.
///
/// #Master and slave devices
///
/// ```text
/// carlos@sacarino:~$ xinput list
/// ⎡ Virtual core pointer                          id=2    [master pointer  (3)]
/// ⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
/// ⎜   ↳ Wacom ISDv4 E6 Pen stylus                 id=10   [slave  pointer  (2)]
/// ⎜   ↳ Wacom ISDv4 E6 Finger touch               id=11   [slave  pointer  (2)]
/// ⎜   ↳ SynPS/2 Synaptics TouchPad                id=13   [slave  pointer  (2)]
/// ⎜   ↳ TPPS/2 IBM TrackPoint                     id=14   [slave  pointer  (2)]
/// ⎜   ↳ Wacom ISDv4 E6 Pen eraser                 id=16   [slave  pointer  (2)]
/// ⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
///     ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
///     ↳ Power Button                              id=6    [slave  keyboard (3)]
///     ↳ Video Bus                                 id=7    [slave  keyboard (3)]
///     ↳ Sleep Button                              id=8    [slave  keyboard (3)]
///     ↳ Integrated Camera                         id=9    [slave  keyboard (3)]
///     ↳ AT Translated Set 2 keyboard              id=12   [slave  keyboard (3)]
///     ↳ ThinkPad Extra Buttons                    id=15   [slave  keyboard (3)]
/// ```
///
/// By default, GDK will automatically listen for events coming from all master devices, setting the
/// Device for all events coming from input devices. Events containing device information are
/// GDK_MOTION_NOTIFY, GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_3BUTTON_PRESS, GDK_BUTTON_RELEASE,
/// GDK_SCROLL, GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_ENTER_NOTIFY, GDK_LEAVE_NOTIFY, GDK_FOCUS_CHANGE,
/// GDK_PROXIMITY_IN, GDK_PROXIMITY_OUT, GDK_DRAG_ENTER, GDK_DRAG_LEAVE, GDK_DRAG_MOTION,
/// GDK_DRAG_STATUS, GDK_DROP_START, GDK_DROP_FINISHED and GDK_GRAB_BROKEN. When dealing with an event
/// on a master device, it is possible to get the source (slave) device that the event originated from
/// via Event::get_source_device().
///
/// On a standard session, all physical devices are connected by default to the "Virtual Core
/// Pointer/Keyboard" master devices, hence routing all events through these. This behavior is only
/// modified by device grabs, where the slave device is temporarily detached for as long as the grab is
/// held, and more permanently by user modifications to the device hierarchy.
///
/// On certain application specific setups, it may make sense to detach a physical device from its
/// master pointer, and mapping it to an specific window. This can be achieved by the combination of
/// Device::grab() and Device::set_mode().
///
/// In order to listen for events coming from devices other than a virtual device,
/// Window::set_device_events() must be called. Generally, this function can be used to modify the event
/// mask for any given device.
///
/// Input devices may also provide additional information besides X/Y. For example, graphics tablets may
/// also provide pressure and X/Y tilt information. This information is device-dependent, and may be
/// queried through Device::get_axis(). In multidevice mode, virtual devices will change axes in order to
/// always represent the physical device that is routing events through it. Whenever the physical device
/// changes, the “n-axes” property will be notified, and Device::list_axes() will return the new device
/// axes.
///
/// Devices may also have associated “keys” or macro buttons. Such keys can be globally set to map into
/// normal X keyboard events. The mapping is set using Device::set_key().
pub type DeviceManager = Object<ffi::GdkDeviceManager>;

impl StaticType for DeviceManager {
    fn static_type() -> Type { unsafe { from_glib(ffi::gdk_device_manager_get_type()) } }
}

impl DeviceManager {
    /// Disables multidevice support in GDK. This call must happen prior to Display::open(),
    /// gtk::init(), gtk::init_with_args() or gtk::init_check() in order to take effect.
    ///
    /// Most common GTK+ applications won’t ever need to call this. Only applications that do
    /// mixed GDK/Xlib calls could want to disable multidevice support if such Xlib code deals
    /// with input devices in any way and doesn’t observe the presence of XInput 2.
    pub fn disable_multidevice() {
        unsafe { ffi::gdk_disable_multidevice() }
    }

    /// Gets the Display associated to `self`.
    pub fn get_display(&self) -> Option<Display> {
        unsafe { from_glib_none(ffi::gdk_device_manager_get_display(self.to_glib_none().0)) }
    }

    /// Returns the client pointer, that is, the master pointer that acts as the core pointer
    /// for this application. In X11, window managers may change this depending on the
    /// interaction pattern under the presence of several pointers.
    ///
    /// You should use this function seldomly, only in code that isn’t triggered by a Event and
    /// there aren’t other means to get a meaningful Device to operate on.
    pub fn get_client_pointer(&self) -> Device {
        unsafe {
            from_glib_none(
                ffi::gdk_device_manager_get_client_pointer(self.to_glib_none().0))
        }
    }
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::io::{Read, Write};
use std::sync::mpsc::{Sender, channel};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;

use VERSION;

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use mio::{EventLoop as MioEventLoop, EventSet, Handler as MioHandler, PollOpt, Token};
use mio::tcp::{Shutdown, TcpListener, TcpStream};
use mio::util::Slab;
use slab::Index;

pub mod client;
pub mod server;
#[cfg(Test)]
pub mod test;

/// The default port for a server to listen on.
pub const STANDARD_PORT: u16 = 25566;
/// Standard number to ensure network connections are syncronized and the same protocol is being used.
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.
const MAX_CONNECTIONS: usize = 1024;

pub enum HandlerMessage {
    Send(NetworkPacket, Token),
    AddStream(TcpStream, Sender<Token>),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        version: String,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
    /// Used to unit test networking. When recived, increments a value. TODO: Locate that value.
    #[cfg(test)]
    Test,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    VersionMismatch(String, String),
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => "VersionMismatch: The versions of the client and server attempting to connect mismatch.",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
        }
    }
}

pub type EventLoop = MioEventLoop<Handler>;
pub struct Handler {
    connections: Slab<Connection>,
    listener: Option<TcpListener>,
}

impl Handler {
    /// Creates a new instance of a Handler. Does not listen for connections.
    pub fn new() -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: None,
        }
    }

    /// Creates a new instance of a Handler. Does listen for connections.
    pub fn new_listener(addr: &SocketAddr) -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: TcpListener::bind(addr),
        }
    }
}

#[derive(Debug)]
struct Connection {
    message_queue: Vec<NetworkPacket>,
    stream: TcpStream,
}

impl Connection {
    fn new(stream: TcpStream) -> Connection {
        Connection {
            stream: stream,
            message_queue: Vec::new(),
        }
    }
}

impl MioHandler for Handler {
    type Timeout = ();
    type Message = HandlerMessage;
    fn ready(&mut self, event_loop: &mut MioEventLoop<Handler>, token: Token, events: EventSet) {
        if events.is_readable() {
            // Read the 6 byte header of each packet, throw it into get_packet_length, then read that number of bytes.
            // Then throw those bytes into deserialize_packet. Afterwards, throw it to handle_packet.

            let mut header = [0; 6];
            self.connections[token]
                .stream
                .read(&mut header)
                .expect(&format!("An error occured reading from socket {:?}", token));    // TODO: Figure out possible errors and take care of them.
            let length = get_packet_length(header).unwrap_or(0);
            if length == 0 {
                event_loop.deregister(self.connections[token].stream);
                self.connections[token].stream.shutdown(Shutdown::Both);
                self.connections.remove(token);
                // I directly kill the connection, becasue if the magic number doesn't match,
                // the peer probably doesn't share the same protocol. It wouldn't understand a normal error packet.
                return;
            }
            let mut packet = Vec::new();
            (&mut self.connections[token].stream).take(length as u64).read_to_end(&mut packet).unwrap();
            // I do this because Read.take takes a self, instead of a reasonable alternitive.
            // However &mut Read is it's self a Reader. So I use that instead.
            let dese = deserialize_packet(&packet).unwrap();
            handle_packet(dese, token, event_loop);
        }

        if events.is_writable() {
            // Get all the messages that should be send to that token, seralize all of them, then send all of them.
            // Afterwards, flush the buffer.
            let to_send = self.connections[token].message_queue.clone();
            self.connections[token].message_queue = Vec::new();
            if !to_send.is_empty() {
                for send in to_send {
                    let bytes = seralize_packet(&send);
                    self.connections[token]
                        .stream
                        .write(&bytes)
                        .expect(&format!("Error writing {:?} to connection {:?}/{:?}",
                                         send,
                                         token,
                                         self.connections[token]));
                }
                self.connections[token]
                    .stream
                    .flush()
                    .expect(&format!("Error flushing connection {:?}/{:?}",
                                     token,
                                     self.connections[token]));;
            }
        }

        if self.listener.is_some() {
            match self.listener.as_ref().unwrap().accept() {
                Ok(Some((socket, address))) => {
                    let token = self.connections.insert(Connection::new(socket)).unwrap();
                    send(event_loop,
                         NetworkPacket::Init { version: VERSION.to_owned() },
                         token);
                    info!("Accepted connection {}.", address);
                }
                Ok(None) => debug!("Recived Ok(None) in listener.accept()."),
                Err(error) => panic!("listener.accept() errored with {:?}!", error),
                // TODO: See if any of these errors can be handled better.
            }
        }
    }

    fn notify(&mut self, event_loop: &mut MioEventLoop<Handler>, msg: HandlerMessage) {
        match msg {
            HandlerMessage::AddStream(stream, tx) => {
                let token = self.connections.insert(Connection::new(stream)).unwrap();
                event_loop.register(&self.connections[token].stream,
                                    token,
                                    EventSet::all(),
                                    PollOpt::level())
                          .unwrap();
                tx.send(token).unwrap();
            }
            HandlerMessage::Send(packet, token) => {
                self.connections[token].message_queue.push(packet);
            }
        }
    }
}

fn add_socket(event_loop: &EventLoop, socket: TcpStream) -> Token {
    let (tx, rx) = channel();   // How expensive is this? Should I be creating a whole new channel for just 1 message?
    event_loop.channel().send(HandlerMessage::AddStream(socket, tx)).unwrap();
    rx.recv().unwrap() // I should feel bad.
}

/// Send a NetworkPacket over the network.
///
/// This is a static function instead of an impl function because you can't impl on external structs. In this case, mio::EventLoop.
pub fn send(event_loop: &EventLoop, to_send: NetworkPacket, token: Token) {
    event_loop.channel().send(HandlerMessage::Send(to_send, token)).unwrap();
}

fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}

#[derive(Debug)]
enum PacketDeseError {
    MagicNumberMismatch,
    InvalidEncoding(DeserializeError),
}

impl From<DeserializeError> for PacketDeseError {
    fn from(err: DeserializeError) -> PacketDeseError {
        PacketDeseError::InvalidEncoding(err)
    }
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, PacketDeseError> {
    Ok(try!(deserialize::<NetworkPacket>(to_de)))
}

fn handle_packet(to_handle: NetworkPacket, sender: Token, event_loop: &EventLoop) {
    match to_handle {
        NetworkPacket::Init{version} => {
            if version != VERSION {
                send(event_loop,
                     NetworkPacket::Error(NetworkError::VersionMismatch(version.to_owned(), VERSION.to_owned())),
                     sender)
            }
        }

        #[cfg(Test)]
        NetworkPacket::Test => unimplemented!(),

        NetworkPacket::Error(error) => if ::check_should_crash() { panic!(error) } else { unimplemented!() },
    }
}
<commit_msg>Fix compile error<commit_after>use std::convert::From;
use std::io;
use std::io::{Read, Write};
use std::sync::mpsc::{Sender, channel};
use std::fmt;
use std::fmt::{Display, Formatter};
use std::error::Error;
use std::net::SocketAddr;

use VERSION;

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use mio::{EventLoop as MioEventLoop, EventSet, Handler as MioHandler, PollOpt, Token};
use mio::tcp::{Shutdown, TcpListener, TcpStream};
use mio::util::Slab;
use slab::Index;

pub mod client;
pub mod server;
#[cfg(Test)]
pub mod test;

/// The default port for a server to listen on.
pub const STANDARD_PORT: u16 = 25566;
/// Standard number to ensure network connections are syncronized and the same protocol is being used.
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.
const MAX_CONNECTIONS: usize = 1024;

pub enum HandlerMessage {
    Send(NetworkPacket, Token),
    AddStream(TcpStream, Sender<Token>),
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        version: String,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
    /// Used to unit test networking. When recived, increments a value. TODO: Locate that value.
    #[cfg(test)]
    Test,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    VersionMismatch(String, String),
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => "VersionMismatch: The versions of the client and server attempting to connect mismatch.",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
        }
    }
}

pub type EventLoop = MioEventLoop<Handler>;
pub struct Handler {
    connections: Slab<Connection>,
    listener: Option<TcpListener>,
}

impl Handler {
    /// Creates a new instance of a Handler. Does not listen for connections.
    pub fn new() -> Self {
        Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: None,
        }
    }

    /// Creates a new instance of a Handler. Does listen for connections.
    pub fn new_listener(addr: &SocketAddr) -> Result<Self, io::Error> {
        Ok(Handler {
            connections: Slab::new_starting_at(Token::from_usize(1), MAX_CONNECTIONS),
            listener: Some(try!(TcpListener::bind(addr))),
        })
    }
}

#[derive(Debug)]
struct Connection {
    message_queue: Vec<NetworkPacket>,
    stream: TcpStream,
}

impl Connection {
    fn new(stream: TcpStream) -> Connection {
        Connection {
            stream: stream,
            message_queue: Vec::new(),
        }
    }
}

impl MioHandler for Handler {
    type Timeout = ();
    type Message = HandlerMessage;
    fn ready(&mut self, event_loop: &mut MioEventLoop<Handler>, token: Token, events: EventSet) {
        if events.is_readable() {
            // Read the 6 byte header of each packet, throw it into get_packet_length, then read that number of bytes.
            // Then throw those bytes into deserialize_packet. Afterwards, throw it to handle_packet.

            let mut header = [0; 6];
            self.connections[token]
                .stream
                .read(&mut header)
                .expect(&format!("An error occured reading from socket {:?}", token));    // TODO: Figure out possible errors and take care of them.
            let length = get_packet_length(header).unwrap_or(0);
            if length == 0 {
                event_loop.deregister(&self.connections[token].stream);
                self.connections[token].stream.shutdown(Shutdown::Both);
                self.connections.remove(token);
                // I directly kill the connection, becasue if the magic number doesn't match,
                // the peer probably doesn't share the same protocol. It wouldn't understand a normal error packet.
                return;
            }
            let mut packet = Vec::new();
            (&mut self.connections[token].stream).take(length as u64).read_to_end(&mut packet).unwrap();
            // I do this because Read.take takes a self, instead of a reasonable alternitive.
            // However &mut Read is it's self a Reader. So I use that instead.
            let dese = deserialize_packet(&packet).unwrap();
            handle_packet(dese, token, event_loop);
        }

        if events.is_writable() {
            // Get all the messages that should be send to that token, seralize all of them, then send all of them.
            // Afterwards, flush the buffer.
            let to_send = self.connections[token].message_queue.clone();
            self.connections[token].message_queue = Vec::new();
            if !to_send.is_empty() {
                for send in to_send {
                    let bytes = seralize_packet(&send);
                    self.connections[token]
                        .stream
                        .write(&bytes)
                        .expect(&format!("Error writing {:?} to connection {:?}/{:?}",
                                         send,
                                         token,
                                         self.connections[token]));
                }
                self.connections[token]
                    .stream
                    .flush()
                    .expect(&format!("Error flushing connection {:?}/{:?}",
                                     token,
                                     self.connections[token]));;
            }
        }

        if self.listener.is_some() {
            match self.listener.as_ref().unwrap().accept() {
                Ok(Some((socket, address))) => {
                    let token = self.connections.insert(Connection::new(socket)).unwrap();
                    send(event_loop,
                         NetworkPacket::Init { version: VERSION.to_owned() },
                         token);
                    info!("Accepted connection {}.", address);
                }
                Ok(None) => debug!("Recived Ok(None) in listener.accept()."),
                Err(error) => panic!("listener.accept() errored with {:?}!", error),
                // TODO: See if any of these errors can be handled better.
            }
        }
    }

    fn notify(&mut self, event_loop: &mut MioEventLoop<Handler>, msg: HandlerMessage) {
        match msg {
            HandlerMessage::AddStream(stream, tx) => {
                let token = self.connections.insert(Connection::new(stream)).unwrap();
                event_loop.register(&self.connections[token].stream,
                                    token,
                                    EventSet::all(),
                                    PollOpt::level())
                          .unwrap();
                tx.send(token).unwrap();
            }
            HandlerMessage::Send(packet, token) => {
                self.connections[token].message_queue.push(packet);
            }
        }
    }
}

fn add_socket(event_loop: &EventLoop, socket: TcpStream) -> Token {
    let (tx, rx) = channel();   // How expensive is this? Should I be creating a whole new channel for just 1 message?
    event_loop.channel().send(HandlerMessage::AddStream(socket, tx)).unwrap();
    rx.recv().unwrap() // I should feel bad.
}

/// Send a NetworkPacket over the network.
///
/// This is a static function instead of an impl function because you can't impl on external structs. In this case, mio::EventLoop.
pub fn send(event_loop: &EventLoop, to_send: NetworkPacket, token: Token) {
    event_loop.channel().send(HandlerMessage::Send(to_send, token)).unwrap();
}

fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}

#[derive(Debug)]
enum PacketDeseError {
    MagicNumberMismatch,
    InvalidEncoding(DeserializeError),
}

impl From<DeserializeError> for PacketDeseError {
    fn from(err: DeserializeError) -> PacketDeseError {
        PacketDeseError::InvalidEncoding(err)
    }
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, PacketDeseError> {
    Ok(try!(deserialize::<NetworkPacket>(to_de)))
}

fn handle_packet(to_handle: NetworkPacket, sender: Token, event_loop: &EventLoop) {
    match to_handle {
        NetworkPacket::Init{version} => {
            if version != VERSION {
                send(event_loop,
                     NetworkPacket::Error(NetworkError::VersionMismatch(version.to_owned(), VERSION.to_owned())),
                     sender)
            }
        }

        #[cfg(Test)]
        NetworkPacket::Test => unimplemented!(),

        NetworkPacket::Error(error) => if ::check_should_crash() { panic!(error) } else { unimplemented!() },
    }
}
<|endoftext|>


<commit_before>//! Contains code relating to networking.

#[cfg(test)]
mod test;

use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::io;
use std::net::{SocketAddr, ToSocketAddrs, TcpListener, TcpStream};
use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};

/// Standard number to ensure network connections are syncronized and the same protocol is being used.
///
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.

/// The maximum number of clients allowed to be connected at one time.
///
/// Eventually this should be removed and replaced with something configurable.
pub const MAX_CONNECTED_CLIENTS: usize = 30;

/// Holds all state for networking.
///
/// Has no notion of client or server. A client can listen, if that would ever be useful.
#[derive(Debug, Clone)]
pub struct Controller {
    pub raw: Arc<ControllerRaw>,
}

impl Controller {
    /// Contructs a new Controller, without any connection or listeners.
    ///
    /// This spawns a new thread to check multithreading channels.
    pub fn new_empty() -> Controller {
        let (tx, rx) = channel::<ControllerMessage>();
        let self_raw = Arc::from(ControllerRaw {
            listeners: Mutex::new(Vec::new()),
            connections: Mutex::new(Vec::new()),
            tx: Mutex::new(tx),
        });
        let self_raw_clone = self_raw.clone();
        thread::spawn(move || {
            check_channel(rx, self_raw_clone);
        });
        Controller {
            raw: self_raw
        }
    }

    /// Adds a new listener and spins up a new thread to check it.
    ///
    /// # Errors
    /// * A call to `listener.try_clone()` failed for some reason.
    pub fn add_listener(&mut self, listener: TcpListener) -> Result<(), io::Error> {
        let listener_clone = try!(listener.try_clone());
        let tx_clone = self.raw.tx.lock().unwrap().clone();
        thread::spawn(|| {
            check_listener(listener_clone, tx_clone);
        });
        self.raw.listeners.lock().unwrap().push(listener);
        Ok(())
    }
}

/// Raw representation of a controller. Used internally for things.
#[derive(Debug)]
pub struct ControllerRaw {
    pub listeners: Mutex<Vec<TcpListener>>,
    pub connections: Mutex<Vec<Connection>>,
    pub tx: Mutex<Sender<ControllerMessage>>,
}

#[derive(Debug)]
/// Represents a single connection without any notion of client or server.
///
/// It's own struct to allow for hooks and the like.
pub struct Connection {
    pub channel: Mutex<Sender<ConnectionMessage>>,
}

/// Sent in the case of an error that should be sent to the peer.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    /// If the versions mismatch sufficently to become incompatible with each other.
    VersionMismatch(String, String),
    /// If both peers have should_crash == false, then this error should be sent.
    ///
    /// Do note that this error should not be rewrapped into a reerror, since it would cause a loop.
    /// Instead, it should be logged and ignored, as the connection will be killed shortly after.
    ShouldCrashBothTrue,
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to \
                        connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
            NetworkError::ShouldCrashBothTrue => {
                write!(fmt,
                       "ShouldCrashBothTrue: Both peers have should_crash == false.")
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => {
                "VersionMismatch: The versions of the client and server attempting to connect \
                 mismatch."
            }
            NetworkError::ShouldCrashBothTrue => {
                "ShouldCrashBothTrue: Both peers have should_crash == false."
            }
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
            NetworkError::ShouldCrashBothTrue => None,
        }
    }
}

/// Messages that can be sent between peers to facilitate vairous actions.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        /// The curent version of the local game.
        ///
        /// Should be formatted according to Scematic Versioning.
        version: String,
        /// If the local game should crash when an error occours.
        ///
        /// Two peers should not have this as false, because should_crash will send the error to the
        /// remote peer and make it crash instead.
        /// This would cause a infinite loop if both were to do it.
        should_crash: bool,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
}

/// Message sent to a connection to do vairous actions.
#[derive(Debug, Clone, Copy)]
pub enum ConnectionMessage {
    DoNothing,
}

/// Channel message sent to controller to dictate certain actions.
#[derive(Debug, Clone)]
pub enum ControllerMessage {
    /// Add a socket, spinning up a new thread in the process.
    AddSocket(Sender<ConnectionMessage>, String),
}

/// Parses a str to a SocketAddr.
///
/// This is a function because while str implements ToSocketAddrs, it requires a good bit of boilerplate to use.
///
/// #Panics
/// * Calling with a localhost ip address: Use 127.0.0.1 instead.
/// * Calling with an ip address that resolves to more than 1 ip address.
pub fn ip(ip_addr: &str) -> SocketAddr {
    if ip_addr.starts_with("localhost") {
        panic!("because localhost can resolve to both 127.0.0.1, and the various IPV6 versions \
                of 127.0.0.1, it may not be used. please instead use 127.0.0.1");
    }
    let mut iter = ip_addr.to_socket_addrs().unwrap();
    let ip = iter.next().unwrap();
    if iter.next() != None {
        panic!("the given ip to net::ip() resolved to more than 1 SocketAddr");
    }
    ip
}

fn check_channel(rx: Receiver<ControllerMessage>, controller: Arc<ControllerRaw>) {
    loop {
        match rx.recv() {
            Ok(msg) => match msg {
                ControllerMessage::AddSocket(tx_connection, _addr) => {
                    // TODO: Add a hook allowing intersepting the addr and denying the connection.
                    controller.connections.lock().unwrap().push(Connection {
                        channel: Mutex::new(tx_connection),
                    });
                }
            },
            Err(_err) => {
                debug!("Channel connected to controller disconnected");
                break
            }
        }
    }
}

fn check_listener(listener: TcpListener, channel_: Sender<ControllerMessage>) {
    loop {
        match listener.accept() {
            Ok((stream, addr)) => {
                let (tx, rx) = channel();
                match channel_.send(ControllerMessage::AddSocket(tx, addr.to_string())) {
                    Ok(()) => {},
                    Err(_err) => {
                        debug!("listener {:?} stopped accepting because of channel close", listener);
                        break
                    },
                }
                thread::spawn(|| {
                    check_stream(rx, stream);
                });
            },
            Err(err) => panic!("{}", err),  // TODO: Better handle errors.
        }
    }
}

fn check_stream(_rx: Receiver<ConnectionMessage>, _stream: TcpStream) {
    unimplemented!()
}

#[allow(unused)]    // TODO: Remove allow(unused).
fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, DeserializeError> {
    deserialize(to_de)
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
#[allow(unused)]
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

#[allow(unused)]
fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}
<commit_msg>Refine a few function interfaces to better represent the networking architecture<commit_after>//! Contains code relating to networking.

#[cfg(test)]
mod test;

use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::io;
use std::net::{SocketAddr, ToSocketAddrs, TcpListener, TcpStream};
use std::thread;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};

use bincode::serde::{DeserializeError, deserialize, serialize};
use bincode::SizeLimit;
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};

/// Standard number to ensure network connections are syncronized and the same protocol is being used.
///
/// Reexported incase it is of use for something not-networking.
pub const NET_MAGIC_NUMBER: u32 = 0xCB011043; //0xcafebade + 0x25565, because programming references.

/// The maximum number of clients allowed to be connected at one time.
///
/// Eventually this should be removed and replaced with something configurable.
pub const MAX_CONNECTED_CLIENTS: usize = 30;

/// Holds all state for networking.
///
/// Has no notion of client or server. A client can listen, if that would ever be useful.
#[derive(Debug, Clone)]
pub struct Controller {
    pub raw: Arc<ControllerRaw>,
}

impl Controller {
    /// Contructs a new Controller, without any connection or listeners.
    ///
    /// This spawns a new thread to check multithreading channels.
    pub fn new_empty() -> Controller {
        let (tx, rx) = channel::<ControllerMessage>();
        let self_raw = Arc::from(ControllerRaw {
            listeners: Mutex::new(Vec::new()),
            connections: Mutex::new(Vec::new()),
            tx: Mutex::new(tx),
        });
        let self_raw_clone = self_raw.clone();
        thread::spawn(move || {
            check_controller_channel(rx, self_raw_clone);
        });
        Controller {
            raw: self_raw
        }
    }

    /// Adds a new listener and spins up a new thread to check it.
    ///
    /// # Errors
    /// * A call to `listener.try_clone()` failed for some reason.
    pub fn add_listener(&mut self, listener: TcpListener) -> Result<(), io::Error> {
        let listener_clone = try!(listener.try_clone());
        let tx_clone = self.raw.tx.lock().unwrap().clone();
        thread::spawn(|| {
            check_listener(listener_clone, tx_clone);
        });
        self.raw.listeners.lock().unwrap().push(listener);
        Ok(())
    }
}

/// Raw representation of a controller. Used internally for things.
#[derive(Debug)]
pub struct ControllerRaw {
    pub listeners: Mutex<Vec<TcpListener>>,
    pub connections: Mutex<Vec<Connection>>,
    pub tx: Mutex<Sender<ControllerMessage>>,
}

#[derive(Debug)]
/// Represents a single connection without any notion of client or server.
///
/// It's own struct to allow for hooks and the like.
pub struct Connection {
    pub channel: Mutex<Sender<ConnectionMessage>>,
}

/// Sent in the case of an error that should be sent to the peer.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkError {
    /// If the versions mismatch sufficently to become incompatible with each other.
    VersionMismatch(String, String),
    /// If both peers have should_crash == false, then this error should be sent.
    ///
    /// Do note that this error should not be rewrapped into a reerror, since it would cause a loop.
    /// Instead, it should be logged and ignored, as the connection will be killed shortly after.
    ShouldCrashBothTrue,
}

impl Display for NetworkError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            NetworkError::VersionMismatch(ref ver1, ref ver2) => {
                write!(fmt,
                       "VersionMismatch: The versions of the client and server attempting to \
                        connect mismatch. ver1: {}, ver2: {}",
                       ver1,
                       ver2)
            }
            NetworkError::ShouldCrashBothTrue => {
                write!(fmt,
                       "ShouldCrashBothTrue: Both peers have should_crash == false.")
            }
        }
    }
}

impl Error for NetworkError {
    fn description(&self) -> &str {
        match *self {
            NetworkError::VersionMismatch(_, _) => {
                "VersionMismatch: The versions of the client and server attempting to connect \
                 mismatch."
            }
            NetworkError::ShouldCrashBothTrue => {
                "ShouldCrashBothTrue: Both peers have should_crash == false."
            }
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            NetworkError::VersionMismatch(_, _) => None,
            NetworkError::ShouldCrashBothTrue => None,
        }
    }
}

/// Messages that can be sent between peers to facilitate vairous actions.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum NetworkPacket {
    /// Sent on connection to verify everything is in sync.
    Init {
        /// The curent version of the local game.
        ///
        /// Should be formatted according to Scematic Versioning.
        version: String,
        /// If the local game should crash when an error occours.
        ///
        /// Two peers should not have this as false, because should_crash will send the error to the
        /// remote peer and make it crash instead.
        /// This would cause a infinite loop if both were to do it.
        should_crash: bool,
    },
    /// An error that should crash the game and show an error to the user, but only on a client.
    Error(NetworkError),
}

/// Message sent to a connection to do vairous actions.
#[derive(Debug, Clone, Copy)]
pub enum ConnectionMessage {
    DoNothing,
}

/// Channel message sent to controller to dictate certain actions.
#[derive(Debug, Clone)]
pub enum ControllerMessage {
    /// Add a socket, spinning up a new thread in the process.
    AddSocket(Sender<ConnectionMessage>, String),
}

/// Parses a str to a SocketAddr.
///
/// This is a function because while str implements ToSocketAddrs, it requires a good bit of boilerplate to use.
///
/// #Panics
/// * Calling with a localhost ip address: Use 127.0.0.1 instead.
/// * Calling with an ip address that resolves to more than 1 ip address.
pub fn ip(ip_addr: &str) -> SocketAddr {
    if ip_addr.starts_with("localhost") {
        panic!("because localhost can resolve to both 127.0.0.1, and the various IPV6 versions \
                of 127.0.0.1, it may not be used. please instead use 127.0.0.1");
    }
    let mut iter = ip_addr.to_socket_addrs().unwrap();
    let ip = iter.next().unwrap();
    if iter.next() != None {
        panic!("the given ip to net::ip() resolved to more than 1 SocketAddr");
    }
    ip
}

fn check_controller_channel(rx: Receiver<ControllerMessage>, controller: Arc<ControllerRaw>) {
    loop {
        match rx.recv() {
            Ok(msg) => match msg {
                ControllerMessage::AddSocket(tx_connection, _addr) => {
                    // TODO: Add a hook allowing intersepting the addr and denying the connection.
                    controller.connections.lock().unwrap().push(Connection {
                        channel: Mutex::new(tx_connection),
                    });
                }
            },
            Err(_err) => {
                debug!("Channel connected to controller disconnected");
                break
            }
        }
    }
}

fn check_listener(listener: TcpListener, channel_: Sender<ControllerMessage>) {
    loop {
        match listener.accept() {
            Ok((stream, addr)) => {
                let (tx, rx) = channel();
                match channel_.send(ControllerMessage::AddSocket(tx, addr.to_string())) {
                    Ok(()) => {},
                    Err(_err) => {
                        debug!("listener {:?} stopped accepting because of channel close", listener);
                        break
                    },
                }
                let stream_clone = stream.try_clone().unwrap();
                thread::spawn(|| check_stream_send(rx, stream));
                thread::spawn(|| check_stream_recv(stream_clone));
            },
            Err(err) => panic!("{}", err),  // TODO: Better handle errors.
        }
    }
}

fn check_stream_send(rx: Receiver<ConnectionMessage>, stream: TcpStream) {
    unimplemented!()
}

fn check_stream_recv(stream: TcpStream) {
    unimplemented!()
}

#[allow(unused)]    // TODO: Remove allow(unused).
fn deserialize_packet(to_de: &[u8]) -> Result<NetworkPacket, DeserializeError> {
    deserialize(to_de)
}

/// Returns the length of a given packet, or a None if the first four bytes do not match NET_MAGIC_NUMBER.
#[allow(unused)]
fn get_packet_length(to_ln: [u8; 6]) -> Option<u16> {
    let (first_four, next_two) = to_ln.split_at(4);
    let should_be_magic_num = LittleEndian::read_u32(&first_four);
    if should_be_magic_num != NET_MAGIC_NUMBER {
        return None;
    }
    let length = LittleEndian::read_u16(&next_two);
    Some(length)
}

#[allow(unused)]
fn seralize_packet(to_ser: &NetworkPacket) -> Vec<u8> {
    let mut result: Vec<u8> = Vec::new();
    result.write_u32::<LittleEndian>(NET_MAGIC_NUMBER).unwrap();   // No possible errors here.
    // The NET_MAGIC_NUMBER is used before every packet, so incase the stream is desynced for whatever reason, the game doesn't just read arbratrary data and crash badly.
    // Instead, it can either recover somehow, by disconnecting and reconnecting, or just erroring gracefully.
    let mut encoded = serialize(to_ser, SizeLimit::Infinite).unwrap();
    // Since the size limit is infinite and i'm not encoding to a stream, there is no error and I can safely unwrap();
    result.write_u16::<LittleEndian>(encoded.len() as u16).unwrap();
    result.append(&mut encoded);
    result
}
<|endoftext|>