<commit_before>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use data_model::*;
use std;
use std::fmt::{self, Display};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::result;
use sys_util::{Error as SysError, EventFd};

use std::fs::File;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};

#[derive(Debug, PartialEq)]
/// An error during transaction or serialization/deserialization.
pub enum MsgError {
    /// Error while sending a request or response.
    Send(SysError),
    /// Error while receiving a request or response.
    Recv(SysError),
    /// The type of a received request or response is unknown.
    InvalidType,
    /// There was not the expected amount of data when receiving a message. The inner
    /// value is how much data is expected and how much data was actually received.
    BadRecvSize { expected: usize, actual: usize },
    /// There was no associated file descriptor received for a request that expected it.
    ExpectFd,
    /// There was some associated file descriptor received but not used when deserialize.
    NotExpectFd,
    /// Trying to serialize/deserialize, but fd buffer size is too small. This typically happens
    /// when max_fd_count() returns a value that is too small.
    WrongFdBufferSize,
    /// Trying to serialize/deserialize, but msg buffer size is too small. This typically happens
    /// when msg_size() returns a value that is too small.
    WrongMsgBufferSize,
}

pub type MsgResult<T> = result::Result<T, MsgError>;

impl Display for MsgError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::MsgError::*;

        match self {
            Send(e) => write!(f, "failed to send request or response: {}", e),
            Recv(e) => write!(f, "failed to receive request or response: {}", e),
            InvalidType => write!(f, "invalid type"),
            BadRecvSize { expected, actual } => write!(
                f,
                "wrong amount of data received; expected {} bytes; got {} bytes",
                expected, actual
            ),
            ExpectFd => write!(f, "missing associated file descriptor for request"),
            NotExpectFd => write!(f, "unexpected file descriptor is unused"),
            WrongFdBufferSize => write!(f, "fd buffer size too small"),
            WrongMsgBufferSize => write!(f, "msg buffer size too small"),
        }
    }
}

/// A msg that could be serialized to and deserialize from array in little endian.
///
/// For structs, we always have fixed size of bytes and fixed count of fds.
/// For enums, the size needed might be different for each variant.
///
/// e.g.
/// ```
/// use std::os::unix::io::RawFd;
/// enum Message {
///     VariantA(u8),
///     VariantB(u32, RawFd),
///     VariantC,
/// }
/// ```
///
/// For variant A, we need 1 byte to store its inner value.
/// For variant B, we need 4 bytes and 1 RawFd to store its inner value.
/// For variant C, we need 0 bytes to store its inner value.
/// When we serialize Message to (buffer, fd_buffer), we always use fixed number of bytes in
/// the buffer. Unused buffer bytes will be padded with zero.
/// However, for fd_buffer, we could not do the same thing. Otherwise, we are essentially sending
/// fd 0 through the socket.
/// Thus, read/write functions always the return correct count of fds in this variant. There will be
/// no padding in fd_buffer.
pub trait MsgOnSocket: Sized {
    /// Size of message in bytes.
    fn msg_size() -> usize;
    /// Max possible fd count in this type.
    fn max_fd_count() -> usize {
        0
    }
    /// Returns (self, fd read count).
    /// This function is safe only when:
    ///     0. fds contains valid fds, received from socket, serialized by Self::write_to_buffer.
    ///     1. For enum, fds contains correct fd layout of the particular variant.
    ///     2. write_to_buffer is implemented correctly(put valid fds into the buffer, has no padding,
    ///        return correct count).
    unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)>;
    /// Serialize self to buffers.
    fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize>;
}

impl MsgOnSocket for SysError {
    fn msg_size() -> usize {
        u32::msg_size()
    }
    unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        let (v, size) = u32::read_from_buffer(buffer, fds)?;
        Ok((SysError::new(v as i32), size))
    }
    fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
        let v = self.errno() as u32;
        v.write_to_buffer(buffer, fds)
    }
}

impl MsgOnSocket for RawFd {
    fn msg_size() -> usize {
        0
    }
    fn max_fd_count() -> usize {
        1
    }
    unsafe fn read_from_buffer(_buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        if fds.is_empty() {
            return Err(MsgError::ExpectFd);
        }
        Ok((fds[0], 1))
    }
    fn write_to_buffer(&self, _buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
        if fds.is_empty() {
            return Err(MsgError::WrongFdBufferSize);
        }
        fds[0] = *self;
        Ok(1)
    }
}

macro_rules! rawfd_impl {
    ($type:ident) => {
        impl MsgOnSocket for $type {
            fn msg_size() -> usize {
                0
            }
            fn max_fd_count() -> usize {
                1
            }
            unsafe fn read_from_buffer(_buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
                if fds.len() < 1 {
                    return Err(MsgError::ExpectFd);
                }
                Ok(($type::from_raw_fd(fds[0].clone()), 1))
            }
            fn write_to_buffer(&self, _buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
                if fds.len() < 1 {
                    return Err(MsgError::WrongFdBufferSize);
                }
                fds[0] = self.as_raw_fd();
                Ok(1)
            }
        }
    };
}

rawfd_impl!(EventFd);
rawfd_impl!(File);
rawfd_impl!(UnixStream);
rawfd_impl!(TcpStream);
rawfd_impl!(TcpListener);
rawfd_impl!(UdpSocket);
rawfd_impl!(UnixListener);
rawfd_impl!(UnixDatagram);

// This trait is unsafe as it use uninitialized memory.
// Please only implement it for primitive types.
unsafe trait AlignedNew: Sized + DataInit {
    unsafe fn from_unaligned(buffer: &[u8]) -> Option<Self> {
        let mut value = std::mem::uninitialized::<Self>();
        {
            let value_mem = value.as_mut_slice();
            if value_mem.len() != buffer.len() {
                return None;
            }
            value_mem.copy_from_slice(buffer);
        }
        Some(value)
    }
}

unsafe impl AlignedNew for u8 {}
unsafe impl AlignedNew for u16 {}
unsafe impl AlignedNew for u32 {}
unsafe impl AlignedNew for u64 {}

unsafe impl AlignedNew for Le16 {}
unsafe impl AlignedNew for Le32 {}
unsafe impl AlignedNew for Le64 {}

// usize could be different sizes on different targets. We always use u64.
impl MsgOnSocket for usize {
    fn msg_size() -> usize {
        std::mem::size_of::<u64>()
    }
    unsafe fn read_from_buffer(buffer: &[u8], _fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        if buffer.len() < std::mem::size_of::<u64>() {
            return Err(MsgError::WrongMsgBufferSize);
        }
        let t: u64 = Le64::from_unaligned(&buffer[0..Self::msg_size()])
            .unwrap()
            .into();
        Ok((t as usize, 0))
    }

    fn write_to_buffer(&self, buffer: &mut [u8], _fds: &mut [RawFd]) -> MsgResult<usize> {
        if buffer.len() < std::mem::size_of::<u64>() {
            return Err(MsgError::WrongMsgBufferSize);
        }
        let t: Le64 = (*self as u64).into();
        buffer[0..Self::msg_size()].copy_from_slice(t.as_slice());
        Ok(0)
    }
}

macro_rules! le_impl {
    ($type:ident, $le_type:ident) => {
        impl MsgOnSocket for $type {
            fn msg_size() -> usize {
                std::mem::size_of::<$le_type>()
            }
            unsafe fn read_from_buffer(buffer: &[u8], _fds: &[RawFd]) -> MsgResult<(Self, usize)> {
                if buffer.len() < std::mem::size_of::<$le_type>() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let t = $le_type::from_unaligned(&buffer[0..Self::msg_size()]).unwrap();
                Ok((t.into(), 0))
            }

            fn write_to_buffer(&self, buffer: &mut [u8], _fds: &mut [RawFd]) -> MsgResult<usize> {
                if buffer.len() < std::mem::size_of::<$le_type>() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let t: $le_type = self.clone().into();
                buffer[0..Self::msg_size()].copy_from_slice(t.as_slice());
                Ok(0)
            }
        }
    };
}

le_impl!(u8, u8);
le_impl!(u16, Le16);
le_impl!(u32, Le32);
le_impl!(u64, Le64);

le_impl!(Le16, Le16);
le_impl!(Le32, Le32);
le_impl!(Le64, Le64);

macro_rules! array_impls {
    ($N:expr, $t: ident $($ts:ident)*)
    => {
        impl<T: MsgOnSocket + Clone> MsgOnSocket for [T; $N] {
            fn msg_size() -> usize {
                T::msg_size() * $N
            }
            fn max_fd_count() -> usize {
                T::max_fd_count() * $N
            }
            unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
                if buffer.len() < Self::msg_size() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let mut offset = 0usize;
                let mut fd_offset = 0usize;
                let ($t, fd_size) =
                    T::read_from_buffer(&buffer[offset..], &fds[fd_offset..])?;
                offset += T::msg_size();
                fd_offset += fd_size;
                $(
                    let ($ts, fd_size) =
                        T::read_from_buffer(&buffer[offset..], &fds[fd_offset..])?;
                    offset += T::msg_size();
                    fd_offset += fd_size;
                    )*
                assert_eq!(offset, Self::msg_size());
                Ok(([$t, $($ts),*], fd_offset))
            }

            fn write_to_buffer(
                &self,
                buffer: &mut [u8],
                fds: &mut [RawFd],
                ) -> MsgResult<usize> {
                if buffer.len() < Self::msg_size() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let mut offset = 0usize;
                let mut fd_offset = 0usize;
                for idx in 0..$N {
                    let fd_size = self[idx].clone().write_to_buffer(&mut buffer[offset..],
                                                            &mut fds[fd_offset..])?;
                    offset += T::msg_size();
                    fd_offset += fd_size;
                }

                Ok(fd_offset)
            }
        }
        array_impls!(($N - 1), $($ts)*);
    };
    {$N:expr, } => {};
}

array_impls! {
    32, tmp1 tmp2 tmp3 tmp4 tmp5 tmp6 tmp7 tmp8 tmp9 tmp10 tmp11 tmp12 tmp13 tmp14 tmp15 tmp16
        tmp17 tmp18 tmp19 tmp20 tmp21 tmp22 tmp23 tmp24 tmp25 tmp26 tmp27 tmp28 tmp29 tmp30 tmp31
        tmp32
}

// TODO(jkwang) Define MsgOnSocket for tuple?
<commit_msg>msg_socket: implement MsgOnSocket for Option<MsgOnSocket><commit_after>// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use data_model::*;
use std;
use std::fmt::{self, Display};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::result;
use sys_util::{Error as SysError, EventFd};

use std::fs::File;
use std::net::{TcpListener, TcpStream, UdpSocket};
use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};

#[derive(Debug, PartialEq)]
/// An error during transaction or serialization/deserialization.
pub enum MsgError {
    /// Error while sending a request or response.
    Send(SysError),
    /// Error while receiving a request or response.
    Recv(SysError),
    /// The type of a received request or response is unknown.
    InvalidType,
    /// There was not the expected amount of data when receiving a message. The inner
    /// value is how much data is expected and how much data was actually received.
    BadRecvSize { expected: usize, actual: usize },
    /// There was no associated file descriptor received for a request that expected it.
    ExpectFd,
    /// There was some associated file descriptor received but not used when deserialize.
    NotExpectFd,
    /// Trying to serialize/deserialize, but fd buffer size is too small. This typically happens
    /// when max_fd_count() returns a value that is too small.
    WrongFdBufferSize,
    /// Trying to serialize/deserialize, but msg buffer size is too small. This typically happens
    /// when msg_size() returns a value that is too small.
    WrongMsgBufferSize,
}

pub type MsgResult<T> = result::Result<T, MsgError>;

impl Display for MsgError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::MsgError::*;

        match self {
            Send(e) => write!(f, "failed to send request or response: {}", e),
            Recv(e) => write!(f, "failed to receive request or response: {}", e),
            InvalidType => write!(f, "invalid type"),
            BadRecvSize { expected, actual } => write!(
                f,
                "wrong amount of data received; expected {} bytes; got {} bytes",
                expected, actual
            ),
            ExpectFd => write!(f, "missing associated file descriptor for request"),
            NotExpectFd => write!(f, "unexpected file descriptor is unused"),
            WrongFdBufferSize => write!(f, "fd buffer size too small"),
            WrongMsgBufferSize => write!(f, "msg buffer size too small"),
        }
    }
}

/// A msg that could be serialized to and deserialize from array in little endian.
///
/// For structs, we always have fixed size of bytes and fixed count of fds.
/// For enums, the size needed might be different for each variant.
///
/// e.g.
/// ```
/// use std::os::unix::io::RawFd;
/// enum Message {
///     VariantA(u8),
///     VariantB(u32, RawFd),
///     VariantC,
/// }
/// ```
///
/// For variant A, we need 1 byte to store its inner value.
/// For variant B, we need 4 bytes and 1 RawFd to store its inner value.
/// For variant C, we need 0 bytes to store its inner value.
/// When we serialize Message to (buffer, fd_buffer), we always use fixed number of bytes in
/// the buffer. Unused buffer bytes will be padded with zero.
/// However, for fd_buffer, we could not do the same thing. Otherwise, we are essentially sending
/// fd 0 through the socket.
/// Thus, read/write functions always the return correct count of fds in this variant. There will be
/// no padding in fd_buffer.
pub trait MsgOnSocket: Sized {
    /// Size of message in bytes.
    fn msg_size() -> usize;
    /// Max possible fd count in this type.
    fn max_fd_count() -> usize {
        0
    }
    /// Returns (self, fd read count).
    /// This function is safe only when:
    ///     0. fds contains valid fds, received from socket, serialized by Self::write_to_buffer.
    ///     1. For enum, fds contains correct fd layout of the particular variant.
    ///     2. write_to_buffer is implemented correctly(put valid fds into the buffer, has no padding,
    ///        return correct count).
    unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)>;
    /// Serialize self to buffers.
    fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize>;
}

impl MsgOnSocket for SysError {
    fn msg_size() -> usize {
        u32::msg_size()
    }
    unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        let (v, size) = u32::read_from_buffer(buffer, fds)?;
        Ok((SysError::new(v as i32), size))
    }
    fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
        let v = self.errno() as u32;
        v.write_to_buffer(buffer, fds)
    }
}

impl MsgOnSocket for RawFd {
    fn msg_size() -> usize {
        0
    }
    fn max_fd_count() -> usize {
        1
    }
    unsafe fn read_from_buffer(_buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        if fds.is_empty() {
            return Err(MsgError::ExpectFd);
        }
        Ok((fds[0], 1))
    }
    fn write_to_buffer(&self, _buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
        if fds.is_empty() {
            return Err(MsgError::WrongFdBufferSize);
        }
        fds[0] = *self;
        Ok(1)
    }
}

impl<T: MsgOnSocket> MsgOnSocket for Option<T> {
    fn msg_size() -> usize {
        T::msg_size() + 1
    }

    fn max_fd_count() -> usize {
        T::max_fd_count()
    }

    unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        match buffer[0] {
            0 => Ok((None, 0)),
            1 => {
                let (inner, len) = T::read_from_buffer(&buffer[1..], fds)?;
                Ok((Some(inner), len))
            }
            _ => Err(MsgError::InvalidType),
        }
    }

    fn write_to_buffer(&self, buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
        match self {
            None => {
                buffer[0] = 0;
                Ok(0)
            }
            Some(inner) => {
                buffer[0] = 1;
                inner.write_to_buffer(&mut buffer[1..], fds)
            }
        }
    }
}

macro_rules! rawfd_impl {
    ($type:ident) => {
        impl MsgOnSocket for $type {
            fn msg_size() -> usize {
                0
            }
            fn max_fd_count() -> usize {
                1
            }
            unsafe fn read_from_buffer(_buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
                if fds.len() < 1 {
                    return Err(MsgError::ExpectFd);
                }
                Ok(($type::from_raw_fd(fds[0].clone()), 1))
            }
            fn write_to_buffer(&self, _buffer: &mut [u8], fds: &mut [RawFd]) -> MsgResult<usize> {
                if fds.len() < 1 {
                    return Err(MsgError::WrongFdBufferSize);
                }
                fds[0] = self.as_raw_fd();
                Ok(1)
            }
        }
    };
}

rawfd_impl!(EventFd);
rawfd_impl!(File);
rawfd_impl!(UnixStream);
rawfd_impl!(TcpStream);
rawfd_impl!(TcpListener);
rawfd_impl!(UdpSocket);
rawfd_impl!(UnixListener);
rawfd_impl!(UnixDatagram);

// This trait is unsafe as it use uninitialized memory.
// Please only implement it for primitive types.
unsafe trait AlignedNew: Sized + DataInit {
    unsafe fn from_unaligned(buffer: &[u8]) -> Option<Self> {
        let mut value = std::mem::uninitialized::<Self>();
        {
            let value_mem = value.as_mut_slice();
            if value_mem.len() != buffer.len() {
                return None;
            }
            value_mem.copy_from_slice(buffer);
        }
        Some(value)
    }
}

unsafe impl AlignedNew for u8 {}
unsafe impl AlignedNew for u16 {}
unsafe impl AlignedNew for u32 {}
unsafe impl AlignedNew for u64 {}

unsafe impl AlignedNew for Le16 {}
unsafe impl AlignedNew for Le32 {}
unsafe impl AlignedNew for Le64 {}

// usize could be different sizes on different targets. We always use u64.
impl MsgOnSocket for usize {
    fn msg_size() -> usize {
        std::mem::size_of::<u64>()
    }
    unsafe fn read_from_buffer(buffer: &[u8], _fds: &[RawFd]) -> MsgResult<(Self, usize)> {
        if buffer.len() < std::mem::size_of::<u64>() {
            return Err(MsgError::WrongMsgBufferSize);
        }
        let t: u64 = Le64::from_unaligned(&buffer[0..Self::msg_size()])
            .unwrap()
            .into();
        Ok((t as usize, 0))
    }

    fn write_to_buffer(&self, buffer: &mut [u8], _fds: &mut [RawFd]) -> MsgResult<usize> {
        if buffer.len() < std::mem::size_of::<u64>() {
            return Err(MsgError::WrongMsgBufferSize);
        }
        let t: Le64 = (*self as u64).into();
        buffer[0..Self::msg_size()].copy_from_slice(t.as_slice());
        Ok(0)
    }
}

macro_rules! le_impl {
    ($type:ident, $le_type:ident) => {
        impl MsgOnSocket for $type {
            fn msg_size() -> usize {
                std::mem::size_of::<$le_type>()
            }
            unsafe fn read_from_buffer(buffer: &[u8], _fds: &[RawFd]) -> MsgResult<(Self, usize)> {
                if buffer.len() < std::mem::size_of::<$le_type>() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let t = $le_type::from_unaligned(&buffer[0..Self::msg_size()]).unwrap();
                Ok((t.into(), 0))
            }

            fn write_to_buffer(&self, buffer: &mut [u8], _fds: &mut [RawFd]) -> MsgResult<usize> {
                if buffer.len() < std::mem::size_of::<$le_type>() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let t: $le_type = self.clone().into();
                buffer[0..Self::msg_size()].copy_from_slice(t.as_slice());
                Ok(0)
            }
        }
    };
}

le_impl!(u8, u8);
le_impl!(u16, Le16);
le_impl!(u32, Le32);
le_impl!(u64, Le64);

le_impl!(Le16, Le16);
le_impl!(Le32, Le32);
le_impl!(Le64, Le64);

macro_rules! array_impls {
    ($N:expr, $t: ident $($ts:ident)*)
    => {
        impl<T: MsgOnSocket + Clone> MsgOnSocket for [T; $N] {
            fn msg_size() -> usize {
                T::msg_size() * $N
            }
            fn max_fd_count() -> usize {
                T::max_fd_count() * $N
            }
            unsafe fn read_from_buffer(buffer: &[u8], fds: &[RawFd]) -> MsgResult<(Self, usize)> {
                if buffer.len() < Self::msg_size() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let mut offset = 0usize;
                let mut fd_offset = 0usize;
                let ($t, fd_size) =
                    T::read_from_buffer(&buffer[offset..], &fds[fd_offset..])?;
                offset += T::msg_size();
                fd_offset += fd_size;
                $(
                    let ($ts, fd_size) =
                        T::read_from_buffer(&buffer[offset..], &fds[fd_offset..])?;
                    offset += T::msg_size();
                    fd_offset += fd_size;
                    )*
                assert_eq!(offset, Self::msg_size());
                Ok(([$t, $($ts),*], fd_offset))
            }

            fn write_to_buffer(
                &self,
                buffer: &mut [u8],
                fds: &mut [RawFd],
                ) -> MsgResult<usize> {
                if buffer.len() < Self::msg_size() {
                    return Err(MsgError::WrongMsgBufferSize);
                }
                let mut offset = 0usize;
                let mut fd_offset = 0usize;
                for idx in 0..$N {
                    let fd_size = self[idx].clone().write_to_buffer(&mut buffer[offset..],
                                                            &mut fds[fd_offset..])?;
                    offset += T::msg_size();
                    fd_offset += fd_size;
                }

                Ok(fd_offset)
            }
        }
        array_impls!(($N - 1), $($ts)*);
    };
    {$N:expr, } => {};
}

array_impls! {
    32, tmp1 tmp2 tmp3 tmp4 tmp5 tmp6 tmp7 tmp8 tmp9 tmp10 tmp11 tmp12 tmp13 tmp14 tmp15 tmp16
        tmp17 tmp18 tmp19 tmp20 tmp21 tmp22 tmp23 tmp24 tmp25 tmp26 tmp27 tmp28 tmp29 tmp30 tmp31
        tmp32
}

// TODO(jkwang) Define MsgOnSocket for tuple?
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::vm_status::StatusCode;
use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;

/// This is the generic struct we use for all API errors, it contains a string
/// message and an Aptos API specific error code.
#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct AptosError {
    /// A message describing the error
    pub message: String,
    pub error_code: AptosErrorCode,
    /// A code providing VM error details when submitting transactions to the VM
    pub vm_error_code: Option<u64>,
}

impl std::fmt::Display for AptosError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "Error({:?}): {}", self.error_code, self.message)
    }
}

impl std::error::Error for AptosError {}

impl AptosError {
    pub fn new_with_error_code<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: None,
        }
    }

    pub fn new_with_vm_status<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
        vm_error_code: StatusCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: Some(vm_error_code as u64),
        }
    }
}

/// These codes provide more granular error information beyond just the HTTP
/// status code of the response.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Enum)]
#[oai(rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
#[repr(u32)]
pub enum AptosErrorCode {
    /// Account not found at the requested version
    AccountNotFound = 101,
    /// Resource not found at the requested version
    ResourceNotFound = 102,
    /// Module not found at the requested version
    ModuleNotFound = 103,
    /// Struct field not found at the requested version
    StructFieldNotFound = 104,
    /// Ledger version not found at the requested version
    ///
    /// Usually means that the version is ahead of the latest version
    VersionNotFound = 105,
    /// Transaction not found at the requested version or with the requested hash
    TransactionNotFound = 106,
    /// Table item not found at the requested version
    TableItemNotFound = 107,
    /// Block not found at the requested version or height
    ///
    /// Usually means the block is fully or partially pruned or the height / version is ahead
    /// of the latest version
    BlockNotFound = 108,

    /// Ledger version is pruned
    VersionPruned = 200,
    /// Block is fully or partially pruned
    BlockPruned = 201,

    /// The API's inputs were invalid
    InvalidInput = 300,

    /// The transaction was an invalid update to an already submitted transaction.
    InvalidTransactionUpdate = 401,
    /// The sequence number for the transaction is behind the latest sequence number.
    SequenceNumberTooOld = 402,
    /// The submitted transaction failed VM checks.
    VmError = 403,

    /// Health check failed.
    HealthCheckFailed = 500,
    /// The mempool is full, no new transactions can be submitted.
    MempoolIsFull = 501,

    /// Internal server error
    InternalError = 600,
    /// Error from the web framework
    WebFrameworkError = 601,
    /// BCS format is not supported on this API.
    BcsNotSupported = 602,
    /// API Disabled
    ApiDisabled = 603,
}

impl AptosErrorCode {
    pub fn as_u32(&self) -> u32 {
        *self as u32
    }
}

#[test]
fn test_serialize_deserialize() {
    let with_code = AptosError::new_with_vm_status(
        "Invalid transaction",
        AptosErrorCode::VmError,
        aptos_types::vm_status::StatusCode::UNKNOWN_MODULE,
    );
    let _: AptosError = bcs::from_bytes(&bcs::to_bytes(&with_code).unwrap()).unwrap();
    let _: AptosError = serde_json::from_str(&serde_json::to_string(&with_code).unwrap()).unwrap();

    let without_code =
        AptosError::new_with_error_code("some message", AptosErrorCode::MempoolIsFull);
    let _: AptosError = bcs::from_bytes(&bcs::to_bytes(&without_code).unwrap()).unwrap();
    let _: AptosError =
        serde_json::from_str(&serde_json::to_string(&without_code).unwrap()).unwrap();
}
<commit_msg>[api] Ensure error messages have full context<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::vm_status::StatusCode;
use poem_openapi::{Enum, Object};
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;

/// This is the generic struct we use for all API errors, it contains a string
/// message and an Aptos API specific error code.
#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct AptosError {
    /// A message describing the error
    pub message: String,
    pub error_code: AptosErrorCode,
    /// A code providing VM error details when submitting transactions to the VM
    pub vm_error_code: Option<u64>,
}

impl std::fmt::Display for AptosError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "Error({:?}): {:#}", self.error_code, self.message)
    }
}

impl std::error::Error for AptosError {}

impl AptosError {
    pub fn new_with_error_code<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
    ) -> AptosError {
        Self {
            message: format!("{:#}", error),
            error_code,
            vm_error_code: None,
        }
    }

    pub fn new_with_vm_status<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
        vm_error_code: StatusCode,
    ) -> AptosError {
        Self {
            message: format!("{:#}", error),
            error_code,
            vm_error_code: Some(vm_error_code as u64),
        }
    }
}

/// These codes provide more granular error information beyond just the HTTP
/// status code of the response.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, Enum)]
#[oai(rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
#[repr(u32)]
pub enum AptosErrorCode {
    /// Account not found at the requested version
    AccountNotFound = 101,
    /// Resource not found at the requested version
    ResourceNotFound = 102,
    /// Module not found at the requested version
    ModuleNotFound = 103,
    /// Struct field not found at the requested version
    StructFieldNotFound = 104,
    /// Ledger version not found at the requested version
    ///
    /// Usually means that the version is ahead of the latest version
    VersionNotFound = 105,
    /// Transaction not found at the requested version or with the requested hash
    TransactionNotFound = 106,
    /// Table item not found at the requested version
    TableItemNotFound = 107,
    /// Block not found at the requested version or height
    ///
    /// Usually means the block is fully or partially pruned or the height / version is ahead
    /// of the latest version
    BlockNotFound = 108,

    /// Ledger version is pruned
    VersionPruned = 200,
    /// Block is fully or partially pruned
    BlockPruned = 201,

    /// The API's inputs were invalid
    InvalidInput = 300,

    /// The transaction was an invalid update to an already submitted transaction.
    InvalidTransactionUpdate = 401,
    /// The sequence number for the transaction is behind the latest sequence number.
    SequenceNumberTooOld = 402,
    /// The submitted transaction failed VM checks.
    VmError = 403,

    /// Health check failed.
    HealthCheckFailed = 500,
    /// The mempool is full, no new transactions can be submitted.
    MempoolIsFull = 501,

    /// Internal server error
    InternalError = 600,
    /// Error from the web framework
    WebFrameworkError = 601,
    /// BCS format is not supported on this API.
    BcsNotSupported = 602,
    /// API Disabled
    ApiDisabled = 603,
}

impl AptosErrorCode {
    pub fn as_u32(&self) -> u32 {
        *self as u32
    }
}

#[test]
fn test_serialize_deserialize() {
    let with_code = AptosError::new_with_vm_status(
        "Invalid transaction",
        AptosErrorCode::VmError,
        aptos_types::vm_status::StatusCode::UNKNOWN_MODULE,
    );
    let _: AptosError = bcs::from_bytes(&bcs::to_bytes(&with_code).unwrap()).unwrap();
    let _: AptosError = serde_json::from_str(&serde_json::to_string(&with_code).unwrap()).unwrap();

    let without_code =
        AptosError::new_with_error_code("some message", AptosErrorCode::MempoolIsFull);
    let _: AptosError = bcs::from_bytes(&bcs::to_bytes(&without_code).unwrap()).unwrap();
    let _: AptosError =
        serde_json::from_str(&serde_json::to_string(&without_code).unwrap()).unwrap();
}
<|endoftext|>


<commit_before>use clap::App;
use std::default::Default;
use thud_game;
use thud_ui_common;
use thud_ui_console;

fn main() {
  let mut agents = thud_ui_common::agent_registry::AgentRegistry::new();
  agents
    .register(Box::new(
      thud_ui_common::agent_registry::StdinAgentBuilder::new(),
    ))
    .register(Box::new(
      thud_ui_common::agent_registry::mcts::MctsAgentBuilder::new("mcts"),
    ))
    .register(Box::new(
      thud_ui_common::agent_registry::FileAgentBuilder::new("file_agent"),
    ));

  // Set up arg handling.
  let matches = {
    let mut app = thud_ui_common::set_args(
      App::new("console_play")
        .version("0.1.0")
        .author("Stu Black <trurl@freeshell.org>")
        .about("Play Thud on the console"),
      &[
        thud_ui_common::FLAG_INITIAL_BOARD,
        thud_ui_common::FLAG_INITIAL_PLAYER,
        thud_ui_common::FLAG_LOG_LEVEL,
      ],
    );
    app = agents.register_args(app);
    app.get_matches()
  };
  let initial_cells = match matches
    .value_of(thud_ui_common::FLAG_INITIAL_BOARD)
    .map(|x| x.parse::<thud_ui_common::InitialBoard>())
  {
    None => thud_game::board::Cells::default(),
    Some(Ok(x)) => x.cells(),
    Some(Err(e)) => panic!("Bad initial board configuration: {}", e),
  };
  let logging_level = match matches
    .value_of(thud_ui_common::FLAG_LOG_LEVEL)
    .map(|x| x.parse::<log::LevelFilter>())
  {
    Some(Ok(x)) => x,
    Some(Err(_)) => panic!(
      "Bad logging level '{}'",
      matches.value_of(thud_ui_common::FLAG_LOG_LEVEL).unwrap()
    ),
    None => log::LevelFilter::Info,
  };

  // Set up logging.
  thud_ui_common::init::init_logger(logging_level);

  let mut agent1 = agents.get_player_1_from_arguments(&matches).unwrap();
  let mut agent2 = agents.get_player_2_from_arguments(&matches).unwrap();
  let mut state = thud_game::state::State::new(
    initial_cells,
    &thud_game::board::TRANSPOSITIONAL_EQUIVALENCE,
  );
  while !state.terminated() {
    let action = agent1.propose_action(&state).unwrap();
    state.do_action(&action);
    if state.terminated() {
      break;
    }
    let action = agent2.propose_action(&state).unwrap();
    state.do_action(&action);
  }

  // // Prompt for play.
  // loop {
  //   println!(
  //     "{:?} player's turn. Enter coordinate of piece to move.",
  //     human_role
  //   );
  //   let c = thud_ui_console::prompt_for_piece(state.cells(), human_role);
  //   let piece_actions: Vec<thud_game::Action> = state.position_actions(c).collect();
  //   if piece_actions.is_empty() {
  //     println!("Piece at {:?} has no actions.", c);
  //   } else {
  //     if let Some(action) = thud_ui_console::select_one(&piece_actions) {
  //       let mut moved_state = state.clone();
  //       moved_state.do_action(&action);
  //       println!(
  //         "After action, board: {}",
  //         thud_game::board::format_board(moved_state.cells())
  //       );
  //       println!("Is this okay?");
  //       match thud_ui_console::select_one(&["y", "n"]) {
  //         Some(&"y") => {
  //           state = moved_state;
  //           graph.retain_reachable_from(&[&state]);
  //           break;
  //         }
  //         _ => continue,
  //       }
  //     }
  //   }
  // }
}
<commit_msg>Display game state and actions taken in console_play.<commit_after>use clap::App;
use std::default::Default;
use thud_game;
use thud_ui_common;
use thud_ui_console;

fn main() {
  let mut agents = thud_ui_common::agent_registry::AgentRegistry::new();
  agents
    .register(Box::new(
      thud_ui_common::agent_registry::StdinAgentBuilder::new(),
    ))
    .register(Box::new(
      thud_ui_common::agent_registry::mcts::MctsAgentBuilder::new("mcts"),
    ))
    .register(Box::new(
      thud_ui_common::agent_registry::FileAgentBuilder::new("file_agent"),
    ));

  // Set up arg handling.
  let matches = {
    let mut app = thud_ui_common::set_args(
      App::new("console_play")
        .version("0.1.0")
        .author("Stu Black <trurl@freeshell.org>")
        .about("Play Thud on the console"),
      &[
        thud_ui_common::FLAG_INITIAL_BOARD,
        thud_ui_common::FLAG_INITIAL_PLAYER,
        thud_ui_common::FLAG_LOG_LEVEL,
      ],
    );
    app = agents.register_args(app);
    app.get_matches()
  };
  let initial_cells = match matches
    .value_of(thud_ui_common::FLAG_INITIAL_BOARD)
    .map(|x| x.parse::<thud_ui_common::InitialBoard>())
  {
    None => thud_game::board::Cells::default(),
    Some(Ok(x)) => x.cells(),
    Some(Err(e)) => panic!("Bad initial board configuration: {}", e),
  };
  let logging_level = match matches
    .value_of(thud_ui_common::FLAG_LOG_LEVEL)
    .map(|x| x.parse::<log::LevelFilter>())
  {
    Some(Ok(x)) => x,
    Some(Err(_)) => panic!(
      "Bad logging level '{}'",
      matches.value_of(thud_ui_common::FLAG_LOG_LEVEL).unwrap()
    ),
    None => log::LevelFilter::Info,
  };

  // Set up logging.
  thud_ui_common::init::init_logger(logging_level);

  let mut agent1 = agents.get_player_1_from_arguments(&matches).unwrap();
  let mut agent2 = agents.get_player_2_from_arguments(&matches).unwrap();
  let mut state = thud_game::state::State::new(
    initial_cells,
    &thud_game::board::TRANSPOSITIONAL_EQUIVALENCE,
  );
  while !state.terminated() {
    println!("state: {:?}", state);
    let action = agent1.propose_action(&state).unwrap();
    println!("agent 1 proposes action: {:?}", action);
    state.do_action(&action);
    println!("state: {:?}", state);
    if state.terminated() {
      break;
    }
    let action = agent2.propose_action(&state).unwrap();
    println!("agent 2 proposes action: {:?}", action);
    state.do_action(&action);
  }
  println!("state has terminated");

  // // Prompt for play.
  // loop {
  //   println!(
  //     "{:?} player's turn. Enter coordinate of piece to move.",
  //     human_role
  //   );
  //   let c = thud_ui_console::prompt_for_piece(state.cells(), human_role);
  //   let piece_actions: Vec<thud_game::Action> = state.position_actions(c).collect();
  //   if piece_actions.is_empty() {
  //     println!("Piece at {:?} has no actions.", c);
  //   } else {
  //     if let Some(action) = thud_ui_console::select_one(&piece_actions) {
  //       let mut moved_state = state.clone();
  //       moved_state.do_action(&action);
  //       println!(
  //         "After action, board: {}",
  //         thud_game::board::format_board(moved_state.cells())
  //       );
  //       println!("Is this okay?");
  //       match thud_ui_console::select_one(&["y", "n"]) {
  //         Some(&"y") => {
  //           state = moved_state;
  //           graph.retain_reachable_from(&[&state]);
  //           break;
  //         }
  //         _ => continue,
  //       }
  //     }
  //   }
  // }
}
<|endoftext|>


<commit_before>//! Collection Utility

/// Clone a vector consisting of item references to
/// a new vector owning cloned items.
#[inline]
pub fn to_owned_vec<T: Clone>(v: &Vec<&T>) -> Vec<T>
{
  v.iter().map(|e| (*e).clone()).collect::<Vec<T>>()
}

/// Convert Vec<T> into Vec<Box<T>>
///
/// It is usually used for arguments of nested Struct or Enum.
pub fn to_boxed_vec<T>(v: Vec<T>) -> Vec<Box<T>>
{
  v.into_iter().map(|e| Box::new(e)).collect::<Vec<Box<T>>>()
}

/// Convert Vec<Box<T>> to Vec<T>
pub fn strip_box_from_vec<T>(v: Vec<Box<T>>) -> Vec<T>
{
  v.into_iter().map(|e: Box<T>| *e).collect::<Vec<T>>()
}

#[inline]

#[test]
pub fn test() {
  let x = 3; let y = 4;

  let ref_vec : Vec<&usize> = vec![&x, &y];
  let expected: Vec<usize> = vec![x, y];
  assert_eq!(to_owned_vec(&ref_vec), expected);
}<commit_msg>Move some util functions into vec module.<commit_after>//! Collection Utility

pub mod vec {
  /// Clone a vector consisting of item references to
  /// a new vector owning cloned items.
  #[inline]
  pub fn to_owned<T: Clone>(v: &Vec<&T>) -> Vec<T>
  {
    v.iter().map(|e| (*e).clone()).collect::<Vec<T>>()
  }

  /// Convert Vec<T> into Vec<Box<T>>
  ///
  /// It is usually used for arguments of nested Struct or Enum.
  pub fn to_boxed<T>(v: Vec<T>) -> Vec<Box<T>>
  {
    v.into_iter().map(|e| Box::new(e)).collect::<Vec<Box<T>>>()
  }

  /// Convert Vec<Box<T>> to Vec<T>
  pub fn strip_box<T>(v: Vec<Box<T>>) -> Vec<T>
  {
    v.into_iter().map(|e: Box<T>| *e).collect::<Vec<T>>()
  }
}

#[cfg(test)]
pub mod tests {
  use super::*;

  #[test]
  pub fn test() {
    let x = 3; let y = 4;

    let ref_vec : Vec<&usize> = vec![&x, &y];
    let expected: Vec<usize> = vec![x, y];
    assert_eq!(vec::to_owned(&ref_vec), expected);
  }
}<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use libc::{c_int, c_char};

pub fn chown(r_path: *const c_char, uid: u32, gid: u32) -> c_int {
    unimplemented!();
}

pub fn chmod(r_path: *const c_char, mode: u32) -> c_int {
    unimplemented!();
}
<commit_msg>Just enough code to make the core crate tests pass<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use libc::{c_int, c_char};
use std::ffi::CStr;
use std::path::Path;

pub fn chown(r_path: *const c_char, uid: u32, gid: u32) -> c_int {
    unimplemented!();
}

pub fn chmod(r_path: *const c_char, mode: u32) -> c_int {
    unsafe {
        let path = CStr::from_ptr(r_path).to_str().unwrap();
        match Path::new(path).exists() {
            false => 1,
            true => 0
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![feature(custom_attribute, rustc_attrs)]

macro_rules! mac {
    {} => {
        #[cfg(attr)]
        mod m {
            #[lang_item]
            fn f() {}

            #[cfg_attr(target_thread_local, custom)]
            fn g() {}
        }
    }
}

mac! {}

#[rustc_error]
fn main() {} //~ ERROR compilation successful
<commit_msg>Test that unconfigured macro-expanded macro invocations are not expanded.<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

#![feature(custom_attribute, rustc_attrs)]

macro_rules! mac {
    {} => {
        #[cfg(attr)]
        mod m {
            #[lang_item]
            fn f() {}

            #[cfg_attr(target_thread_local, custom)]
            fn g() {}
        }

        #[cfg(attr)]
        unconfigured_invocation!();
    }
}

mac! {}

#[rustc_error]
fn main() {} //~ ERROR compilation successful
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use bytes::BytesMut;
use citaprotocol::pubsub_message_to_network_message;
use config;
use config::NetConfig;
use libproto::TryInto;
use libproto::{Message, OperateType};
use native_tls::{self, TlsConnector};
use notify::DebouncedEvent;
use std::collections::HashMap;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
use std::net::{Shutdown, TcpStream};
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use tokio;
use tokio::prelude::*;
use tokio::util::FutureExt;
use tokio_tls;

const TIMEOUT: u64 = 15;
const ROOT_CERT_FILE: &str = "rootCA.crt";

pub enum RealStream {
    CryptStream(tokio_tls::TlsStream<tokio::net::TcpStream>),
    NormalStream(TcpStream),
}

impl RealStream {
    pub fn shutdown(&mut self) -> io::Result<()> {
        match self {
            RealStream::CryptStream(ref mut tls) => tls.shutdown().map(|_| ()),
            RealStream::NormalStream(ref mut tcp) => tcp.shutdown(Shutdown::Both),
        }
    }
}

impl io::Write for RealStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self {
            RealStream::CryptStream(ref mut tls) => tls.write(buf),
            RealStream::NormalStream(ref mut tcp) => tcp.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self {
            RealStream::CryptStream(ref mut tls) => tls.flush(),
            RealStream::NormalStream(ref mut tcp) => tcp.flush(),
        }
    }
}

pub enum Task {
    Broadcast((String, Message)),
    Update(NetConfig),
    NewTCP((u32, SocketAddr, RealStream, String)),
}

/// Manager unconnected address
struct Manager {
    need_connect: Vec<(u32, SocketAddr, String)>,
    connect_receiver: Receiver<(u32, SocketAddr, String)>,
    task_sender: Sender<Task>,
    enable_tls: bool,
}

fn generate_tls_connector(path: &str) -> Option<TlsConnector> {
    let mut file = File::open(path).expect("Not has cert file");
    let mut pem = vec![];
    file.read_to_end(&mut pem).expect("Cert File read error");
    let root_ca =
        native_tls::Certificate::from_pem(&pem).expect("Cert file content not right, pem ?");

    native_tls::TlsConnector::builder()
        .min_protocol_version(Some(native_tls::Protocol::Tlsv11))
        .max_protocol_version(Some(native_tls::Protocol::Tlsv12))
        .add_root_certificate(root_ca)
        .build()
        .ok()
}

impl Manager {
    fn new(
        task_sender: Sender<Task>,
        connect_receiver: Receiver<(u32, SocketAddr, String)>,
        enable_tls: bool,
    ) -> Self {
        Manager {
            need_connect: Vec::new(),
            connect_receiver,
            task_sender,
            enable_tls,
        }
    }

    fn run(&mut self) {
        let (tls_connector, mut rt) = if self.enable_tls {
            let tls_connector = generate_tls_connector(ROOT_CERT_FILE);
            let rt = tokio::runtime::current_thread::Runtime::new().ok();
            if tls_connector.is_none() || rt.is_none() {
                panic!("TLS connector not generated");
            }
            (tls_connector, rt)
        } else {
            (None, None)
        };

        loop {
            while let Ok(message) = self.connect_receiver.try_recv() {
                self.need_connect.push(message);
            }
            let mut new_need_connect = Vec::new();
            while let Some((id, addr, common_name)) = self.need_connect.pop() {
                match tls_connector.clone() {
                    Some(tls_connect) => {
                        let common_name_clone = common_name.clone();
                        let task = tokio::net::TcpStream::connect(&addr)
                            .and_then(move |socket| {
                                tokio_tls::TlsConnector::from(tls_connect)
                                    .connect(&common_name_clone, socket)
                                    .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
                            })
                            .timeout(Duration::from_secs(TIMEOUT));
                        match rt.as_mut().unwrap().block_on(task) {
                            Ok(tls) => {
                                self.task_sender
                                    .send(Task::NewTCP((
                                        id,
                                        addr,
                                        RealStream::CryptStream(tls),
                                        common_name.clone(),
                                    )))
                                    .unwrap();
                            }
                            Err(e) => {
                                warn!("TLS connect {} failed, error: {}", addr, e);
                                new_need_connect.push((id, addr, common_name));
                            }
                        };
                    }
                    None => match TcpStream::connect_timeout(&addr, Duration::from_secs(TIMEOUT)) {
                        Ok(tcp) => {
                            self.task_sender
                                .send(Task::NewTCP((
                                    id,
                                    addr,
                                    RealStream::NormalStream(tcp),
                                    common_name.clone(),
                                )))
                                .unwrap();
                        }
                        Err(e) => {
                            warn!(
                                "Node{}, {} unable to establish connection, error: {}",
                                id, addr, e
                            );
                            new_need_connect.push((id, addr, common_name));
                        }
                    },
                }
            }
            self.need_connect = new_need_connect;

            if !self.need_connect.is_empty() {
                debug!(
                    "Complete a round of attempts to connect, \
                     left {} address for the next round of processing",
                    self.need_connect.len()
                );
            }

            thread::sleep(Duration::from_secs(TIMEOUT));
        }
    }
}

/// Manage p2p networks
pub struct Connections {
    id_card: u32,
    /// list of peer: id, addr, tcp_connect
    peers: HashMap<(u32, SocketAddr, String), RealStream>,
    pub is_pause: Arc<AtomicBool>,
    pub connect_number: Arc<AtomicUsize>,
    task_receiver: Receiver<Task>,
    connect_sender: Sender<(u32, SocketAddr, String)>,
}

impl Connections {
    pub fn create(config: &config::NetConfig) -> (Self, Sender<Task>) {
        let id_card = config.id_card.unwrap();
        let (task_sender, task_receiver) = channel();
        let (connect_sender, connect_receiver) = channel();

        let connect_task_sender = task_sender.clone();
        let enable_tls = config.enable_tls.unwrap_or(false);
        thread::spawn(move || {
            Manager::new(connect_task_sender, connect_receiver, enable_tls).run()
        });

        if let Some(peers) = config.peers.as_ref() {
            for peer in peers.iter() {
                let id_card: u32 = peer.id_card.unwrap();
                let addr = format!("{}:{}", peer.ip.clone().unwrap(), peer.port.unwrap())
                    .to_socket_addrs()
                    .unwrap()
                    .next()
                    .unwrap();
                connect_sender
                    .send((id_card, addr, peer.common_name.clone().unwrap_or_default()))
                    .unwrap();
            }
        }

        (
            Connections {
                id_card,
                peers: HashMap::new(),
                is_pause: Arc::new(AtomicBool::new(false)),
                connect_number: Arc::new(AtomicUsize::new(0)),
                task_receiver,
                connect_sender,
            },
            task_sender,
        )
    }

    fn is_send(id_card: u32, origin: u32, operate: OperateType) -> bool {
        match operate {
            OperateType::Broadcast => true,
            OperateType::Single => id_card == origin,
            OperateType::Subtract => id_card != origin,
        }
    }

    pub fn run(&mut self) {
        loop {
            match self
                .task_receiver
                .recv_timeout(Duration::from_secs(TIMEOUT))
            {
                Ok(task) => match task {
                    Task::Broadcast((key, message)) => {
                        if !self.is_pause.load(Ordering::SeqCst) {
                            self.broadcast(key, message)
                        }
                    }
                    Task::NewTCP(tcp) => {
                        self.peers.insert((tcp.0, tcp.1, tcp.3), tcp.2);
                        self.connect_number.fetch_add(1, Ordering::Relaxed);
                    }
                    Task::Update(config) => self.update(config),
                },
                Err(_) => {
                    self.heart_beat();
                }
            }
        }
    }

    fn update(&mut self, config: config::NetConfig) {
        // Update configuration
        match config.peers {
            Some(peers) => {
                let config_peers = peers
                    .into_iter()
                    .map(|peer| {
                        let id_card: u32 = peer.id_card.unwrap();
                        let addr = format!("{}:{}", peer.ip.unwrap(), peer.port.unwrap())
                            .to_socket_addrs()
                            .unwrap()
                            .next()
                            .unwrap();
                        (id_card, addr, peer.common_name.unwrap_or_default())
                    })
                    .collect::<Vec<(u32, SocketAddr, String)>>();

                let remove_peers = self
                    .peers
                    .keys()
                    .filter(|peer| !config_peers.contains(&peer))
                    .map(|ref peer| {
                        info!("Remove peer {}, {},{}", peer.0, peer.1, peer.2);
                        (peer.0, peer.1, peer.2.clone())
                    })
                    .collect::<Vec<(u32, SocketAddr, String)>>();

                config_peers
                    .into_iter()
                    .filter(|peer| {
                        self.peers
                            .keys()
                            .find(|&current_peer| current_peer == peer)
                            .is_none()
                    })
                    .for_each(|peer| {
                        info!("Add peer {}, {}", peer.0, peer.1);
                        let _ = self.connect_sender.send(peer);
                    });

                self.close(Some(remove_peers), false);
            }
            None => {
                info!("clear all peers after update!");
                self.close::<Vec<(u32, SocketAddr, String)>>(None, false);
            }
        }
    }

    fn broadcast(&mut self, key: String, mut msg: Message) {
        let origin = msg.get_origin();
        let operate = msg.get_operate();
        msg.set_origin(self.id_card);

        trace!("Broadcast msg {:?} from key {}", msg, key);
        let msg_bytes: Vec<u8> = msg.try_into().unwrap();

        let mut buf = BytesMut::with_capacity(4 + 4 + 1 + key.len() + msg_bytes.len());
        pubsub_message_to_network_message(&mut buf, Some((key, msg_bytes)));

        let mut peers = Vec::new();
        let mut remove_peers = Vec::new();
        for (peer, stream) in self.peers.iter_mut() {
            if Connections::is_send(peer.0, origin, operate) {
                match stream.write_all(&buf) {
                    Ok(_) => {
                        peers.push(peer.0);
                    }
                    Err(e) => {
                        warn!("Node{} {} is shutdown, err: {}", peer.0, peer.1, e);
                        remove_peers.push(peer.clone());
                    }
                }
            }
        }
        self.close(Some(remove_peers), true);
        trace!(
            "{:?} broadcast msg to nodes {:?} {:?}",
            self.id_card,
            operate,
            peers
        );
    }

    fn close<T: ::std::iter::IntoIterator<Item = (u32, SocketAddr, String)>>(
        &mut self,
        peers: Option<T>,
        need_reconnect: bool,
    ) {
        match peers {
            Some(peers) => peers.into_iter().for_each(|peer| {
                if let Some(mut stream) = self.peers.remove(&peer) {
                    let _ = stream.shutdown().map_err(|err| {
                        warn!("Shutdown {} - {} failed: {}", peer.0, peer.1, err);
                    });
                    if need_reconnect {
                        self.connect_sender.send(peer).unwrap();
                    }
                    self.connect_number.fetch_sub(1, Ordering::Relaxed);
                }
            }),
            None => {
                self.peers.iter_mut().for_each(|(peer, stream)| {
                    let _ = stream.shutdown().map_err(|err| {
                        warn!("Shutdown {} - {} failed: {}", peer.0, peer.1, err);
                    });
                });
                if need_reconnect {
                    self.peers.iter().for_each(|(ref peer, _)| {
                        self.connect_sender
                            .send((peer.0, peer.1, peer.2.clone()))
                            .unwrap();
                    })
                }
                self.peers.clear();
                self.connect_number.store(0, Ordering::Relaxed);
            }
        }
    }

    fn heart_beat(&mut self) {
        let mut buf = BytesMut::with_capacity(4 + 4);
        pubsub_message_to_network_message(&mut buf, None);
        let mut remove_peers = Vec::new();
        for (peer, stream) in self.peers.iter_mut() {
            match stream.write(&buf) {
                Ok(_) => {
                    let _ = stream.flush();
                }
                Err(e) => {
                    warn!(
                        "Node{} {} {} is shutdown, err: {}",
                        peer.0, peer.1, peer.2, e
                    );
                    remove_peers.push((peer.0, peer.1, peer.2.clone()));
                }
            };
        }
        self.close(Some(remove_peers), true);
    }
}

pub fn manage_connect(config_path: &str, rx: Receiver<DebouncedEvent>, task_send: Sender<Task>) {
    let config = String::from(config_path);

    thread::spawn(move || loop {
        match rx.recv() {
            Ok(event) => match event {
                DebouncedEvent::Create(path_buf) | DebouncedEvent::Write(path_buf) => {
                    if path_buf.is_file() {
                        let file_name = path_buf.file_name().unwrap().to_str().unwrap();
                        if file_name == config.as_str() {
                            info!("file {} changed, will auto reload!", file_name);
                            let config = NetConfig::new(config.as_str());
                            let _ = task_send.send(Task::Update(config));
                        }
                    }
                }
                _ => trace!("file notify event: {:?}", event),
            },
            Err(e) => warn!("watch error: {:?}", e),
        }
    });
}

#[cfg(test)]
mod test {
    use super::Connections;
    use libproto::OperateType;
    #[test]
    fn is_send_msg() {
        assert!(Connections::is_send(0, 0, OperateType::Broadcast));
        assert!(Connections::is_send(0, 1, OperateType::Broadcast));

        assert!(Connections::is_send(0, 0, OperateType::Single));
        assert!(!Connections::is_send(0, 1, OperateType::Single));

        assert!(!Connections::is_send(0, 0, OperateType::Subtract));
        assert!(Connections::is_send(0, 1, OperateType::Subtract));
    }
}
<commit_msg>fix network parse config<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use bytes::BytesMut;
use citaprotocol::pubsub_message_to_network_message;
use config;
use config::{NetConfig, PeerConfig};
use libproto::TryInto;
use libproto::{Message, OperateType};
use native_tls::{self, TlsConnector};
use notify::DebouncedEvent;
use std::collections::HashMap;
use std::fs::File;
use std::io;
use std::io::{Read, Write};
use std::net::{Shutdown, TcpStream};
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use tokio;
use tokio::prelude::*;
use tokio::util::FutureExt;
use tokio_tls;

const TIMEOUT: u64 = 15;
const ROOT_CERT_FILE: &str = "rootCA.crt";

pub enum RealStream {
    CryptStream(tokio_tls::TlsStream<tokio::net::TcpStream>),
    NormalStream(TcpStream),
}

impl RealStream {
    pub fn shutdown(&mut self) -> io::Result<()> {
        match self {
            RealStream::CryptStream(ref mut tls) => tls.shutdown().map(|_| ()),
            RealStream::NormalStream(ref mut tcp) => tcp.shutdown(Shutdown::Both),
        }
    }
}

impl io::Write for RealStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match self {
            RealStream::CryptStream(ref mut tls) => tls.write(buf),
            RealStream::NormalStream(ref mut tcp) => tcp.write(buf),
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match self {
            RealStream::CryptStream(ref mut tls) => tls.flush(),
            RealStream::NormalStream(ref mut tcp) => tcp.flush(),
        }
    }
}

pub enum Task {
    Broadcast((String, Message)),
    Update(NetConfig),
    NewTCP((u32, SocketAddr, RealStream, String)),
}

/// Manager unconnected address
struct Manager {
    need_connect: Vec<(u32, SocketAddr, String)>,
    connect_receiver: Receiver<(u32, SocketAddr, String)>,
    task_sender: Sender<Task>,
    enable_tls: bool,
}

fn generate_tls_connector(path: &str) -> Option<TlsConnector> {
    let mut file = File::open(path).expect("Not has cert file");
    let mut pem = vec![];
    file.read_to_end(&mut pem).expect("Cert File read error");
    let root_ca =
        native_tls::Certificate::from_pem(&pem).expect("Cert file content not right, pem ?");

    native_tls::TlsConnector::builder()
        .min_protocol_version(Some(native_tls::Protocol::Tlsv11))
        .max_protocol_version(Some(native_tls::Protocol::Tlsv12))
        .add_root_certificate(root_ca)
        .build()
        .ok()
}

impl Manager {
    fn new(
        task_sender: Sender<Task>,
        connect_receiver: Receiver<(u32, SocketAddr, String)>,
        enable_tls: bool,
    ) -> Self {
        Manager {
            need_connect: Vec::new(),
            connect_receiver,
            task_sender,
            enable_tls,
        }
    }

    fn run(&mut self) {
        let (tls_connector, mut rt) = if self.enable_tls {
            let tls_connector = generate_tls_connector(ROOT_CERT_FILE);
            let rt = tokio::runtime::current_thread::Runtime::new().ok();
            if tls_connector.is_none() || rt.is_none() {
                panic!("TLS connector not generated");
            }
            (tls_connector, rt)
        } else {
            (None, None)
        };

        loop {
            while let Ok(message) = self.connect_receiver.try_recv() {
                self.need_connect.push(message);
            }
            let mut new_need_connect = Vec::new();
            while let Some((id, addr, common_name)) = self.need_connect.pop() {
                match tls_connector.clone() {
                    Some(tls_connect) => {
                        let common_name_clone = common_name.clone();
                        let task = tokio::net::TcpStream::connect(&addr)
                            .and_then(move |socket| {
                                tokio_tls::TlsConnector::from(tls_connect)
                                    .connect(&common_name_clone, socket)
                                    .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
                            })
                            .timeout(Duration::from_secs(TIMEOUT));
                        match rt.as_mut().unwrap().block_on(task) {
                            Ok(tls) => {
                                self.task_sender
                                    .send(Task::NewTCP((
                                        id,
                                        addr,
                                        RealStream::CryptStream(tls),
                                        common_name.clone(),
                                    )))
                                    .unwrap();
                            }
                            Err(e) => {
                                warn!("TLS connect {} failed, error: {}", addr, e);
                                new_need_connect.push((id, addr, common_name));
                            }
                        };
                    }
                    None => match TcpStream::connect_timeout(&addr, Duration::from_secs(TIMEOUT)) {
                        Ok(tcp) => {
                            self.task_sender
                                .send(Task::NewTCP((
                                    id,
                                    addr,
                                    RealStream::NormalStream(tcp),
                                    common_name.clone(),
                                )))
                                .unwrap();
                        }
                        Err(e) => {
                            warn!(
                                "Node{}, {} unable to establish connection, error: {}",
                                id, addr, e
                            );
                            new_need_connect.push((id, addr, common_name));
                        }
                    },
                }
            }
            self.need_connect = new_need_connect;

            if !self.need_connect.is_empty() {
                debug!(
                    "Complete a round of attempts to connect, \
                     left {} address for the next round of processing",
                    self.need_connect.len()
                );
            }

            thread::sleep(Duration::from_secs(TIMEOUT));
        }
    }
}

/// Manage p2p networks
pub struct Connections {
    id_card: u32,
    /// list of peer: id, addr, tcp_connect
    peers: HashMap<(u32, SocketAddr, String), RealStream>,
    pub is_pause: Arc<AtomicBool>,
    pub connect_number: Arc<AtomicUsize>,
    task_receiver: Receiver<Task>,
    connect_sender: Sender<(u32, SocketAddr, String)>,
}

impl Connections {
    pub fn create(config: &config::NetConfig) -> (Self, Sender<Task>) {
        let id_card = config.id_card.unwrap();
        let (task_sender, task_receiver) = channel();
        let (connect_sender, connect_receiver) = channel();

        let connect_task_sender = task_sender.clone();
        let enable_tls = config.enable_tls.unwrap_or(false);
        thread::spawn(move || {
            Manager::new(connect_task_sender, connect_receiver, enable_tls).run()
        });

        if let Some(peers) = config.peers.as_ref() {
            config_peer(&peers).into_iter().for_each(|config| {
                connect_sender.send(config).unwrap();
            });
        }

        (
            Connections {
                id_card,
                peers: HashMap::new(),
                is_pause: Arc::new(AtomicBool::new(false)),
                connect_number: Arc::new(AtomicUsize::new(0)),
                task_receiver,
                connect_sender,
            },
            task_sender,
        )
    }

    fn is_send(id_card: u32, origin: u32, operate: OperateType) -> bool {
        match operate {
            OperateType::Broadcast => true,
            OperateType::Single => id_card == origin,
            OperateType::Subtract => id_card != origin,
        }
    }

    pub fn run(&mut self) {
        loop {
            match self
                .task_receiver
                .recv_timeout(Duration::from_secs(TIMEOUT))
            {
                Ok(task) => match task {
                    Task::Broadcast((key, message)) => {
                        if !self.is_pause.load(Ordering::SeqCst) {
                            self.broadcast(key, message)
                        }
                    }
                    Task::NewTCP(tcp) => {
                        self.peers.insert((tcp.0, tcp.1, tcp.3), tcp.2);
                        self.connect_number.fetch_add(1, Ordering::Relaxed);
                    }
                    Task::Update(config) => self.update(config),
                },
                Err(_) => {
                    self.heart_beat();
                }
            }
        }
    }

    fn update(&mut self, config: config::NetConfig) {
        // Update configuration
        match config.peers {
            Some(peers) => {
                let config_peers = config_peer(&peers);

                let remove_peers = self
                    .peers
                    .keys()
                    .filter(|peer| !config_peers.contains(&peer))
                    .map(|ref peer| {
                        info!("Remove peer {}, {},{}", peer.0, peer.1, peer.2);
                        (peer.0, peer.1, peer.2.clone())
                    })
                    .collect::<Vec<(u32, SocketAddr, String)>>();

                config_peers
                    .into_iter()
                    .filter(|peer| {
                        self.peers
                            .keys()
                            .find(|&current_peer| current_peer == peer)
                            .is_none()
                    })
                    .for_each(|peer| {
                        info!("Add peer {}, {}", peer.0, peer.1);
                        let _ = self.connect_sender.send(peer);
                    });

                self.close(Some(remove_peers), false);
            }
            None => {
                info!("clear all peers after update!");
                self.close::<Vec<(u32, SocketAddr, String)>>(None, false);
            }
        }
    }

    fn broadcast(&mut self, key: String, mut msg: Message) {
        let origin = msg.get_origin();
        let operate = msg.get_operate();
        msg.set_origin(self.id_card);

        trace!("Broadcast msg {:?} from key {}", msg, key);
        let msg_bytes: Vec<u8> = msg.try_into().unwrap();

        let mut buf = BytesMut::with_capacity(4 + 4 + 1 + key.len() + msg_bytes.len());
        pubsub_message_to_network_message(&mut buf, Some((key, msg_bytes)));

        let mut peers = Vec::new();
        let mut remove_peers = Vec::new();
        for (peer, stream) in self.peers.iter_mut() {
            if Connections::is_send(peer.0, origin, operate) {
                match stream.write_all(&buf) {
                    Ok(_) => {
                        peers.push(peer.0);
                    }
                    Err(e) => {
                        warn!("Node{} {} is shutdown, err: {}", peer.0, peer.1, e);
                        remove_peers.push(peer.clone());
                    }
                }
            }
        }
        self.close(Some(remove_peers), true);
        trace!(
            "{:?} broadcast msg to nodes {:?} {:?}",
            self.id_card,
            operate,
            peers
        );
    }

    fn close<T: ::std::iter::IntoIterator<Item = (u32, SocketAddr, String)>>(
        &mut self,
        peers: Option<T>,
        need_reconnect: bool,
    ) {
        match peers {
            Some(peers) => peers.into_iter().for_each(|peer| {
                if let Some(mut stream) = self.peers.remove(&peer) {
                    let _ = stream.shutdown().map_err(|err| {
                        warn!("Shutdown {} - {} failed: {}", peer.0, peer.1, err);
                    });
                    if need_reconnect {
                        self.connect_sender.send(peer).unwrap();
                    }
                    self.connect_number.fetch_sub(1, Ordering::Relaxed);
                }
            }),
            None => {
                self.peers.iter_mut().for_each(|(peer, stream)| {
                    let _ = stream.shutdown().map_err(|err| {
                        warn!("Shutdown {} - {} failed: {}", peer.0, peer.1, err);
                    });
                });
                if need_reconnect {
                    self.peers.iter().for_each(|(ref peer, _)| {
                        self.connect_sender
                            .send((peer.0, peer.1, peer.2.clone()))
                            .unwrap();
                    })
                }
                self.peers.clear();
                self.connect_number.store(0, Ordering::Relaxed);
            }
        }
    }

    fn heart_beat(&mut self) {
        let mut buf = BytesMut::with_capacity(4 + 4);
        pubsub_message_to_network_message(&mut buf, None);
        let mut remove_peers = Vec::new();
        for (peer, stream) in self.peers.iter_mut() {
            match stream.write(&buf) {
                Ok(_) => {
                    let _ = stream.flush();
                }
                Err(e) => {
                    warn!(
                        "Node{} {} {} is shutdown, err: {}",
                        peer.0, peer.1, peer.2, e
                    );
                    remove_peers.push((peer.0, peer.1, peer.2.clone()));
                }
            };
        }
        self.close(Some(remove_peers), true);
    }
}

pub fn manage_connect(config_path: &str, rx: Receiver<DebouncedEvent>, task_send: Sender<Task>) {
    let config = String::from(config_path);

    thread::spawn(move || loop {
        match rx.recv() {
            Ok(event) => match event {
                DebouncedEvent::Create(path_buf) | DebouncedEvent::Write(path_buf) => {
                    if path_buf.is_file() {
                        let file_name = path_buf.file_name().unwrap().to_str().unwrap();
                        if file_name == config.as_str() {
                            info!("file {} changed, will auto reload!", file_name);
                            let config = NetConfig::new(config.as_str());
                            let _ = task_send.send(Task::Update(config));
                        }
                    }
                }
                _ => trace!("file notify event: {:?}", event),
            },
            Err(e) => warn!("watch error: {:?}", e),
        }
    });
}

fn config_peer(config: &[PeerConfig]) -> Vec<(u32, SocketAddr, String)> {
    config
        .into_iter()
        .filter_map(|peer| {
            if let (Some(id_card), Some(ip), Some(port)) =
                (peer.id_card, peer.ip.clone(), peer.port)
            {
                match format!("{}:{}", ip, port).to_socket_addrs() {
                    Ok(mut result) => {
                        if let Some(addr) = result.next() {
                            Some((id_card, addr, peer.common_name.clone().unwrap_or_default()))
                        } else {
                            error!("Can't convert to socket address, error");
                            None
                        }
                    }
                    Err(e) => {
                        error!("Can't convert to socket address, error: {}", e);
                        None
                    }
                }
            } else {
                error!("Invalid peer config: {:?}", peer);
                None
            }
        })
        .collect()
}

#[cfg(test)]
mod test {
    use super::Connections;
    use libproto::OperateType;
    #[test]
    fn is_send_msg() {
        assert!(Connections::is_send(0, 0, OperateType::Broadcast));
        assert!(Connections::is_send(0, 1, OperateType::Broadcast));

        assert!(Connections::is_send(0, 0, OperateType::Single));
        assert!(!Connections::is_send(0, 1, OperateType::Single));

        assert!(!Connections::is_send(0, 0, OperateType::Subtract));
        assert!(Connections::is_send(0, 1, OperateType::Subtract));
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "no_std")]
#![allow(dead_code)]
#![no_std]

#[macro_use]
extern crate bitflags;

bitflags! {
    /// baz
    flags Flags: u32 {
        const A       = 0b00000001,
        #[doc = "bar"]
        const B       = 0b00000010,
        const C       = 0b00000100,
        #[doc = "foo"]
        const ABC     = A.bits | B.bits | C.bits,
    }
}

#[test]
fn smoke() {
    assert_eq!(ABC, A | B | C);
}
<commit_msg>Oops, forgot to remove cfg from test<commit_after>#![allow(dead_code)]
#![no_std]

#[macro_use]
extern crate bitflags;

bitflags! {
    /// baz
    flags Flags: u32 {
        const A       = 0b00000001,
        #[doc = "bar"]
        const B       = 0b00000010,
        const C       = 0b00000100,
        #[doc = "foo"]
        const ABC     = A.bits | B.bits | C.bits,
    }
}

#[test]
fn smoke() {
    assert_eq!(ABC, A | B | C);
}
<|endoftext|>


<commit_before>use std::cmp::FuzzyEq;
use num::Num;

pub pure fn Matrix4<T:Copy FuzzyEq Num>(m11: T, m12: T, m13: T, m14: T,
                                        m21: T, m22: T, m23: T, m24: T,
                                        m31: T, m32: T, m33: T, m34: T,
                                        m41: T, m42: T, m43: T, m44: T)
                                     -> Matrix4<T> {

    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

pub struct Matrix4<T:Copy FuzzyEq Num> {
    m11: T, m12: T, m13: T, m14: T,
    m21: T, m22: T, m23: T, m24: T,
    m31: T, m32: T, m33: T, m34: T,
    m41: T, m42: T, m43: T, m44: T,
}

impl<T:Copy FuzzyEq Num> Matrix4<T> {
    pure fn fuzzy_eq(other: &Matrix4<T>) -> bool {
        self.m11.fuzzy_eq(&other.m11) && self.m12.fuzzy_eq(&other.m12) &&
        self.m13.fuzzy_eq(&other.m13) && self.m14.fuzzy_eq(&other.m14) &&
        self.m21.fuzzy_eq(&other.m21) && self.m22.fuzzy_eq(&other.m22) &&
        self.m23.fuzzy_eq(&other.m23) && self.m24.fuzzy_eq(&other.m24) &&
        self.m31.fuzzy_eq(&other.m31) && self.m32.fuzzy_eq(&other.m32) &&
        self.m33.fuzzy_eq(&other.m33) && self.m34.fuzzy_eq(&other.m34) &&
        self.m41.fuzzy_eq(&other.m41) && self.m42.fuzzy_eq(&other.m42) &&
        self.m43.fuzzy_eq(&other.m43) && self.m44.fuzzy_eq(&other.m44)
    }

    pure fn mul(m: &Matrix4<T>) -> Matrix4<T> {
        return Matrix4(m.m11.mul(&self.m11).add(&m.m12.mul(&self.m21))
                                           .add(&m.m13.mul(&self.m31))
                                           .add(&m.m14.mul(&self.m41)),
                       m.m11.mul(&self.m12).add(&m.m12.mul(&self.m22))
                                           .add(&m.m13.mul(&self.m32))
                                           .add(&m.m14.mul(&self.m42)),
                       m.m11.mul(&self.m13).add(&m.m12.mul(&self.m23))
                                           .add(&m.m13.mul(&self.m33))
                                           .add(&m.m14.mul(&self.m43)),
                       m.m11.mul(&self.m14).add(&m.m12.mul(&self.m24))
                                           .add(&m.m13.mul(&self.m34))
                                           .add(&m.m14.mul(&self.m44)),
                       m.m21.mul(&self.m11).add(&m.m22.mul(&self.m21))
                                           .add(&m.m23.mul(&self.m31))
                                           .add(&m.m24.mul(&self.m41)),
                       m.m21.mul(&self.m12).add(&m.m22.mul(&self.m22))
                                           .add(&m.m23.mul(&self.m32))
                                           .add(&m.m24.mul(&self.m42)),
                       m.m21.mul(&self.m13).add(&m.m22.mul(&self.m23))
                                           .add(&m.m23.mul(&self.m33))
                                           .add(&m.m24.mul(&self.m43)),
                       m.m21.mul(&self.m14).add(&m.m22.mul(&self.m24))
                                           .add(&m.m23.mul(&self.m34))
                                           .add(&m.m24.mul(&self.m44)),
                       m.m31.mul(&self.m11).add(&m.m32.mul(&self.m21))
                                           .add(&m.m33.mul(&self.m31))
                                           .add(&m.m34.mul(&self.m41)),
                       m.m31.mul(&self.m12).add(&m.m32.mul(&self.m22))
                                           .add(&m.m33.mul(&self.m32))
                                           .add(&m.m34.mul(&self.m42)),
                       m.m31.mul(&self.m13).add(&m.m32.mul(&self.m23))
                                           .add(&m.m33.mul(&self.m33))
                                           .add(&m.m34.mul(&self.m43)),
                       m.m31.mul(&self.m14).add(&m.m32.mul(&self.m24))
                                           .add(&m.m33.mul(&self.m34))
                                           .add(&m.m34.mul(&self.m44)),
                       m.m41.mul(&self.m11).add(&m.m42.mul(&self.m21))
                                           .add(&m.m43.mul(&self.m31))
                                           .add(&m.m44.mul(&self.m41)),
                       m.m41.mul(&self.m12).add(&m.m42.mul(&self.m22))
                                           .add(&m.m43.mul(&self.m32))
                                           .add(&m.m44.mul(&self.m42)),
                       m.m41.mul(&self.m13).add(&m.m42.mul(&self.m23))
                                           .add(&m.m43.mul(&self.m33))
                                           .add(&m.m44.mul(&self.m43)),
                       m.m41.mul(&self.m14).add(&m.m42.mul(&self.m24))
                                           .add(&m.m43.mul(&self.m34))
                                           .add(&m.m44.mul(&self.m44)));
    }

    pure fn mul_s(x: &T) -> Matrix4<T> {
        return Matrix4(self.m11.mul(x), self.m12.mul(x), self.m13.mul(x), self.m14.mul(x),
                       self.m21.mul(x), self.m22.mul(x), self.m23.mul(x), self.m24.mul(x),
                       self.m31.mul(x), self.m32.mul(x), self.m33.mul(x), self.m34.mul(x),
                       self.m41.mul(x), self.m42.mul(x), self.m43.mul(x), self.m44.mul(x));
    }

    pure fn scale(x: &T, y: &T, z: &T) -> Matrix4<T> {
        return Matrix4(self.m11.mul(x), self.m12,        self.m13,        self.m14,
                       self.m21,        self.m22.mul(y), self.m23,        self.m24,
                       self.m31,        self.m32,        self.m33.mul(z), self.m34,
                       self.m41,        self.m42,        self.m43,        self.m44);
    }

    pure fn to_array() -> ~[T] {
        return ~[
            self.m11, self.m12, self.m13, self.m14,
            self.m21, self.m22, self.m23, self.m24,
            self.m31, self.m32, self.m33, self.m34,
            self.m41, self.m42, self.m43, self.m44
        ];
    }

    pure fn translate(x: &T, y: &T, z: &T) -> Matrix4<T> {
        let _0 = num::from_int(0);
        let _1 = num::from_int(1);
        let matrix = Matrix4(_1, _0, _0, _0,
                             _0, _1, _0, _0,
                             _0, _0, _1, _0,
                             *x, *y, *z, _1);

        return self.mul(&matrix);
    }
}

pub fn ortho<T:Copy FuzzyEq Num>(left: T, right: T, bottom: T, top: T, near: T, far: T)
                              -> Matrix4<T> {

    let two: T = num::from_int(2);
    let one: T = num::from_int(1);
    let zero: T = num::from_int(0);
    let minus_two: T = num::from_int(-2);

    let tx = right.add(&left).div(&right.sub(&left)).neg();
    let ty = top.add(&bottom).div(&top.sub(&bottom)).neg();
    let tz = far.add(&near).div(&far.sub(&near)).neg();

    return Matrix4(two.div(&right.sub(&left)), zero, zero, zero,
                   zero, two.div(&top.sub(&bottom)), zero, zero,
                   zero, zero, minus_two.div(&far.sub(&near)), zero,
                   tx, ty, tz, one);
}

pub fn identity<T:Copy FuzzyEq Num>(_0: T) -> Matrix4<T> {
    let _1 = num::from_int(1);
    return Matrix4(_1, _0, _0, _0,
                   _0, _1, _0, _0,
                   _0, _0, _1, _0,
                   _0, _0, _0, _1);
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0, 1.0, 0.1, 1.0);
    let (near, far) = (-1.0, 1.0);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    #debug("result=%? expected=%?", result, expected);
    assert result.fuzzy_eq(&expected);
}

<commit_msg>Update for language changes<commit_after>use std::cmp::FuzzyEq;
use num::Num;

pub pure fn Matrix4<T:Copy FuzzyEq Num>(m11: T, m12: T, m13: T, m14: T,
                                        m21: T, m22: T, m23: T, m24: T,
                                        m31: T, m32: T, m33: T, m34: T,
                                        m41: T, m42: T, m43: T, m44: T)
                                     -> Matrix4<T> {

    Matrix4 {
        m11: m11, m12: m12, m13: m13, m14: m14,
        m21: m21, m22: m22, m23: m23, m24: m24,
        m31: m31, m32: m32, m33: m33, m34: m34,
        m41: m41, m42: m42, m43: m43, m44: m44
    }
}

pub struct Matrix4<T:Copy FuzzyEq Num> {
    m11: T, m12: T, m13: T, m14: T,
    m21: T, m22: T, m23: T, m24: T,
    m31: T, m32: T, m33: T, m34: T,
    m41: T, m42: T, m43: T, m44: T,
}

impl<T:Copy FuzzyEq Num> Matrix4<T> {
    pure fn fuzzy_eq(other: &Matrix4<T>) -> bool {
        self.m11.fuzzy_eq(&other.m11) && self.m12.fuzzy_eq(&other.m12) &&
        self.m13.fuzzy_eq(&other.m13) && self.m14.fuzzy_eq(&other.m14) &&
        self.m21.fuzzy_eq(&other.m21) && self.m22.fuzzy_eq(&other.m22) &&
        self.m23.fuzzy_eq(&other.m23) && self.m24.fuzzy_eq(&other.m24) &&
        self.m31.fuzzy_eq(&other.m31) && self.m32.fuzzy_eq(&other.m32) &&
        self.m33.fuzzy_eq(&other.m33) && self.m34.fuzzy_eq(&other.m34) &&
        self.m41.fuzzy_eq(&other.m41) && self.m42.fuzzy_eq(&other.m42) &&
        self.m43.fuzzy_eq(&other.m43) && self.m44.fuzzy_eq(&other.m44)
    }

    pure fn mul(m: &Matrix4<T>) -> Matrix4<T> {
        return Matrix4(m.m11.mul(&self.m11).add(&m.m12.mul(&self.m21))
                                           .add(&m.m13.mul(&self.m31))
                                           .add(&m.m14.mul(&self.m41)),
                       m.m11.mul(&self.m12).add(&m.m12.mul(&self.m22))
                                           .add(&m.m13.mul(&self.m32))
                                           .add(&m.m14.mul(&self.m42)),
                       m.m11.mul(&self.m13).add(&m.m12.mul(&self.m23))
                                           .add(&m.m13.mul(&self.m33))
                                           .add(&m.m14.mul(&self.m43)),
                       m.m11.mul(&self.m14).add(&m.m12.mul(&self.m24))
                                           .add(&m.m13.mul(&self.m34))
                                           .add(&m.m14.mul(&self.m44)),
                       m.m21.mul(&self.m11).add(&m.m22.mul(&self.m21))
                                           .add(&m.m23.mul(&self.m31))
                                           .add(&m.m24.mul(&self.m41)),
                       m.m21.mul(&self.m12).add(&m.m22.mul(&self.m22))
                                           .add(&m.m23.mul(&self.m32))
                                           .add(&m.m24.mul(&self.m42)),
                       m.m21.mul(&self.m13).add(&m.m22.mul(&self.m23))
                                           .add(&m.m23.mul(&self.m33))
                                           .add(&m.m24.mul(&self.m43)),
                       m.m21.mul(&self.m14).add(&m.m22.mul(&self.m24))
                                           .add(&m.m23.mul(&self.m34))
                                           .add(&m.m24.mul(&self.m44)),
                       m.m31.mul(&self.m11).add(&m.m32.mul(&self.m21))
                                           .add(&m.m33.mul(&self.m31))
                                           .add(&m.m34.mul(&self.m41)),
                       m.m31.mul(&self.m12).add(&m.m32.mul(&self.m22))
                                           .add(&m.m33.mul(&self.m32))
                                           .add(&m.m34.mul(&self.m42)),
                       m.m31.mul(&self.m13).add(&m.m32.mul(&self.m23))
                                           .add(&m.m33.mul(&self.m33))
                                           .add(&m.m34.mul(&self.m43)),
                       m.m31.mul(&self.m14).add(&m.m32.mul(&self.m24))
                                           .add(&m.m33.mul(&self.m34))
                                           .add(&m.m34.mul(&self.m44)),
                       m.m41.mul(&self.m11).add(&m.m42.mul(&self.m21))
                                           .add(&m.m43.mul(&self.m31))
                                           .add(&m.m44.mul(&self.m41)),
                       m.m41.mul(&self.m12).add(&m.m42.mul(&self.m22))
                                           .add(&m.m43.mul(&self.m32))
                                           .add(&m.m44.mul(&self.m42)),
                       m.m41.mul(&self.m13).add(&m.m42.mul(&self.m23))
                                           .add(&m.m43.mul(&self.m33))
                                           .add(&m.m44.mul(&self.m43)),
                       m.m41.mul(&self.m14).add(&m.m42.mul(&self.m24))
                                           .add(&m.m43.mul(&self.m34))
                                           .add(&m.m44.mul(&self.m44)));
    }

    pure fn mul_s(x: &T) -> Matrix4<T> {
        return Matrix4(self.m11.mul(x), self.m12.mul(x), self.m13.mul(x), self.m14.mul(x),
                       self.m21.mul(x), self.m22.mul(x), self.m23.mul(x), self.m24.mul(x),
                       self.m31.mul(x), self.m32.mul(x), self.m33.mul(x), self.m34.mul(x),
                       self.m41.mul(x), self.m42.mul(x), self.m43.mul(x), self.m44.mul(x));
    }

    pure fn scale(x: &T, y: &T, z: &T) -> Matrix4<T> {
        return Matrix4(self.m11.mul(x), self.m12,        self.m13,        self.m14,
                       self.m21,        self.m22.mul(y), self.m23,        self.m24,
                       self.m31,        self.m32,        self.m33.mul(z), self.m34,
                       self.m41,        self.m42,        self.m43,        self.m44);
    }

    pure fn to_array() -> ~[T] {
        return ~[
            self.m11, self.m12, self.m13, self.m14,
            self.m21, self.m22, self.m23, self.m24,
            self.m31, self.m32, self.m33, self.m34,
            self.m41, self.m42, self.m43, self.m44
        ];
    }

    pure fn translate(x: &T, y: &T, z: &T) -> Matrix4<T> {
        let _0 = num::from_int(0);
        let _1 = num::from_int(1);
        let matrix = Matrix4(_1, _0, _0, _0,
                             _0, _1, _0, _0,
                             _0, _0, _1, _0,
                             *x, *y, *z, _1);

        return self.mul(&matrix);
    }
}

pub fn ortho<T:Copy FuzzyEq Num>(left: T, right: T, bottom: T, top: T, near: T, far: T)
                              -> Matrix4<T> {

    let two: T = num::from_int(2);
    let one: T = num::from_int(1);
    let zero: T = num::from_int(0);
    let minus_two: T = num::from_int(-2);

    let tx = right.add(&left).div(&right.sub(&left)).neg();
    let ty = top.add(&bottom).div(&top.sub(&bottom)).neg();
    let tz = far.add(&near).div(&far.sub(&near)).neg();

    return Matrix4(two.div(&right.sub(&left)), zero, zero, zero,
                   zero, two.div(&top.sub(&bottom)), zero, zero,
                   zero, zero, minus_two.div(&far.sub(&near)), zero,
                   tx, ty, tz, one);
}

pub fn identity<T:Copy FuzzyEq Num>(_0: T) -> Matrix4<T> {
    let _1 = num::from_int(1);
    return Matrix4(_1, _0, _0, _0,
                   _0, _1, _0, _0,
                   _0, _0, _1, _0,
                   _0, _0, _0, _1);
}

#[test]
pub fn test_ortho() {
    let (left, right, bottom, top) = (0.0, 1.0, 0.1, 1.0);
    let (near, far) = (-1.0, 1.0);
    let result = ortho(left, right, bottom, top, near, far);
    let expected = Matrix4(2.0,  0.0,         0.0,  0.0,
                           0.0,  2.22222222,  0.0,  0.0,
                           0.0,  0.0,         -1.0, 0.0,
                           -1.0, -1.22222222, -0.0, 1.0);
    debug!("result=%? expected=%?", result, expected);
    assert result.fuzzy_eq(&expected);
}

<|endoftext|>


<commit_before>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    #[inline(always)]
    pub fn schedule(&mut self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    #[inline(always)]
    pub fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles)
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if event.cycles_remaining > new_event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx + 1;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if self.has_next_event(cycles) {
            let event = self.events.pop_front().unwrap();
            Some((event.callback, cycles - event.cycles_remaining))
        } else {
            None
        }
    }
}
<commit_msg>Remove unnecessary inline hints from scheduler.<commit_after>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&mut self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&mut self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if event.cycles_remaining > new_event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx + 1;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if self.has_next_event(cycles) {
            let event = self.events.pop_front().unwrap();
            Some((event.callback, cycles - event.cycles_remaining))
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Use Log middleware<commit_after><|endoftext|>