<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod convert;

use convert::FromLossy;

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        // TODO: Move this into some utility module.
        // TODO: Add support for other log types.
        macro_rules! ack {
            { $expr:expr, error: $message:literal } => {
                match $expr {
                    Ok(value) => Some(value),
                    Err(err) => {
                        ::log::error!(concat!($message, ": {}"), err);
                        None
                    },
                }
            };
        }

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let btime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|crtime| ack! {
            secs(crtime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = ack! {
            u64::try_from(metadata.ctime()),
            error: "negative inode change time"
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_crtime: btime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

impl From<std::num::TryFromIntError> for MicrosError {

    fn from(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();
    Ok(std::convert::TryInto::try_into(time_micros)?)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<commit_msg>Remove spurious conversion for microsecond errors.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod convert;

use convert::FromLossy;

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        // TODO: Move this into some utility module.
        // TODO: Add support for other log types.
        macro_rules! ack {
            { $expr:expr, error: $message:literal } => {
                match $expr {
                    Ok(value) => Some(value),
                    Err(err) => {
                        ::log::error!(concat!($message, ": {}"), err);
                        None
                    },
                }
            };
        }

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let btime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|crtime| ack! {
            secs(crtime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = ack! {
            u64::try_from(metadata.ctime()),
            error: "negative inode change time"
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_crtime: btime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl MicrosError {

    /// Creates a microsecond conversion error from an integer overflow error.
    pub fn overflow(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();

    use std::convert::TryInto as _;
    time_micros.try_into().map_err(MicrosError::overflow)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<|endoftext|>


<commit_before>use nix::fcntl::FcntlArg::F_SETFL;
use nix::fcntl::{fcntl, O_NONBLOCK};
use nix::sys::socket::{bind, listen, setsockopt, sockopt, AddressFamily, SockFlag, SockType,
                       SockLevel, SockAddr, socket, InetAddr};
use std::net::{self, SocketAddr, UdpSocket};
use std::io;
use std::os::unix::io::{RawFd, FromRawFd};
use std::str::FromStr;
use super::{TCP_BACKLOG, UDP_BUFFER_SIZE};

pub fn socket_tcp_v4() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet,
                                SockType::Stream,
                                SockFlag::empty(),
                                SockLevel::Tcp as i32));
    Ok(socket_fd)
}

pub fn socket_tcp_v6() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet6,
                                SockType::Stream,
                                SockFlag::empty(),
                                SockLevel::Tcp as i32));
    Ok(socket_fd)
}

pub fn socket_tcp_bound(addr: &str) -> io::Result<net::TcpListener> {
    let actual: SocketAddr = FromStr::from_str(addr).expect("Invalid address");
    let nix_addr = SockAddr::Inet(InetAddr::from_std(&actual));
    let socket_fd = match actual {
        SocketAddr::V4(_) => try!(socket_tcp_v4()),
        SocketAddr::V6(_) => try!(socket_tcp_v6()),
    };
    let _ = setsockopt(socket_fd, sockopt::ReuseAddr, &true);
    let _ = setsockopt(socket_fd, sockopt::ReusePort, &true);
    let _ = setsockopt(socket_fd, sockopt::TcpNoDelay, &true);
    bind(socket_fd, &nix_addr).expect("Unable to bind a TCP socket");
    listen(socket_fd, TCP_BACKLOG).expect("Unable to listen to the TCP socket");
    let socket = unsafe { net::TcpListener::from_raw_fd(socket_fd) };
    Ok(socket)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn socket_udp_set_buffer_size(socket_fd: RawFd) {
    let _ = setsockopt(socket_fd, sockopt::SndBufForce, &UDP_BUFFER_SIZE);
    let _ = setsockopt(socket_fd, sockopt::RcvBufForce, &UDP_BUFFER_SIZE);
}

#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn socket_udp_set_buffer_size(socket_fd: RawFd) {
    let _ = setsockopt(socket_fd, sockopt::SndBuf, &UDP_BUFFER_SIZE);
    let _ = setsockopt(socket_fd, sockopt::RcvBuf, &UDP_BUFFER_SIZE);
}

pub fn socket_udp_v4() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet,
                                SockType::Datagram,
                                SockFlag::empty(),
                                SockLevel::Udp as i32));
    Ok(socket_fd)
}

pub fn socket_udp_v6() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet6,
                                SockType::Datagram,
                                SockFlag::empty(),
                                SockLevel::Udp as i32));
    Ok(socket_fd)
}

pub fn socket_udp_bound(addr: &str) -> io::Result<UdpSocket> {
    let actual: SocketAddr = FromStr::from_str(addr).expect("Invalid address");
    let nix_addr = SockAddr::Inet(InetAddr::from_std(&actual));
    let socket_fd = match actual {
        SocketAddr::V4(_) => try!(socket_udp_v4()),
        SocketAddr::V6(_) => try!(socket_udp_v6()),
    };
    let _ = setsockopt(socket_fd, sockopt::ReuseAddr, &true);
    let _ = setsockopt(socket_fd, sockopt::ReusePort, &true);
    socket_udp_set_buffer_size(socket_fd);
    bind(socket_fd, &nix_addr).expect("Unable to bind a UDP socket");
    let socket = unsafe { UdpSocket::from_raw_fd(socket_fd) };
    Ok(socket)
}

pub fn set_nonblock(sock: RawFd) -> io::Result<()> {
    try!(fcntl(sock, F_SETFL(O_NONBLOCK)));
    Ok(())
}
<commit_msg>Inline<commit_after>use nix::fcntl::FcntlArg::F_SETFL;
use nix::fcntl::{fcntl, O_NONBLOCK};
use nix::sys::socket::{bind, listen, setsockopt, sockopt, AddressFamily, SockFlag, SockType,
                       SockLevel, SockAddr, socket, InetAddr};
use std::net::{self, SocketAddr, UdpSocket};
use std::io;
use std::os::unix::io::{RawFd, FromRawFd};
use std::str::FromStr;
use super::{TCP_BACKLOG, UDP_BUFFER_SIZE};

#[inline]
pub fn socket_tcp_v4() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet,
                                SockType::Stream,
                                SockFlag::empty(),
                                SockLevel::Tcp as i32));
    Ok(socket_fd)
}

#[inline]
pub fn socket_tcp_v6() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet6,
                                SockType::Stream,
                                SockFlag::empty(),
                                SockLevel::Tcp as i32));
    Ok(socket_fd)
}

pub fn socket_tcp_bound(addr: &str) -> io::Result<net::TcpListener> {
    let actual: SocketAddr = FromStr::from_str(addr).expect("Invalid address");
    let nix_addr = SockAddr::Inet(InetAddr::from_std(&actual));
    let socket_fd = match actual {
        SocketAddr::V4(_) => try!(socket_tcp_v4()),
        SocketAddr::V6(_) => try!(socket_tcp_v6()),
    };
    let _ = setsockopt(socket_fd, sockopt::ReuseAddr, &true);
    let _ = setsockopt(socket_fd, sockopt::ReusePort, &true);
    let _ = setsockopt(socket_fd, sockopt::TcpNoDelay, &true);
    bind(socket_fd, &nix_addr).expect("Unable to bind a TCP socket");
    listen(socket_fd, TCP_BACKLOG).expect("Unable to listen to the TCP socket");
    let socket = unsafe { net::TcpListener::from_raw_fd(socket_fd) };
    Ok(socket)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn socket_udp_set_buffer_size(socket_fd: RawFd) {
    let _ = setsockopt(socket_fd, sockopt::SndBufForce, &UDP_BUFFER_SIZE);
    let _ = setsockopt(socket_fd, sockopt::RcvBufForce, &UDP_BUFFER_SIZE);
}

#[cfg(not(any(target_os = "linux", target_os = "android")))]
pub fn socket_udp_set_buffer_size(socket_fd: RawFd) {
    let _ = setsockopt(socket_fd, sockopt::SndBuf, &UDP_BUFFER_SIZE);
    let _ = setsockopt(socket_fd, sockopt::RcvBuf, &UDP_BUFFER_SIZE);
}

#[inline]
pub fn socket_udp_v4() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet,
                                SockType::Datagram,
                                SockFlag::empty(),
                                SockLevel::Udp as i32));
    Ok(socket_fd)
}

#[inline]
pub fn socket_udp_v6() -> io::Result<RawFd> {
    let socket_fd = try!(socket(AddressFamily::Inet6,
                                SockType::Datagram,
                                SockFlag::empty(),
                                SockLevel::Udp as i32));
    Ok(socket_fd)
}

pub fn socket_udp_bound(addr: &str) -> io::Result<UdpSocket> {
    let actual: SocketAddr = FromStr::from_str(addr).expect("Invalid address");
    let nix_addr = SockAddr::Inet(InetAddr::from_std(&actual));
    let socket_fd = match actual {
        SocketAddr::V4(_) => try!(socket_udp_v4()),
        SocketAddr::V6(_) => try!(socket_udp_v6()),
    };
    let _ = setsockopt(socket_fd, sockopt::ReuseAddr, &true);
    let _ = setsockopt(socket_fd, sockopt::ReusePort, &true);
    socket_udp_set_buffer_size(socket_fd);
    bind(socket_fd, &nix_addr).expect("Unable to bind a UDP socket");
    let socket = unsafe { UdpSocket::from_raw_fd(socket_fd) };
    Ok(socket)
}

#[inline]
pub fn set_nonblock(sock: RawFd) -> io::Result<()> {
    try!(fcntl(sock, F_SETFL(O_NONBLOCK)));
    Ok(())
}
<|endoftext|>


<commit_before>use address::{LENGTH, Address, Addressable};
use node::Node;
use num::bigint::{BigUint, ToBigUint};
use std::cmp;
use std::collections::HashMap;
use std::fmt;
use time;
use num;

const MINUTES_UNTIL_NEEDS_REFRESH: i64 = 15;

#[derive(Debug, PartialEq)]
pub enum InsertOutcome {
    Inserted,   // Inserted new node
    Updated,    // Updated existing node
    Discarded   // Bucket is full
}

pub type InsertionResult = Result<InsertOutcome, String>;

pub struct NodeBucket {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, Box<Node>>,
    last_inserted: time::Tm
}

impl fmt::Debug for NodeBucket {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NodeBucket {{ [{:040x} - {:040x}], contains: {:?} last_changed: {:?}}}",
               self.min, self.max, self.addresses, self.last_changed())
    }
}

impl NodeBucket {
    pub fn new(k: usize) -> NodeBucket {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k),
            last_inserted: time::empty_tm()
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn find_node(&mut self, address: &Address) -> Option<&mut Box<Node>> {
        self.nodes.get_mut(address)
    }

    pub fn get_nodes(&mut self) -> Vec<&mut Box<Node>> {
        self.nodes.iter_mut().map(|(_, node)| node).collect()
    }

    pub fn questionable_nodes(&mut self) -> Vec<&mut Box<Node>> {
        self.nodes.iter_mut()
            .map(|(_, node)| node)
            .filter(|n| n.is_questionable())
            .collect()
    }

    pub fn insert(&mut self, node: Box<Node>) -> InsertionResult {
        let address = node.get_address();
        if self.covers(&address) {
            if let Some(pos) = self.addresses.iter().position(|a| a == &address) {
                // TODO: Should this update the node's socket address incase a device has changed
                // IPs?
                self.addresses.remove(pos);
                self.addresses.insert(0, address);
                self.last_inserted = time::now_utc();
                Ok(InsertOutcome::Updated)
            } else if !self.is_full() {
                self.addresses.insert(0, address);
                self.nodes.insert(address, node);
                self.last_inserted = time::now_utc();
                Ok(InsertOutcome::Inserted)
            } else {
                Ok(InsertOutcome::Discarded)
            }
        } else {
            Err(format!("Bucket {:?}  does not cover {:?}", self, address))
        }
    }

    pub fn is_full(&self) -> bool {
        self.addresses.len() >= self.k
    }

    pub fn last_changed(&self) -> time::Tm {
        if let Some((_, node)) = self.nodes.iter().max_by_key(|&(_, node)| node.last_seen()) {
            cmp::max(self.last_inserted, node.last_seen())
        } else {
            self.last_inserted
        }
    }

    pub fn needs_refresh(&self) -> bool {
        let time_since_changed = time::now_utc() - self.last_changed();
        time_since_changed > time::Duration::minutes(MINUTES_UNTIL_NEEDS_REFRESH)
    }

    pub fn random_address_in_space(&self) -> Address {
        Address::random(&self.min, &self.max)
    }

    fn remove(&mut self, address: &Address) {
        self.nodes.remove(address);
        let pos = self.addresses.iter().position(|a| a == address).unwrap();
        self.addresses.remove(pos);
    }

    pub fn remove_bad_nodes(&mut self) {
        let mut to_remove = vec![];
        for (address, node) in self.nodes.iter() {
            if node.is_bad() {
                to_remove.push(address.clone());
            }
        }
        for address in to_remove {
            self.remove(&address);
        }
    }

    pub fn split(self) -> (Self, Self) {
        let difference = &self.max - &self.min;
        let partition = difference / 2.to_biguint().unwrap() + &self.min;
        let (a_addresses, b_addresses) = self.addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.into_iter() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min,
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes,
            last_inserted: self.last_inserted
        };
        let b = NodeBucket {
            k: self.k,
            min: partition,
            max: self.max,
            addresses: b_addresses,
            nodes: b_nodes,
            last_inserted: self.last_inserted
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::{InsertOutcome, NodeBucket};
    use tests::TestNode;
    use time;

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node = Box::new(TestNode::new(Address::for_content("some string")));
        assert_eq!(bucket.insert(node).unwrap(), InsertOutcome::Inserted);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let addr_1 = Address::for_content("node 1");
        let addr_2 = Address::for_content("node 2");
        let addr_3 = Address::for_content("node 1");
        let a = Box::new(TestNode::new(addr_1));
        let b = Box::new(TestNode::new(addr_2));
        let c = Box::new(TestNode::new(addr_3));

        bucket.insert(a).unwrap();
        bucket.insert(b).unwrap();
        assert_eq!(bucket.insert(c).unwrap(), InsertOutcome::Updated);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")].get_address(), addr_1);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1")))).unwrap();
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2")))).unwrap();
        let result = bucket.insert(Box::new(TestNode::new(Address::for_content("node 3")))).unwrap();
        assert_eq!(result, InsertOutcome::Discarded);
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn insert_node_outside_of_address_space() {
        use num::bigint::ToBigUint;
        use std::collections::HashMap;

        let mut bucket = NodeBucket {
            k: 8,
            min: 0.to_biguint().unwrap(),
            max: 1.to_biguint().unwrap(),
            addresses: vec![],
            nodes: HashMap::new(),
            last_inserted: time::empty_tm()
        };
        let result = bucket.insert(Box::new(TestNode::new(Address::for_content("node 3"))));
        assert!(result.is_err());
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1")))).unwrap();
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2")))).unwrap();
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1")))).unwrap();
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket = NodeBucket::new(4);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000000");
        let addr_2 = Address::from_str("7fffffffffffffffffffffffffffffffffffffff");
        let addr_3 = Address::from_str("8000000000000000000000000000000000000000");
        let addr_4 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        let node_4 = Box::new(TestNode::new(addr_4));

        bucket.insert(node_1).unwrap();
        bucket.insert(node_2).unwrap();
        bucket.insert(node_3).unwrap();
        bucket.insert(node_4).unwrap();

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")].get_address(), addr_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")].get_address(), addr_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")].get_address(), addr_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }

    #[test]
    fn test_last_changed() {
        let mut bucket: NodeBucket = NodeBucket::new(4);

        // it updates upon inserting a node
        let last_changed_before_insert = bucket.last_changed();
        let addr = Address::from_str("0000000000000000000000000000000000000000");
        let node = Box::new(TestNode::new(addr));
        bucket.insert(node).unwrap();
        let last_changed_after_insert = bucket.last_changed();
        assert!(last_changed_before_insert < last_changed_after_insert);

        // it updates when one of its nodes are heard from
        let last_changed_before_received = bucket.last_changed();
        bucket.find_node(&addr).unwrap().received_response(1);
        let last_changed_after_received = bucket.last_changed();
        assert!(last_changed_before_received < last_changed_after_received);
    }

    #[test]
    fn test_remove_bad_nodes() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node_1 = Box::new(TestNode::new(Address::for_content("good node")));
        let node_2 = Box::new(TestNode::questionable(Address::for_content("questionable node")));
        let node_3 = Box::new(TestNode::bad(Address::for_content("bad node")));
        bucket.insert(node_1).unwrap();
        bucket.insert(node_2).unwrap();
        bucket.insert(node_3).unwrap();
        assert_eq!(bucket.addresses.len(), 3);

        bucket.remove_bad_nodes();
        assert_eq!(bucket.addresses.len(), 2);
    }
}
<commit_msg>Impl is_full in terms of nodes hash<commit_after>use address::{LENGTH, Address, Addressable};
use node::Node;
use num::bigint::{BigUint, ToBigUint};
use std::cmp;
use std::collections::HashMap;
use std::fmt;
use time;
use num;

const MINUTES_UNTIL_NEEDS_REFRESH: i64 = 15;

#[derive(Debug, PartialEq)]
pub enum InsertOutcome {
    Inserted,   // Inserted new node
    Updated,    // Updated existing node
    Discarded   // Bucket is full
}

pub type InsertionResult = Result<InsertOutcome, String>;

pub struct NodeBucket {
    k: usize,
    min: BigUint,
    max: BigUint,
    addresses: Vec<Address>,
    nodes: HashMap<Address, Box<Node>>,
    last_inserted: time::Tm
}

impl fmt::Debug for NodeBucket {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NodeBucket {{ [{:040x} - {:040x}], contains: {:?} last_changed: {:?}}}",
               self.min, self.max, self.addresses, self.last_changed())
    }
}

impl NodeBucket {
    pub fn new(k: usize) -> NodeBucket {
        let min = 0.to_biguint().unwrap();
        let max = num::pow(2.to_biguint().unwrap(), LENGTH);
        NodeBucket {
            k: k,
            min: min,
            max: max,
            addresses: Vec::with_capacity(k),
            nodes: HashMap::with_capacity(k),
            last_inserted: time::empty_tm()
        }
    }

    pub fn contains(&self, address: &Address) -> bool {
        self.addresses.contains(address)
    }

    pub fn covers(&self, address: &Address) -> bool {
        let numeric = address.as_numeric();
        self.min <= numeric && numeric < self.max
    }

    pub fn find_node(&mut self, address: &Address) -> Option<&mut Box<Node>> {
        self.nodes.get_mut(address)
    }

    pub fn get_nodes(&mut self) -> Vec<&mut Box<Node>> {
        self.nodes.iter_mut().map(|(_, node)| node).collect()
    }

    pub fn questionable_nodes(&mut self) -> Vec<&mut Box<Node>> {
        self.nodes.iter_mut()
            .map(|(_, node)| node)
            .filter(|n| n.is_questionable())
            .collect()
    }

    pub fn insert(&mut self, node: Box<Node>) -> InsertionResult {
        let address = node.get_address();
        if self.covers(&address) {
            if let Some(pos) = self.addresses.iter().position(|a| a == &address) {
                // TODO: Should this update the node's socket address incase a device has changed
                // IPs?
                self.addresses.remove(pos);
                self.addresses.insert(0, address);
                self.last_inserted = time::now_utc();
                Ok(InsertOutcome::Updated)
            } else if !self.is_full() {
                self.addresses.insert(0, address);
                self.nodes.insert(address, node);
                self.last_inserted = time::now_utc();
                Ok(InsertOutcome::Inserted)
            } else {
                Ok(InsertOutcome::Discarded)
            }
        } else {
            Err(format!("Bucket {:?}  does not cover {:?}", self, address))
        }
    }

    pub fn is_full(&self) -> bool {
        self.nodes.len() >= self.k
    }

    pub fn last_changed(&self) -> time::Tm {
        if let Some((_, node)) = self.nodes.iter().max_by_key(|&(_, node)| node.last_seen()) {
            cmp::max(self.last_inserted, node.last_seen())
        } else {
            self.last_inserted
        }
    }

    pub fn needs_refresh(&self) -> bool {
        let time_since_changed = time::now_utc() - self.last_changed();
        time_since_changed > time::Duration::minutes(MINUTES_UNTIL_NEEDS_REFRESH)
    }

    pub fn random_address_in_space(&self) -> Address {
        Address::random(&self.min, &self.max)
    }

    fn remove(&mut self, address: &Address) {
        self.nodes.remove(address);
        let pos = self.addresses.iter().position(|a| a == address).unwrap();
        self.addresses.remove(pos);
    }

    pub fn remove_bad_nodes(&mut self) {
        let mut to_remove = vec![];
        for (address, node) in self.nodes.iter() {
            if node.is_bad() {
                to_remove.push(address.clone());
            }
        }
        for address in to_remove {
            self.remove(&address);
        }
    }

    pub fn split(self) -> (Self, Self) {
        let difference = &self.max - &self.min;
        let partition = difference / 2.to_biguint().unwrap() + &self.min;
        let (a_addresses, b_addresses) = self.addresses
            .into_iter()
            .partition(|&a| a.as_numeric() < partition);
        let mut a_nodes = HashMap::new();
        let mut b_nodes = HashMap::new();
        for (address, node) in self.nodes.into_iter() {
            if address.as_numeric() < partition {
                a_nodes.insert(address, node);
            } else {
                b_nodes.insert(address, node);
            }
        }

        let a = NodeBucket {
            k: self.k,
            min: self.min,
            max: partition.clone(),
            addresses: a_addresses,
            nodes: a_nodes,
            last_inserted: self.last_inserted
        };
        let b = NodeBucket {
            k: self.k,
            min: partition,
            max: self.max,
            addresses: b_addresses,
            nodes: b_nodes,
            last_inserted: self.last_inserted
        };
        (a, b)
    }
}

#[cfg(test)]
mod tests {
    use address::{Address, Addressable};
    use super::{InsertOutcome, NodeBucket};
    use tests::TestNode;
    use time;

    #[test]
    fn test_insert() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node = Box::new(TestNode::new(Address::for_content("some string")));
        assert_eq!(bucket.insert(node).unwrap(), InsertOutcome::Inserted);
        assert_eq!(bucket.addresses.len(), 1);
    }

    #[test]
    fn test_insert_duplicate() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let addr_1 = Address::for_content("node 1");
        let addr_2 = Address::for_content("node 2");
        let addr_3 = Address::for_content("node 1");
        let a = Box::new(TestNode::new(addr_1));
        let b = Box::new(TestNode::new(addr_2));
        let c = Box::new(TestNode::new(addr_3));

        bucket.insert(a).unwrap();
        bucket.insert(b).unwrap();
        assert_eq!(bucket.insert(c).unwrap(), InsertOutcome::Updated);

        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes[&Address::for_content("node 1")].get_address(), addr_1);
    }

    #[test]
    fn test_insert_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1")))).unwrap();
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2")))).unwrap();
        let result = bucket.insert(Box::new(TestNode::new(Address::for_content("node 3")))).unwrap();
        assert_eq!(result, InsertOutcome::Discarded);
        assert_eq!(bucket.addresses.len(), 2);
        assert_eq!(bucket.nodes.get(&Address::for_content("node 3")), None);
    }

    #[test]
    fn insert_node_outside_of_address_space() {
        use num::bigint::ToBigUint;
        use std::collections::HashMap;

        let mut bucket = NodeBucket {
            k: 8,
            min: 0.to_biguint().unwrap(),
            max: 1.to_biguint().unwrap(),
            addresses: vec![],
            nodes: HashMap::new(),
            last_inserted: time::empty_tm()
        };
        let result = bucket.insert(Box::new(TestNode::new(Address::for_content("node 3"))));
        assert!(result.is_err());
    }

    #[test]
    fn test_is_full() {
        let mut bucket: NodeBucket = NodeBucket::new(2);
        assert!(!bucket.is_full());

        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1")))).unwrap();
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 2")))).unwrap();
        assert!(bucket.is_full());
    }

    #[test]
    fn test_contains() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        bucket.insert(Box::new(TestNode::new(Address::for_content("node 1")))).unwrap();
        assert!(bucket.contains(&Address::for_content("node 1")));
    }

    #[test]
    fn test_covers() {
        let bucket: NodeBucket = NodeBucket::new(8);
        let address_1 = Address::from_str("0000000000000000000000000000000000000000");
        let address_2 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        assert!(bucket.covers(&address_1));
        assert!(bucket.covers(&address_2));
    }

    #[test]
    fn test_split() {
        let mut bucket: NodeBucket = NodeBucket::new(4);
        let addr_1 = Address::from_str("0000000000000000000000000000000000000000");
        let addr_2 = Address::from_str("7fffffffffffffffffffffffffffffffffffffff");
        let addr_3 = Address::from_str("8000000000000000000000000000000000000000");
        let addr_4 = Address::from_str("ffffffffffffffffffffffffffffffffffffffff");
        let node_1 = Box::new(TestNode::new(addr_1));
        let node_2 = Box::new(TestNode::new(addr_2));
        let node_3 = Box::new(TestNode::new(addr_3));
        let node_4 = Box::new(TestNode::new(addr_4));

        bucket.insert(node_1).unwrap();
        bucket.insert(node_2).unwrap();
        bucket.insert(node_3).unwrap();
        bucket.insert(node_4).unwrap();

        let (a, b) = bucket.split();

        // Splits up known address
        assert_eq!(a.addresses.len(), 2);
        assert_eq!(b.addresses.len(), 2);

        // Splits up known nodes
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("0000000000000000000000000000000000000000")].get_address(), addr_1);
        assert_eq!(a.nodes[&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")].get_address(), addr_2);
        assert_eq!(b.nodes[&Address::from_str("8000000000000000000000000000000000000000")].get_address(), addr_3);
        assert_eq!(b.nodes[&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")].get_address(), addr_4);

        // Equitably covers address space
        assert!(a.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(!b.covers(&Address::from_str("0000000000000000000000000000000000000000")));
        assert!(a.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!b.covers(&Address::from_str("7fffffffffffffffffffffffffffffffffffffff")));
        assert!(!a.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(b.covers(&Address::from_str("8000000000000000000000000000000000000000")));
        assert!(!a.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
        assert!(b.covers(&Address::from_str("ffffffffffffffffffffffffffffffffffffffff")));
    }

    #[test]
    fn test_last_changed() {
        let mut bucket: NodeBucket = NodeBucket::new(4);

        // it updates upon inserting a node
        let last_changed_before_insert = bucket.last_changed();
        let addr = Address::from_str("0000000000000000000000000000000000000000");
        let node = Box::new(TestNode::new(addr));
        bucket.insert(node).unwrap();
        let last_changed_after_insert = bucket.last_changed();
        assert!(last_changed_before_insert < last_changed_after_insert);

        // it updates when one of its nodes are heard from
        let last_changed_before_received = bucket.last_changed();
        bucket.find_node(&addr).unwrap().received_response(1);
        let last_changed_after_received = bucket.last_changed();
        assert!(last_changed_before_received < last_changed_after_received);
    }

    #[test]
    fn test_remove_bad_nodes() {
        let mut bucket: NodeBucket = NodeBucket::new(8);
        let node_1 = Box::new(TestNode::new(Address::for_content("good node")));
        let node_2 = Box::new(TestNode::questionable(Address::for_content("questionable node")));
        let node_3 = Box::new(TestNode::bad(Address::for_content("bad node")));
        bucket.insert(node_1).unwrap();
        bucket.insert(node_2).unwrap();
        bucket.insert(node_3).unwrap();
        assert_eq!(bucket.addresses.len(), 3);

        bucket.remove_bad_nodes();
        assert_eq!(bucket.addresses.len(), 2);
    }
}
<|endoftext|>


<commit_before>use std::error::Error;

//Following semver here
#[derive(Clone, Debug, PartialOrd, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub major: u16,
    pub minor: u16,
    pub patch: u32
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
pub struct Package {
    pub name: String,
    pub version: Version,
    pub crc32: u32,
    pub child_url: String, // Examples: /some_dir/something.exe
    pub dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    pub packages: Vec<Package>,
    pub parent_url: String, // Examples: https://www.foo.bar
    pub version: u32
}

impl Version {
    pub fn new() -> Version {
        Version {
            major: 0u16,
            minor: 0u16,
            patch: 0u32
        }
    }

    pub fn from(major: u16, minor: u16, patch: u32) -> Version {
        Version {
            major: major,
            minor: minor,
            patch: patch
        }
    }

    pub fn from_str(input: &str) -> Result<Version, String> {
        let versions: Vec<&str> = input.split('.').collect();
        if versions.len() == 3 {
            return Ok(
                Version {
                    major: get!(versions[0].parse::<u16>(),"Version: Unable to parse &str into u16 (major)"),
                    minor: get!(versions[1].parse::<u16>(),"Version: Unable to parse &str into u16 (minor)"),
                    patch: get!(versions[2].parse::<u32>(),"Version: Unable to parse &str into u32 (patch)")
                }
            )
        } else {
            return Err("Version::from_str() cannot parse provided input into Version: invalid input".to_string())
        }
    }
}

impl PartialEq for Version {
    fn eq(&self, other: &Version) -> bool {
        self.major == other.major &&
        self.minor == other.minor &&
        self.patch == other.patch
    }
}

impl ToString for Version {
    fn to_string(&self) -> String {
        String::from(self.major.to_string() + "." + &self.minor.to_string() + "." + &self.minor.to_string())
    }
}

impl PartialEq for Package {
    fn eq(&self, other: &Package) -> bool {
        self.name == other.name &&
        self.version == other.version &&
        self.crc32 == other.crc32 &&
        self.dependencies == other.dependencies
    }
}
<commit_msg>Combining both child url and parent url<commit_after>use std::error::Error;

//Following semver here
#[derive(Clone, Debug, PartialOrd, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub major: u16,
    pub minor: u16,
    pub patch: u32
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
pub struct Package {
    pub name: String,
    pub version: Version,
    pub crc32: u32,
    pub url: String,
    pub dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    pub packages: Vec<Package>,
    pub version: u32
}

impl Version {
    pub fn new() -> Version {
        Version {
            major: 0u16,
            minor: 0u16,
            patch: 0u32
        }
    }

    pub fn from(major: u16, minor: u16, patch: u32) -> Version {
        Version {
            major: major,
            minor: minor,
            patch: patch
        }
    }

    pub fn from_str(input: &str) -> Result<Version, String> {
        let versions: Vec<&str> = input.split('.').collect();
        if versions.len() == 3 {
            return Ok(
                Version {
                    major: get!(versions[0].parse::<u16>(),"Version: Unable to parse &str into u16 (major)"),
                    minor: get!(versions[1].parse::<u16>(),"Version: Unable to parse &str into u16 (minor)"),
                    patch: get!(versions[2].parse::<u32>(),"Version: Unable to parse &str into u32 (patch)")
                }
            )
        } else {
            return Err("Version::from_str() cannot parse provided input into Version: invalid input".to_string())
        }
    }
}

impl PartialEq for Version {
    fn eq(&self, other: &Version) -> bool {
        self.major == other.major &&
        self.minor == other.minor &&
        self.patch == other.patch
    }
}

impl ToString for Version {
    fn to_string(&self) -> String {
        String::from(self.major.to_string() + "." + &self.minor.to_string() + "." + &self.minor.to_string())
    }
}

impl PartialEq for Package {
    fn eq(&self, other: &Package) -> bool {
        self.name == other.name &&
        self.version == other.version &&
        self.crc32 == other.crc32 &&
        self.dependencies == other.dependencies
    }
}
<|endoftext|>


<commit_before>//! A PNG Encoder
//!
//! This implementation uses the ```flate``` crate for compression
//! and selects the filter type using the sum of absolute differences method.
//!
//! For each row the filter method that produces the lowest integer when its bytes
//! are interpreted as signed numbers and summed is chosen as the filter.

use std::slice;
use std::old_io:: {
    IoResult,
    MemWriter
};
use std::num::FromPrimitive;
use std::iter::repeat;

use color;
use super::hash::Crc32;

use super::filter::filter;
use super::decoder::PNGSIGNATURE;

/// The representation of a PNG encoder
pub struct PNGEncoder<'a, W: 'a> {
    w: &'a mut W,
    crc: Crc32
}

impl<'a, W: Writer> PNGEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: &mut W) -> PNGEncoder<W> {
        PNGEncoder {
            w: w,
            crc: Crc32::new()
        }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(&mut self,
                  image: &[u8],
                  width: u32,
                  height: u32,
                  c: color::ColorType) -> IoResult<()> {

        let _ = try!(self.write_signature());
        let (bytes, bpp) = build_ihdr(width, height, c);

        let _ = try!(self.write_chunk("IHDR", &bytes));
        let compressed_bytes = build_idat(image, bpp, width, height);

        for chunk in compressed_bytes.chunks(1024 * 256) {
            let _ = try!(self.write_chunk("IDAT", chunk));
        }

        self.write_chunk("IEND", &[])
    }

    fn write_signature(&mut self) -> IoResult<()> {
        self.w.write_all(&PNGSIGNATURE)
    }

    fn write_chunk(&mut self, name: &str, buf: &[u8]) -> IoResult<()> {
        self.crc.reset();
        self.crc.update(name);
        self.crc.update(&buf);

        let crc = self.crc.checksum();

        let _ = try!(self.w.write_be_u32(buf.len() as u32));
        let _ = try!(self.w.write_str(name));
        let _ = try!(self.w.write_all(buf));
        let _ = try!(self.w.write_be_u32(crc));

        Ok(())
    }
}

fn build_ihdr(width: u32, height: u32, c: color::ColorType) -> (Vec<u8>, usize) {
    let mut m = MemWriter::with_capacity(13);

    let _ = m.write_be_u32(width);
    let _ = m.write_be_u32(height);

    let (colortype, bit_depth) = match c {
        color::ColorType::Gray(1)    => (0, 1),
        color::ColorType::Gray(2)    => (0, 2),
        color::ColorType::Gray(4)    => (0, 4),
        color::ColorType::Gray(8)    => (0, 8),
        color::ColorType::Gray(16)   => (0, 16),
        color::ColorType::RGB(8)     => (2, 8),
        color::ColorType::RGB(16)    => (2, 16),
        color::ColorType::Palette(1) => (3, 1),
        color::ColorType::Palette(2) => (3, 2),
        color::ColorType::Palette(4) => (3, 4),
        color::ColorType::Palette(8) => (3, 8),
        color::ColorType::GrayA(8)   => (4, 8),
        color::ColorType::GrayA(16)  => (4, 16),
        color::ColorType::RGBA(8)    => (6, 8),
        color::ColorType::RGBA(16)   => (6, 16),
        _ => panic!("unsupported color type and bitdepth")
    };

    let _ = m.write_u8(bit_depth);
    let _ = m.write_u8(colortype);

    // Compression method, filter method and interlace
    let _ = m.write_u8(0);
    let _ = m.write_u8(0);
    let _ = m.write_u8(0);

    let channels = match colortype {
        0 => 1,
        2 => 3,
        3 => 3,
        4 => 2,
        6 => 4,
        _ => panic!("unknown colour type")
    };

    let bpp = ((channels * bit_depth + 7) / 8) as usize;

    (m.into_inner(), bpp)
}

fn sum_abs_difference(buf: &[u8]) -> i32 {
    buf.iter().fold(0i32, | sum, &b | sum + if b < 128 {b as i32} else {256 - b as i32})
}

fn select_filter(rowlength: usize, bpp: usize, previous: &[u8], current_s: &mut [u8]) -> u8 {
    let mut sum    = sum_abs_difference(&current_s[..rowlength]);
    let mut method = 0;

    for (i, current) in current_s.chunks_mut(rowlength).enumerate() {
        filter(FromPrimitive::from_u8(i as u8 + 1).unwrap(), bpp, previous, current);

        let this_sum = sum_abs_difference(current);

        if this_sum < sum {
            sum = this_sum;
            method = i as u8 + 1;
        }
    }

    method
}

fn build_idat(image: &[u8], bpp: usize, width: u32, height: u32) -> Vec<u8> {
    use flate::deflate_bytes_zlib;

    let rowlen = bpp * width as usize;

    let mut p: Vec<u8> = repeat(0u8).take(rowlen).collect();
    let mut c: Vec<u8> = repeat(0u8).take(4 * rowlen).collect();
    let mut b: Vec<u8> = repeat(0u8).take(height as usize + rowlen * height as usize).collect();

    for (row, outrow) in image.chunks(rowlen).zip(b.chunks_mut(1 + rowlen)) {
        for s in c.chunks_mut(rowlen) {
            slice::bytes::copy_memory(s, row);
        }

        let filter = select_filter(rowlen, bpp, &p, &mut c);

        outrow[0]  = filter;
        let out    = &mut outrow[1..];
        let stride = (filter as usize - 1) * rowlen;

        match filter {
            0 => slice::bytes::copy_memory(out, row),
            _ => slice::bytes::copy_memory(out, &c[stride..stride + rowlen]),
        }

        slice::bytes::copy_memory(&mut p, row);
    }

    deflate_bytes_zlib(&b).unwrap().to_vec()
}
<commit_msg>Fix integer overflow<commit_after>//! A PNG Encoder
//!
//! This implementation uses the ```flate``` crate for compression
//! and selects the filter type using the sum of absolute differences method.
//!
//! For each row the filter method that produces the lowest integer when its bytes
//! are interpreted as signed numbers and summed is chosen as the filter.

use std::slice;
use std::old_io:: {
    IoResult,
    MemWriter
};
use std::num::FromPrimitive;
use std::iter::repeat;

use color;
use super::hash::Crc32;

use super::filter::filter;
use super::decoder::PNGSIGNATURE;

/// The representation of a PNG encoder
pub struct PNGEncoder<'a, W: 'a> {
    w: &'a mut W,
    crc: Crc32
}

impl<'a, W: Writer> PNGEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```
    pub fn new(w: &mut W) -> PNGEncoder<W> {
        PNGEncoder {
            w: w,
            crc: Crc32::new()
        }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```
    pub fn encode(&mut self,
                  image: &[u8],
                  width: u32,
                  height: u32,
                  c: color::ColorType) -> IoResult<()> {

        let _ = try!(self.write_signature());
        let (bytes, bpp) = build_ihdr(width, height, c);

        let _ = try!(self.write_chunk("IHDR", &bytes));
        let compressed_bytes = build_idat(image, bpp, width, height);

        for chunk in compressed_bytes.chunks(1024 * 256) {
            let _ = try!(self.write_chunk("IDAT", chunk));
        }

        self.write_chunk("IEND", &[])
    }

    fn write_signature(&mut self) -> IoResult<()> {
        self.w.write_all(&PNGSIGNATURE)
    }

    fn write_chunk(&mut self, name: &str, buf: &[u8]) -> IoResult<()> {
        self.crc.reset();
        self.crc.update(name);
        self.crc.update(&buf);

        let crc = self.crc.checksum();

        let _ = try!(self.w.write_be_u32(buf.len() as u32));
        let _ = try!(self.w.write_str(name));
        let _ = try!(self.w.write_all(buf));
        let _ = try!(self.w.write_be_u32(crc));

        Ok(())
    }
}

fn build_ihdr(width: u32, height: u32, c: color::ColorType) -> (Vec<u8>, usize) {
    let mut m = MemWriter::with_capacity(13);

    let _ = m.write_be_u32(width);
    let _ = m.write_be_u32(height);

    let (colortype, bit_depth) = match c {
        color::ColorType::Gray(1)    => (0, 1),
        color::ColorType::Gray(2)    => (0, 2),
        color::ColorType::Gray(4)    => (0, 4),
        color::ColorType::Gray(8)    => (0, 8),
        color::ColorType::Gray(16)   => (0, 16),
        color::ColorType::RGB(8)     => (2, 8),
        color::ColorType::RGB(16)    => (2, 16),
        color::ColorType::Palette(1) => (3, 1),
        color::ColorType::Palette(2) => (3, 2),
        color::ColorType::Palette(4) => (3, 4),
        color::ColorType::Palette(8) => (3, 8),
        color::ColorType::GrayA(8)   => (4, 8),
        color::ColorType::GrayA(16)  => (4, 16),
        color::ColorType::RGBA(8)    => (6, 8),
        color::ColorType::RGBA(16)   => (6, 16),
        _ => panic!("unsupported color type and bitdepth")
    };

    let _ = m.write_u8(bit_depth);
    let _ = m.write_u8(colortype);

    // Compression method, filter method and interlace
    let _ = m.write_u8(0);
    let _ = m.write_u8(0);
    let _ = m.write_u8(0);

    let channels = match colortype {
        0 => 1,
        2 => 3,
        3 => 3,
        4 => 2,
        6 => 4,
        _ => panic!("unknown colour type")
    };

    let bpp = ((channels * bit_depth + 7) / 8) as usize;

    (m.into_inner(), bpp)
}

fn sum_abs_difference(buf: &[u8]) -> i32 {
    buf.iter().fold(0i32, | sum, &b | sum + if b < 128 {b as i32} else {256 - b as i32})
}

fn select_filter(rowlength: usize, bpp: usize, previous: &[u8], current_s: &mut [u8]) -> u8 {
    let mut sum    = sum_abs_difference(&current_s[..rowlength]);
    let mut method = 0;

    for (i, current) in current_s.chunks_mut(rowlength).enumerate() {
        filter(FromPrimitive::from_u8(i as u8 + 1).unwrap(), bpp, previous, current);

        let this_sum = sum_abs_difference(current);

        if this_sum < sum {
            sum = this_sum;
            method = i as u8 + 1;
        }
    }

    method
}

fn build_idat(image: &[u8], bpp: usize, width: u32, height: u32) -> Vec<u8> {
    use flate::deflate_bytes_zlib;

    let rowlen = bpp * width as usize;

    let mut p: Vec<u8> = repeat(0u8).take(rowlen).collect();
    let mut c: Vec<u8> = repeat(0u8).take(4 * rowlen).collect();
    let mut b: Vec<u8> = repeat(0u8).take(height as usize + rowlen * height as usize).collect();

    for (row, outrow) in image.chunks(rowlen).zip(b.chunks_mut(1 + rowlen)) {
        for s in c.chunks_mut(rowlen) {
            slice::bytes::copy_memory(s, row);
        }

        let filter = select_filter(rowlen, bpp, &p, &mut c);

        outrow[0]  = filter;
        let out    = &mut outrow[1..];

        match filter {
            0 => slice::bytes::copy_memory(out, row),
            _ => {
                let stride = (filter as usize - 1) * rowlen;
                slice::bytes::copy_memory(out, &c[stride..stride + rowlen])
            }
        }

        slice::bytes::copy_memory(&mut p, row);
    }

    deflate_bytes_zlib(&b).unwrap().to_vec()
}
<|endoftext|>


<commit_before>mod sortdir;
mod entity;

use std::io;
use std::ops::Range;
use std::path::PathBuf;
use std::rc::Rc;
use std::fs::{ Metadata, ReadDir };
use futures::{ future, stream, Stream, Future };
use hyper::{ header, Request, Response, Head, Body, StatusCode };
use mime_guess::guess_mime_type;
use maud::Render;
use slog::Logger;
use ::utils::{ path_canonicalize, decode_path };
use ::{ error, file, Httpd };
use self::sortdir::{ SortDir, up };
use self::entity::{ Entity, EntifyResult };

pub struct Process<'a> {
    httpd: &'a Httpd,
    log: &'a Logger,
    req: &'a Request,
    depth: usize,
    path: Rc<PathBuf>
}

impl<'a> Process<'a> {
    #[inline]
    pub fn new(httpd: &'a Httpd, log: &'a Logger, req: &'a Request) -> Process<'a> {
        let path_buf = decode_path(req.path());
        let (depth, path) = path_canonicalize(&httpd.root, path_buf);
        let path = Rc::new(path);
        Process { httpd, log, req, depth, path }
    }

    #[inline]
    pub fn process(&self) -> io::Result<Response> {
        let metadata = self.path.metadata()?;

        if let Ok(dir) = self.path.read_dir() {
            self.process_dir(dir)
        } else {
            self.process_file(&metadata)
        }
    }
}

impl<'a> Process<'a> {
    fn process_dir(&self, dir: ReadDir) -> io::Result<Response> {
        const HTML_HEADER: &str = "

";
        const HTML_FOOTER: &str = "
</table";

        let mut res = Response::new();

        if self.req.method() == &Head {
            res.set_body(Body::empty());
        } else {
            let log = self.log.clone();
            let is_root = self.depth == 0;
            let root = self.httpd.root.clone();
            let (send, body) = Body::pair();
            res.set_body(body);

            debug!(self.log, "process"; "method" => "senddir");

            let done = stream::once(Ok(chunk!(HTML_HEADER)))
                .chain(stream::once(Ok(chunk!(into up(is_root)))))
                .chain(stream::iter(SortDir::new(root, dir))
                    .map(|p| p.and_then(|m| chunk!(into m.render())).map_err(Into::into))
                )
                .chain(stream::once(Ok(chunk!(HTML_FOOTER))))
                .map_err(error::Error::from)
                .forward(send)
                .map(drop)
                .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

            self.httpd.remote.spawn(move |_| done);
        }

        // TODO https://github.com/hyperium/mime/issues/52
        let mime = "text/html; charset=utf-8".parse().unwrap();
        Ok(res.with_header(header::ContentType(mime)))
    }

    fn process_file(&self, metadata: &Metadata) -> io::Result<Response> {
        let entity = Entity::new(self.path.clone(), metadata, self.log);

        match entity.check(self.req.headers()) {
            EntifyResult::Err(resp) => Ok(resp.with_headers(entity.headers(false))),
            EntifyResult::None => {
                let handle = self.httpd.remote.handle()
                    .ok_or_else(|| err!(Other, "Remote get handle fail"))?;
                let fd = entity.open(handle)?;
                self.send(&fd, None)
                    .map(|res| res
                        .with_headers(entity.headers(false))
                        .with_header(header::ContentLength(fd.len))
                    )
            },
            EntifyResult::One(range) => {
                debug!(self.log, "process"; "range" => format_args!("{:?}", range));
                let handle = self.httpd.remote.handle()
                    .ok_or_else(|| err!(Other, "Remote get handle fail"))?;
                let fd = entity.open(handle)?;
                self.send(&fd, Some(range.clone()))
                    .map(|res| res
                         .with_status(StatusCode::PartialContent)
                         .with_headers(entity.headers(false))
                         .with_header(header::ContentLength(range.end - range.start))
                         .with_header(header::ContentRange(header::ContentRangeSpec::Bytes {
                            range: Some((range.start, range.end - 1)), instance_length: Some(fd.len)
                        }))
                    )
            },
            EntifyResult::Vec(ranges) => {
                const BOUNDARY_LINE: &str = concat!("--", boundary!(), "\r\n");

                debug!(self.log, "process"; "ranges" => format_args!("{:?}", ranges));

                let handle = self.httpd.remote.handle()
                    .ok_or_else(|| err!(Other, "Remote get handle fail"))?;
                let mut res = Response::new();

                if self.req.method() == &Head {
                    return Ok(res
                        .with_status(StatusCode::PartialContent)
                        .with_headers(entity.headers(true))
                        .with_body(Body::empty())
                    );
                }

                let log = self.log.clone();
                let fd = entity.open(handle)?;
                let (send, body) = Body::pair();
                res.set_body(body);

                let content_type = header::ContentType(guess_mime_type(&*self.path));

                let done = stream::iter::<_, _, error::Error>(ranges.into_iter().map(Ok))
                    .and_then(move |range| {
                        let len = range.end - range.start;
                        let mut headers = header::Headers::new();
                        headers.set(content_type.clone());
                        headers.set(header::ContentRange(header::ContentRangeSpec::Bytes {
                            range: Some((range.start, range.end - 1)), instance_length: Some(len)
                        }));

                        fd.read(range)
                            .map(move |fut| {
                                stream::once(Ok(chunk!(BOUNDARY_LINE)))
                                    .chain(stream::once(Ok(chunk!(format!("{}\r\n", headers)))))
                                    .chain(fut)
                                    .chain(stream::once(Ok(chunk!("\r\n"))))
                            })
                            .map_err(Into::into)
                    })
                    .flatten()
                    .forward(send)
                    .map(drop)
                    .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

                self.httpd.remote.spawn(move |_| done);

                Ok(res
                    .with_status(StatusCode::PartialContent)
                    .with_headers(entity.headers(true))
                )
            }
        }
    }

    fn send(&self, fd: &file::File, range: Option<Range<u64>>) -> io::Result<Response> {
        use ::file::CHUNK_BUFF_LENGTH;
        let mut res = Response::new();

        if self.req.method() == &Head {
            res.set_body(Body::empty());
        } else if let (&Some(ref socket), true) = (&self.httpd.socket, CHUNK_BUFF_LENGTH >= fd.len as _) {
            let range = range.unwrap_or_else(|| 0..fd.len);
            let log = self.log.clone();
            res.set_body(Body::empty());

            debug!(self.log, "process"; "method" => "sendfile");

            let done = fd.sendfile(range, socket.clone())?
                //              ^^^ FIXME not work for keepalive
                .for_each(|_| future::empty())
                .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

            self.httpd.remote.spawn(move |_| done);
        } else {
            let range = range.unwrap_or_else(|| 0..fd.len);

            let log = self.log.clone();
            let (send, body) = Body::pair();
            res.set_body(body);

            debug!(self.log, "process"; "method" => "readchunk");

            let done = fd.read(range)?
                .forward(send)
                .map(drop)
                .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

            self.httpd.remote.spawn(move |_| done);
        }

        Ok(res)
    }
}
<commit_msg>[Fixed] sendfile for_each<commit_after>mod sortdir;
mod entity;

use std::io;
use std::ops::Range;
use std::path::PathBuf;
use std::rc::Rc;
use std::fs::{ Metadata, ReadDir };
use futures::{ future, stream, Stream, Future };
use hyper::{ header, Request, Response, Head, Body, StatusCode };
use mime_guess::guess_mime_type;
use maud::Render;
use slog::Logger;
use ::utils::{ path_canonicalize, decode_path };
use ::{ error, file, Httpd };
use self::sortdir::{ SortDir, up };
use self::entity::{ Entity, EntifyResult };

pub struct Process<'a> {
    httpd: &'a Httpd,
    log: &'a Logger,
    req: &'a Request,
    depth: usize,
    path: Rc<PathBuf>
}

impl<'a> Process<'a> {
    #[inline]
    pub fn new(httpd: &'a Httpd, log: &'a Logger, req: &'a Request) -> Process<'a> {
        let path_buf = decode_path(req.path());
        let (depth, path) = path_canonicalize(&httpd.root, path_buf);
        let path = Rc::new(path);
        Process { httpd, log, req, depth, path }
    }

    #[inline]
    pub fn process(&self) -> io::Result<Response> {
        let metadata = self.path.metadata()?;

        if let Ok(dir) = self.path.read_dir() {
            self.process_dir(dir)
        } else {
            self.process_file(&metadata)
        }
    }
}

impl<'a> Process<'a> {
    fn process_dir(&self, dir: ReadDir) -> io::Result<Response> {
        const HTML_HEADER: &str = "

";
        const HTML_FOOTER: &str = "
</table";

        let mut res = Response::new();

        if self.req.method() == &Head {
            res.set_body(Body::empty());
        } else {
            let log = self.log.clone();
            let is_root = self.depth == 0;
            let root = self.httpd.root.clone();
            let (send, body) = Body::pair();
            res.set_body(body);

            debug!(self.log, "process"; "method" => "senddir");

            let done = stream::once(Ok(chunk!(HTML_HEADER)))
                .chain(stream::once(Ok(chunk!(into up(is_root)))))
                .chain(stream::iter(SortDir::new(root, dir))
                    .map(|p| p.and_then(|m| chunk!(into m.render())).map_err(Into::into))
                )
                .chain(stream::once(Ok(chunk!(HTML_FOOTER))))
                .map_err(error::Error::from)
                .forward(send)
                .map(drop)
                .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

            self.httpd.remote.spawn(move |_| done);
        }

        // TODO https://github.com/hyperium/mime/issues/52
        let mime = "text/html; charset=utf-8".parse().unwrap();
        Ok(res.with_header(header::ContentType(mime)))
    }

    fn process_file(&self, metadata: &Metadata) -> io::Result<Response> {
        let entity = Entity::new(self.path.clone(), metadata, self.log);

        match entity.check(self.req.headers()) {
            EntifyResult::Err(resp) => Ok(resp.with_headers(entity.headers(false))),
            EntifyResult::None => {
                let handle = self.httpd.remote.handle()
                    .ok_or_else(|| err!(Other, "Remote get handle fail"))?;
                let fd = entity.open(handle)?;
                self.send(&fd, None)
                    .map(|res| res
                        .with_headers(entity.headers(false))
                        .with_header(header::ContentLength(fd.len))
                    )
            },
            EntifyResult::One(range) => {
                debug!(self.log, "process"; "range" => format_args!("{:?}", range));
                let handle = self.httpd.remote.handle()
                    .ok_or_else(|| err!(Other, "Remote get handle fail"))?;
                let fd = entity.open(handle)?;
                self.send(&fd, Some(range.clone()))
                    .map(|res| res
                         .with_status(StatusCode::PartialContent)
                         .with_headers(entity.headers(false))
                         .with_header(header::ContentLength(range.end - range.start))
                         .with_header(header::ContentRange(header::ContentRangeSpec::Bytes {
                            range: Some((range.start, range.end - 1)), instance_length: Some(fd.len)
                        }))
                    )
            },
            EntifyResult::Vec(ranges) => {
                const BOUNDARY_LINE: &str = concat!("--", boundary!(), "\r\n");

                debug!(self.log, "process"; "ranges" => format_args!("{:?}", ranges));

                let handle = self.httpd.remote.handle()
                    .ok_or_else(|| err!(Other, "Remote get handle fail"))?;
                let mut res = Response::new();

                if self.req.method() == &Head {
                    return Ok(res
                        .with_status(StatusCode::PartialContent)
                        .with_headers(entity.headers(true))
                        .with_body(Body::empty())
                    );
                }

                let log = self.log.clone();
                let fd = entity.open(handle)?;
                let (send, body) = Body::pair();
                res.set_body(body);

                let content_type = header::ContentType(guess_mime_type(&*self.path));

                let done = stream::iter::<_, _, error::Error>(ranges.into_iter().map(Ok))
                    .and_then(move |range| {
                        let len = range.end - range.start;
                        let mut headers = header::Headers::new();
                        headers.set(content_type.clone());
                        headers.set(header::ContentRange(header::ContentRangeSpec::Bytes {
                            range: Some((range.start, range.end - 1)), instance_length: Some(len)
                        }));

                        fd.read(range)
                            .map(move |fut| {
                                stream::once(Ok(chunk!(BOUNDARY_LINE)))
                                    .chain(stream::once(Ok(chunk!(format!("{}\r\n", headers)))))
                                    .chain(fut)
                                    .chain(stream::once(Ok(chunk!("\r\n"))))
                            })
                            .map_err(Into::into)
                    })
                    .flatten()
                    .forward(send)
                    .map(drop)
                    .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

                self.httpd.remote.spawn(move |_| done);

                Ok(res
                    .with_status(StatusCode::PartialContent)
                    .with_headers(entity.headers(true))
                )
            }
        }
    }

    fn send(&self, fd: &file::File, range: Option<Range<u64>>) -> io::Result<Response> {
        use ::file::CHUNK_BUFF_LENGTH;
        let mut res = Response::new();

        if self.req.method() == &Head {
            res.set_body(Body::empty());
        } else if let (&Some(ref socket), true) = (&self.httpd.socket, CHUNK_BUFF_LENGTH >= fd.len as _) {
            let range = range.unwrap_or_else(|| 0..fd.len);
            let log = self.log.clone();
            res.set_body(Body::empty());

            debug!(self.log, "process"; "method" => "sendfile");

            let done = fd.sendfile(range, socket.clone())?
                .for_each(|_| future::ok(()))
                .map(drop)
                .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

            self.httpd.remote.spawn(move |_| done);
        } else {
            let range = range.unwrap_or_else(|| 0..fd.len);

            let log = self.log.clone();
            let (send, body) = Body::pair();
            res.set_body(body);

            debug!(self.log, "process"; "method" => "readchunk");

            let done = fd.read(range)?
                .forward(send)
                .map(drop)
                .map_err(move |err| debug!(log, "send"; "err" => format_args!("{}", err)));

            self.httpd.remote.spawn(move |_| done);
        }

        Ok(res)
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::{cmp, result, io, fmt};
use std::error;
use std::boxed::Box;

use protobuf::ProtobufError;

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    NotFound,
    Store(StorageError),
    Other(Box<error::Error + Send + Sync>),
}

#[derive(Debug, PartialEq)]
pub enum StorageError {
    Compacted,
    Unavailable,
    SnapshotOutOfDate,
}

impl StorageError {
    pub fn string(&self) -> &str {
        match self {
            &StorageError::Compacted => "log compacted",
            &StorageError::Unavailable => "log unavailable",
            &StorageError::SnapshotOutOfDate => "snapshot out of date",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::Io(ref e) => fmt::Display::fmt(e, f),
            &Error::Store(ref e) => fmt::Display::fmt(e, f),
            &Error::Other(ref e) => fmt::Display::fmt(e, f),
            &Error::NotFound => fmt::Display::fmt("not found", f),
        }
    }
}

impl fmt::Display for StorageError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.string(), f)
    }
}

impl cmp::PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (&Error::NotFound, &Error::NotFound) => true,
            (&Error::Store(ref e1), &Error::Store(ref e2)) => e1 == e2,
            (&Error::Io(ref e1), &Error::Io(ref e2)) => e1.kind() == e2.kind(),
            // should not compare directly
            (&Error::Other(ref e1), &Error::Other(ref e2)) => {
                panic!("Shoud not compare boxed error directly {}， {}", e1, e2)
            }
            _ => false,
        }
    }
}

impl error::Error for StorageError {
    fn description(&self) -> &str {
        self.string()
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            // not sure that cause should be included in message
            &Error::Io(ref e) => e.description(),
            &Error::Store(ref e) => e.description(),
            &Error::Other(ref e) => e.description(),
            &Error::NotFound => "not found",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::Io(ref e) => Some(e),
            &Error::Other(ref e) => e.cause(),
            _ => None,
        }
    }
}

// other can convert e to Error::Other.
pub fn other<E>(e: E) -> Error
    where E: Into<Box<error::Error + Send + Sync>>
{
    Error::Other(e.into())
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<ProtobufError> for Error {
    fn from(err: ProtobufError) -> Error {
        other(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[cfg(test)]
mod tests {
    use std::error;
    use protobuf::ProtobufError;

    use super::*;

    #[test]
    fn test_error() {
        let e = ProtobufError::WireError("a error".to_string());
        let err: Error = other(e);
        assert!(error::Error::cause(&err).is_none());

        let err1 = other("hello world");
        assert!(error::Error::cause(&err1).is_none());
    }

    #[test]
    fn test_equal() {
        assert_eq!(Error::NotFound, Error::NotFound);
        assert!(Error::NotFound != Error::Store(StorageError::Compacted));
        assert_eq!(Error::Store(StorageError::Compacted),
                   Error::Store(StorageError::Compacted));
    }
}
<commit_msg>raft: use quick_error<commit_after>#![allow(dead_code)]
use std::{cmp, result, io};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Io(err: io::Error) {
            from()
            cause(err)
            description(err.description())
        }
        Store(err: StorageError) {
            from()
            cause(err)
            description(err.description())
        }
        StepLocalMsg {
            description("raft: cannot step raft local message")
        }
        StepPeerNotFound {
            description("raft: cannot step as peer not found")
        }
    }
}

quick_error! {
    #[derive(Debug, PartialEq)]
    pub enum StorageError {
        Compacted {
            description("log compacted")
        }
        Unavailable {
            description("log unavailable")
        }
        SnapshotOutOfDate {
            description("snapshot out of date")
        }
    }
}

impl cmp::PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        match (self, other) {
            (&Error::StepPeerNotFound, &Error::StepPeerNotFound) => true,
            (&Error::Store(ref e1), &Error::Store(ref e2)) => e1 == e2,
            (&Error::Io(ref e1), &Error::Io(ref e2)) => e1.kind() == e2.kind(),
            (&Error::StepLocalMsg, &Error::StepLocalMsg) => true,
            _ => false,
        }
    }
}

pub type Result<T> = result::Result<T, Error>;

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

    #[test]
    fn test_equal() {
        assert_eq!(Error::StepPeerNotFound, Error::StepPeerNotFound);
        assert!(Error::StepPeerNotFound != Error::Store(StorageError::Compacted));
        assert_eq!(Error::Store(StorageError::Compacted),
                   Error::Store(StorageError::Compacted));
        assert_eq!(Error::StepLocalMsg, Error::StepLocalMsg);
        assert_eq!(Error::from(io::Error::new(io::ErrorKind::Other, "oh no!")),
                   Error::from(io::Error::new(io::ErrorKind::Other, "oh yes!")));
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use self::rand::{thread_rng, Rng};

//pub fn rand_choice<S: Copy + for<'r> Add<&'r S, Output=&S>, T: Iterator<Item=S>>(it: T) {
//pub fn rand_choice<T: Add>(weights: Vec<T>) {

/**
* Chooses n samples of weights. The greater the weight the more likely it gets chosen.
* This function returns only the indices of the weights.
*
* @invariant sum of weights must not overflow.
*
* @param weights Weights that get chosen by their weight/probability. One weight can be greater 1.
* @param n Number of randomly chosen indices by weight.
* @return Indices of the weights. Randomly chosen by their weight.
*/
pub fn random_choice(weights: Vec<f64>, n: usize) -> Vec<usize>{
    // Save accumulated sum of the weights in order to calculate the intervals
    // between accumulated weights
    let mut accumulated_sum = Vec::with_capacity(weights.len());

    accumulated_sum.push(weights[0]);

    for i in 1 .. weights.len() {
        let acc_sum = accumulated_sum[i - 1] + weights[i];
        accumulated_sum.push(acc_sum);
    }

    let sum: f64 = accumulated_sum[weights.len() - 1];
    let spoke_gap: f64 = sum / n as f64;

    // next_f64() ∈ [0.0, 1.0)
    let spin = thread_rng().next_f64() * spoke_gap;
    let mut choices: Vec<usize> = Vec::with_capacity(n);
    let mut i: usize = 0;
    let mut current_spoke: f64 = spin;

    for _ in 0 .. n {
        current_spoke += spoke_gap;
        current_spoke %= sum;

        // accumulated_sum[i] is the interval end
        // (accumulated_sum[i] - weight[i]) is the interval begin
        // Following condition must be true: interval begin <= current_spoke < interval end
        // If the condition is not true, then increment i in order to get the next greater intervals.
        while accumulated_sum[i] <= current_spoke || (accumulated_sum[i] - weights[i]) > current_spoke {
            i += 1;
            i %= weights.len();
        }
        choices.push(i);
    }

    choices
}

#[cfg(test)]
mod tests {
    #[test]
    fn basics() {
        let test_vec = vec![1.0, 2.0, 3.0, 10.0];
        //let sum:f64 = test_vec.iter().fold(0.0, |acc, &i| acc + i);

        //assert_eq!(6.0, sum);

        let indices = super::random_choice(test_vec, 10 as usize);

        for index in indices {
            print!("{}, ", index);
        }
    }
}<commit_msg>removed obsolete code<commit_after>extern crate rand;

use self::rand::{thread_rng, Rng};

/**
* Chooses n samples of weights. The greater the weight the more likely it gets chosen.
* This function returns only the indices of the weights.
*
* @invariant sum of weights must not overflow.
*
* @param weights Weights that get chosen by their weight/probability. One weight can be greater 1.
* @param n Number of randomly chosen indices by weight.
* @return Indices of the weights. Randomly chosen by their weight.
*/
pub fn random_choice(weights: Vec<f64>, n: usize) -> Vec<usize>{
    // Save accumulated sum of the weights in order to calculate the intervals
    // between accumulated weights
    let mut accumulated_sum = Vec::with_capacity(weights.len());

    accumulated_sum.push(weights[0]);

    for i in 1 .. weights.len() {
        let acc_sum = accumulated_sum[i - 1] + weights[i];
        accumulated_sum.push(acc_sum);
    }

    let sum: f64 = accumulated_sum[weights.len() - 1];
    let spoke_gap: f64 = sum / n as f64;

    // next_f64() ∈ [0.0, 1.0)
    let spin = thread_rng().next_f64() * spoke_gap;
    let mut choices: Vec<usize> = Vec::with_capacity(n);
    let mut i: usize = 0;
    let mut current_spoke: f64 = spin;

    for _ in 0 .. n {
        current_spoke += spoke_gap;
        current_spoke %= sum;

        // accumulated_sum[i] is the interval end
        // (accumulated_sum[i] - weight[i]) is the interval begin
        // Following condition must be true: interval begin <= current_spoke < interval end
        // If the condition is not true, then increment i in order to get the next greater intervals.
        while accumulated_sum[i] <= current_spoke || (accumulated_sum[i] - weights[i]) > current_spoke {
            i += 1;
            i %= weights.len();
        }
        choices.push(i);
    }

    choices
}

#[cfg(test)]
mod tests {
    #[test]
    fn basics() {
        let test_vec = vec![1.0, 2.0, 3.0, 10.0];
        //let sum:f64 = test_vec.iter().fold(0.0, |acc, &i| acc + i);

        //assert_eq!(6.0, sum);

        let indices = super::random_choice(test_vec, 10 as usize);

        for index in indices {
            print!("{}, ", index);
        }
    }
}<|endoftext|>


<commit_before>// Predefined unit constants
const U_UNITS: &'static str = "units";

#[derive(PartialEq, Debug, Clone)]
pub struct RichNumber {
    value: f64,
    unit: String,
}

impl RichNumber {
    pub fn zero() -> RichNumber {
        RichNumber::from(0f64)
    }
}

impl From<f64> for RichNumber {
    fn from(number: f64) -> RichNumber {
        RichNumber {
            value: number,
            unit: String::from(U_UNITS),
        }
    }
}

<commit_msg>Starting to implement rich number<commit_after>use std::ops::{Add, Sub, Mul, Div, Rem};

// Predefined unit constants
const U_UNITS: usize = 1;

#[derive(Debug, Clone, Copy)]
pub struct RichNumber {
    value: f64,
    unit: usize,
}

impl RichNumber {
    pub fn new(value: f64, unit: usize) -> RichNumber {
        RichNumber {
            value: value as f64,
            unit: unit,
        }
    }

    pub fn zero() -> RichNumber {
        RichNumber::from(0f64)
    }

    /// Attempts to coerce two values into a common unit
    /// Returns (converted self, converted other, common unit)
    fn coerce(&self, other: &RichNumber) -> (f64, f64, usize) {
        //TODO: Convert between units
        (self.value, other.value, U_UNITS)
    }

    /// Applies an operator to two values given the values and their common unit
    fn apply_operator<F, R>(self, other: RichNumber, operator: F) -> R
        where F: FnOnce(f64, f64, usize) -> R {

        let (value, other_value, unit) = self.coerce(&other);
        operator(value, other_value, unit)
    }

    /// Converts self and other into a common or compatible unit and then performs the given operation
    /// operator is given the two values in order and the common unit
    /// Returns a RichNumber with the new value and the common unit
    fn apply_numeric_operator<F>(self, other: RichNumber, operator: F) -> RichNumber
        where F: FnOnce(f64, f64, usize) -> f64 {

        let (value, other_value, unit) = self.coerce(&other);
        RichNumber::new(operator(value, other_value, unit), unit)
    }
}

impl From<i64> for RichNumber {
    fn from(number: i64) -> RichNumber {
        RichNumber::new(number as f64, U_UNITS)
    }
}

impl From<f64> for RichNumber {
    fn from(number: f64) -> RichNumber {
        RichNumber::new(number, U_UNITS)
    }
}

impl PartialEq for RichNumber {
    fn eq(&self, other: &RichNumber) -> bool {
        let (value, other_value, _) = self.coerce(other);

        (value - other_value).abs() < 1e-10
    }
}

impl Add for RichNumber {
    type Output = RichNumber;

    fn add(self, other: RichNumber) -> Self::Output {
        self.apply_numeric_operator(other, |a, b, _| a + b)
    }
}

impl Sub for RichNumber {
    type Output = RichNumber;

    fn sub(self, other: RichNumber) -> Self::Output {
        self.apply_numeric_operator(other, |a, b, _| a - b)
    }
}

impl Mul for RichNumber {
    type Output = RichNumber;

    fn mul(self, other: RichNumber) -> Self::Output {
        self.apply_numeric_operator(other, |a, b, _| a * b)
    }
}

impl Div for RichNumber {
    type Output = RichNumber;

    fn div(self, other: RichNumber) -> Self::Output {
        self.apply_numeric_operator(other, |a, b, _| a / b)
    }
}

impl Rem for RichNumber {
    type Output = RichNumber;

    fn rem(self, other: RichNumber) -> Self::Output {
        self.apply_numeric_operator(other, |a, b, _| a % b)
    }
}

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

    #[test]
    fn equality() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(2);
        let c = RichNumber::from(3.6);

        assert_eq!(a, b);
        assert!(a != c);
    }

    #[test]
    fn basic_operations() {
        let a = RichNumber::from(2);
        let b = RichNumber::from(3.6);

        assert_eq!(a + b, RichNumber::from(5.6f64));
        assert_eq!(b + a, RichNumber::from(5.6f64));

        assert_eq!(a - b, RichNumber::from(-1.6f64));
        assert_eq!(b - a, RichNumber::from(1.6f64));

        assert_eq!(a * b, RichNumber::from(7.2f64));
        assert_eq!(b * a, RichNumber::from(7.2f64));

        assert_eq!(a / b, RichNumber::from(0.55555555555f64));
        assert_eq!(b / a, RichNumber::from(1.8f64));

        assert_eq!(a % b, RichNumber::from(2f64));
        assert_eq!(b % a, RichNumber::from(1.6f64));
    }
}

<|endoftext|>