<commit_before>use super::Incoming;
use super::TcpStream;

use std::fmt;
use std::io;
use std::net::{self, SocketAddr};

use futures::{Async, Poll};
use mio;
use tokio_reactor::{Handle, PollEvented};

/// An I/O object representing a TCP socket listening for incoming connections.
///
/// This object can be converted into a stream of incoming connections for
/// various forms of processing.
///
/// # Examples
///
/// ```no_run
/// extern crate tokio;
/// extern crate futures;
///
/// use futures::stream::Stream;
/// use std::net::SocketAddr;
/// use tokio::net::{TcpListener, TcpStream};
///
/// fn process_socket(socket: TcpStream) {
///     // ...
/// }
///
/// fn main() -> Result<(), Box<std::error::Error>> {
///     let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
///     let listener = TcpListener::bind(&addr)?;
///
///     // accept connections and process them
///     tokio::run(listener.incoming()
///         .map_err(|e| eprintln!("failed to accept socket; error = {:?}", e))
///         .for_each(|socket| {
///             process_socket(socket);
///             Ok(())
///         })
///     );
///     Ok(())
/// }
/// ```
pub struct TcpListener {
    io: PollEvented<mio::net::TcpListener>,
}

impl TcpListener {
    /// Create a new TCP listener associated with this event loop.
    ///
    /// The TCP listener will bind to the provided `addr` address, if available.
    /// If the result is `Ok`, the socket has successfully bound.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use std::net::SocketAddr;
    /// use tokio::net::TcpListener;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
        let l = mio::net::TcpListener::bind(addr)?;
        Ok(TcpListener::new(l))
    }

    #[deprecated(since = "0.1.2", note = "use poll_accept instead")]
    #[doc(hidden)]
    pub fn accept(&mut self) -> io::Result<(TcpStream, SocketAddr)> {
        match self.poll_accept()? {
            Async::Ready(ret) => Ok(ret),
            Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
        }
    }

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// Note that typically for simple usage it's easier to treat incoming
    /// connections as a `Stream` of `TcpStream`s with the `incoming` method
    /// below.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use std::net::SocketAddr;
    /// use tokio::net::TcpListener;
    /// use futures::Async;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let mut listener = TcpListener::bind(&addr)?;
    /// match listener.poll_accept() {
    ///     Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
    ///     Ok(Async::NotReady) => println!("listener not ready to accept!"),
    ///     Err(e) => eprintln!("got an error: {}", e),
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn poll_accept(&mut self) -> Poll<(TcpStream, SocketAddr), io::Error> {
        let (io, addr) = try_ready!(self.poll_accept_std());

        let io = mio::net::TcpStream::from_stream(io)?;
        let io = TcpStream::new(io);

        Ok((io, addr).into())
    }

    #[deprecated(since = "0.1.2", note = "use poll_accept_std instead")]
    #[doc(hidden)]
    pub fn accept_std(&mut self) -> io::Result<(net::TcpStream, SocketAddr)> {
        match self.poll_accept_std()? {
            Async::Ready(ret) => Ok(ret),
            Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
        }
    }

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// This function is the same as `accept` above except that it returns a
    /// `std::net::TcpStream` instead of a `tokio::net::TcpStream`. This in turn
    /// can then allow for the TCP stream to be associated with a different
    /// reactor than the one this `TcpListener` is associated with.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use std::net::SocketAddr;
    /// use tokio::net::TcpListener;
    /// use futures::Async;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let mut listener = TcpListener::bind(&addr)?;
    /// match listener.poll_accept_std() {
    ///     Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
    ///     Ok(Async::NotReady) => println!("listener not ready to accept!"),
    ///     Err(e) => eprintln!("got an error: {}", e),
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn poll_accept_std(&mut self) -> Poll<(net::TcpStream, SocketAddr), io::Error> {
        try_ready!(self.io.poll_read_ready(mio::Ready::readable()));

        match self.io.get_ref().accept_std() {
            Ok(pair) => Ok(pair.into()),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                self.io.clear_read_ready(mio::Ready::readable())?;
                Ok(Async::NotReady)
            }
            Err(e) => Err(e),
        }
    }

    /// Create a new TCP listener from the standard library's TCP listener.
    ///
    /// This method can be used when the `Handle::tcp_listen` method isn't
    /// sufficient because perhaps some more configuration is needed in terms of
    /// before the calls to `bind` and `listen`.
    ///
    /// This API is typically paired with the `net2` crate and the `TcpBuilder`
    /// type to build up and customize a listener before it's shipped off to the
    /// backing event loop. This allows configuration of options like
    /// `SO_REUSEPORT`, binding to multiple addresses, etc.
    ///
    /// The `addr` argument here is one of the addresses that `listener` is
    /// bound to and the listener will only be guaranteed to accept connections
    /// of the same address type currently.
    ///
    /// Finally, the `handle` argument is the event loop that this listener will
    /// be bound to.
    /// Use [`Handle::default()`] to lazily bind to an event loop, just like `bind` does.
    ///
    /// The platform specific behavior of this function looks like:
    ///
    /// * On Unix, the socket is placed into nonblocking mode and connections
    ///   can be accepted as normal
    ///
    /// * On Windows, the address is stored internally and all future accepts
    ///   will only be for the same IP version as `addr` specified. That is, if
    ///   `addr` is an IPv4 address then all sockets accepted will be IPv4 as
    ///   well (same for IPv6).
    ///
    /// [`Handle::default()`]: ../reactor/struct.Handle.html
    /// # Examples
    ///
    /// ```no_run
    /// # extern crate tokio;
    /// # extern crate tokio_reactor;
    /// use tokio::net::TcpListener;
    /// use std::net::TcpListener as StdTcpListener;
    /// use tokio::reactor::Handle;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let std_listener = StdTcpListener::bind("127.0.0.1:8080")?;
    /// let listener = TcpListener::from_std(std_listener, &Handle::default())?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn from_std(listener: net::TcpListener, handle: &Handle) -> io::Result<TcpListener> {
        let io = mio::net::TcpListener::from_std(listener)?;
        let io = PollEvented::new_with_handle(io, handle)?;
        Ok(TcpListener { io })
    }

    fn new(listener: mio::net::TcpListener) -> TcpListener {
        let io = PollEvented::new(listener);
        TcpListener { io }
    }

    /// Returns the local address that this listener is bound to.
    ///
    /// This can be useful, for example, when binding to port 0 to figure out
    /// which port was actually bound.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use tokio::net::TcpListener;
    /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// assert_eq!(listener.local_addr()?,
    ///            SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
    /// # Ok(())
    /// # }
    /// ```
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().local_addr()
    }

    /// Consumes this listener, returning a stream of the sockets this listener
    /// accepts.
    ///
    /// This method returns an implementation of the `Stream` trait which
    /// resolves to the sockets the are accepted on this listener.
    ///
    /// # Errors
    ///
    /// Note that accepting a connection can lead to various errors and not all of them are
    /// necessarily fatal ‒ for example having too many open file descriptors or the other side
    /// closing the connection while it waits in an accept queue. These would terminate the stream
    /// if not handled in any way.
    ///
    /// If aiming for production, decision what to do about them must be made. The
    /// [`tk-listen`](https://crates.io/crates/tk-listen) crate might be of some help.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use tokio::net::TcpListener;
    /// use futures::stream::Stream;
    /// use std::net::SocketAddr;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    ///
    /// listener.incoming()
    ///     .map_err(|e| eprintln!("failed to accept stream; error = {:?}", e))
    ///     .for_each(|_socket| {
    ///         println!("new socket!");
    ///         Ok(())
    ///     });
    /// # Ok(())
    /// # }
    /// ```
    pub fn incoming(self) -> Incoming {
        Incoming::new(self)
    }

    /// Gets the value of the `IP_TTL` option for this socket.
    ///
    /// For more information about this option, see [`set_ttl`].
    ///
    /// [`set_ttl`]: #method.set_ttl
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use tokio::net::TcpListener;
    /// use std::net::SocketAddr;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// listener.set_ttl(100).expect("could not set TTL");
    /// assert_eq!(listener.ttl()?, 100);
    /// # Ok(())
    /// # }
    /// ```
    pub fn ttl(&self) -> io::Result<u32> {
        self.io.get_ref().ttl()
    }

    /// Sets the value for the `IP_TTL` option on this socket.
    ///
    /// This value sets the time-to-live field that is used in every packet sent
    /// from this socket.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use tokio::net::TcpListener;
    /// use std::net::SocketAddr;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// listener.set_ttl(100).expect("could not set TTL");
    /// # Ok(())
    /// # }
    /// ```
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.get_ref().set_ttl(ttl)
    }
}

impl fmt::Debug for TcpListener {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.io.get_ref().fmt(f)
    }
}

#[cfg(unix)]
mod sys {
    use super::TcpListener;
    use std::os::unix::prelude::*;

    impl AsRawFd for TcpListener {
        fn as_raw_fd(&self) -> RawFd {
            self.io.get_ref().as_raw_fd()
        }
    }
}

#[cfg(windows)]
mod sys {
    // TODO: let's land these upstream with mio and then we can add them here.
    //
    // use std::os::windows::prelude::*;
    // use super::{TcpListener;
    //
    // impl AsRawHandle for TcpListener {
    //     fn as_raw_handle(&self) -> RawHandle {
    //         self.listener.io().as_raw_handle()
    //     }
    // }
}
<commit_msg>tcp: fix some tests that spuriously fail (#1060)<commit_after>use super::Incoming;
use super::TcpStream;

use std::fmt;
use std::io;
use std::net::{self, SocketAddr};

use futures::{Async, Poll};
use mio;
use tokio_reactor::{Handle, PollEvented};

/// An I/O object representing a TCP socket listening for incoming connections.
///
/// This object can be converted into a stream of incoming connections for
/// various forms of processing.
///
/// # Examples
///
/// ```no_run
/// extern crate tokio;
/// extern crate futures;
///
/// use futures::stream::Stream;
/// use std::net::SocketAddr;
/// use tokio::net::{TcpListener, TcpStream};
///
/// fn process_socket(socket: TcpStream) {
///     // ...
/// }
///
/// fn main() -> Result<(), Box<std::error::Error>> {
///     let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
///     let listener = TcpListener::bind(&addr)?;
///
///     // accept connections and process them
///     tokio::run(listener.incoming()
///         .map_err(|e| eprintln!("failed to accept socket; error = {:?}", e))
///         .for_each(|socket| {
///             process_socket(socket);
///             Ok(())
///         })
///     );
///     Ok(())
/// }
/// ```
pub struct TcpListener {
    io: PollEvented<mio::net::TcpListener>,
}

impl TcpListener {
    /// Create a new TCP listener associated with this event loop.
    ///
    /// The TCP listener will bind to the provided `addr` address, if available.
    /// If the result is `Ok`, the socket has successfully bound.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use std::net::SocketAddr;
    /// use tokio::net::TcpListener;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
        let l = mio::net::TcpListener::bind(addr)?;
        Ok(TcpListener::new(l))
    }

    #[deprecated(since = "0.1.2", note = "use poll_accept instead")]
    #[doc(hidden)]
    pub fn accept(&mut self) -> io::Result<(TcpStream, SocketAddr)> {
        match self.poll_accept()? {
            Async::Ready(ret) => Ok(ret),
            Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
        }
    }

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// Note that typically for simple usage it's easier to treat incoming
    /// connections as a `Stream` of `TcpStream`s with the `incoming` method
    /// below.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use std::net::SocketAddr;
    /// use tokio::net::TcpListener;
    /// use futures::Async;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
    /// let mut listener = TcpListener::bind(&addr)?;
    /// match listener.poll_accept() {
    ///     Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
    ///     Ok(Async::NotReady) => println!("listener not ready to accept!"),
    ///     Err(e) => eprintln!("got an error: {}", e),
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn poll_accept(&mut self) -> Poll<(TcpStream, SocketAddr), io::Error> {
        let (io, addr) = try_ready!(self.poll_accept_std());

        let io = mio::net::TcpStream::from_stream(io)?;
        let io = TcpStream::new(io);

        Ok((io, addr).into())
    }

    #[deprecated(since = "0.1.2", note = "use poll_accept_std instead")]
    #[doc(hidden)]
    pub fn accept_std(&mut self) -> io::Result<(net::TcpStream, SocketAddr)> {
        match self.poll_accept_std()? {
            Async::Ready(ret) => Ok(ret),
            Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
        }
    }

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// This function is the same as `accept` above except that it returns a
    /// `std::net::TcpStream` instead of a `tokio::net::TcpStream`. This in turn
    /// can then allow for the TCP stream to be associated with a different
    /// reactor than the one this `TcpListener` is associated with.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use std::net::SocketAddr;
    /// use tokio::net::TcpListener;
    /// use futures::Async;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
    /// let mut listener = TcpListener::bind(&addr)?;
    /// match listener.poll_accept_std() {
    ///     Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
    ///     Ok(Async::NotReady) => println!("listener not ready to accept!"),
    ///     Err(e) => eprintln!("got an error: {}", e),
    /// }
    /// # Ok(())
    /// # }
    /// ```
    pub fn poll_accept_std(&mut self) -> Poll<(net::TcpStream, SocketAddr), io::Error> {
        try_ready!(self.io.poll_read_ready(mio::Ready::readable()));

        match self.io.get_ref().accept_std() {
            Ok(pair) => Ok(pair.into()),
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                self.io.clear_read_ready(mio::Ready::readable())?;
                Ok(Async::NotReady)
            }
            Err(e) => Err(e),
        }
    }

    /// Create a new TCP listener from the standard library's TCP listener.
    ///
    /// This method can be used when the `Handle::tcp_listen` method isn't
    /// sufficient because perhaps some more configuration is needed in terms of
    /// before the calls to `bind` and `listen`.
    ///
    /// This API is typically paired with the `net2` crate and the `TcpBuilder`
    /// type to build up and customize a listener before it's shipped off to the
    /// backing event loop. This allows configuration of options like
    /// `SO_REUSEPORT`, binding to multiple addresses, etc.
    ///
    /// The `addr` argument here is one of the addresses that `listener` is
    /// bound to and the listener will only be guaranteed to accept connections
    /// of the same address type currently.
    ///
    /// Finally, the `handle` argument is the event loop that this listener will
    /// be bound to.
    /// Use [`Handle::default()`] to lazily bind to an event loop, just like `bind` does.
    ///
    /// The platform specific behavior of this function looks like:
    ///
    /// * On Unix, the socket is placed into nonblocking mode and connections
    ///   can be accepted as normal
    ///
    /// * On Windows, the address is stored internally and all future accepts
    ///   will only be for the same IP version as `addr` specified. That is, if
    ///   `addr` is an IPv4 address then all sockets accepted will be IPv4 as
    ///   well (same for IPv6).
    ///
    /// [`Handle::default()`]: ../reactor/struct.Handle.html
    /// # Examples
    ///
    /// ```no_run
    /// # extern crate tokio;
    /// # extern crate tokio_reactor;
    /// use tokio::net::TcpListener;
    /// use std::net::TcpListener as StdTcpListener;
    /// use tokio::reactor::Handle;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let std_listener = StdTcpListener::bind("127.0.0.1:0")?;
    /// let listener = TcpListener::from_std(std_listener, &Handle::default())?;
    /// # Ok(())
    /// # }
    /// ```
    pub fn from_std(listener: net::TcpListener, handle: &Handle) -> io::Result<TcpListener> {
        let io = mio::net::TcpListener::from_std(listener)?;
        let io = PollEvented::new_with_handle(io, handle)?;
        Ok(TcpListener { io })
    }

    fn new(listener: mio::net::TcpListener) -> TcpListener {
        let io = PollEvented::new(listener);
        TcpListener { io }
    }

    /// Returns the local address that this listener is bound to.
    ///
    /// This can be useful, for example, when binding to port 0 to figure out
    /// which port was actually bound.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use tokio::net::TcpListener;
    /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// assert_eq!(listener.local_addr()?,
    ///            SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
    /// # Ok(())
    /// # }
    /// ```
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().local_addr()
    }

    /// Consumes this listener, returning a stream of the sockets this listener
    /// accepts.
    ///
    /// This method returns an implementation of the `Stream` trait which
    /// resolves to the sockets the are accepted on this listener.
    ///
    /// # Errors
    ///
    /// Note that accepting a connection can lead to various errors and not all of them are
    /// necessarily fatal ‒ for example having too many open file descriptors or the other side
    /// closing the connection while it waits in an accept queue. These would terminate the stream
    /// if not handled in any way.
    ///
    /// If aiming for production, decision what to do about them must be made. The
    /// [`tk-listen`](https://crates.io/crates/tk-listen) crate might be of some help.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// # extern crate futures;
    /// use tokio::net::TcpListener;
    /// use futures::stream::Stream;
    /// use std::net::SocketAddr;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    ///
    /// listener.incoming()
    ///     .map_err(|e| eprintln!("failed to accept stream; error = {:?}", e))
    ///     .for_each(|_socket| {
    ///         println!("new socket!");
    ///         Ok(())
    ///     });
    /// # Ok(())
    /// # }
    /// ```
    pub fn incoming(self) -> Incoming {
        Incoming::new(self)
    }

    /// Gets the value of the `IP_TTL` option for this socket.
    ///
    /// For more information about this option, see [`set_ttl`].
    ///
    /// [`set_ttl`]: #method.set_ttl
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use tokio::net::TcpListener;
    /// use std::net::SocketAddr;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// listener.set_ttl(100).expect("could not set TTL");
    /// assert_eq!(listener.ttl()?, 100);
    /// # Ok(())
    /// # }
    /// ```
    pub fn ttl(&self) -> io::Result<u32> {
        self.io.get_ref().ttl()
    }

    /// Sets the value for the `IP_TTL` option on this socket.
    ///
    /// This value sets the time-to-live field that is used in every packet sent
    /// from this socket.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate tokio;
    /// use tokio::net::TcpListener;
    /// use std::net::SocketAddr;
    ///
    /// # fn main() -> Result<(), Box<std::error::Error>> {
    /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
    /// let listener = TcpListener::bind(&addr)?;
    /// listener.set_ttl(100).expect("could not set TTL");
    /// # Ok(())
    /// # }
    /// ```
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.get_ref().set_ttl(ttl)
    }
}

impl fmt::Debug for TcpListener {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.io.get_ref().fmt(f)
    }
}

#[cfg(unix)]
mod sys {
    use super::TcpListener;
    use std::os::unix::prelude::*;

    impl AsRawFd for TcpListener {
        fn as_raw_fd(&self) -> RawFd {
            self.io.get_ref().as_raw_fd()
        }
    }
}

#[cfg(windows)]
mod sys {
    // TODO: let's land these upstream with mio and then we can add them here.
    //
    // use std::os::windows::prelude::*;
    // use super::{TcpListener;
    //
    // impl AsRawHandle for TcpListener {
    //     fn as_raw_handle(&self) -> RawHandle {
    //         self.listener.io().as_raw_handle()
    //     }
    // }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate reroute;
extern crate serde;
extern crate serde_json;

//structs found in /serde_types.in.rs
//need this line to make serialization of structs work.
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

use std::*;
use hyper::server::{Server, Request, Response};
use hyper::status::StatusCode;
use reroute::{Captures, Router};

//static VERSION : &'static str = "/api/v1/";

static PROCESS_END_PT : &'static str = "/api/v1/processes/";
static FILE_SYS_END_PT : &'static str = r"/api/v1/filesystem/[[:ascii:]]*";
static DEBUG_ATTACH_PID_END_PT : &'static str = r"/api/v1/debug/attach/pid/[[:digit:]]*";
static DEBUG_ATTACH_BIN_END_PT : &'static str = r"/api/v1/debug/attach/bin/[[:ascii:]]*";
static DEBUG_END_PT : &'static str = "/api/v1/debug";
static DEBUG_FUNCTIONS_END_PT : &'static str = r"/api/v1/debug/functions/[[:ascii:]]*";
static BREAKPOINTS_END_PT : &'static str = "/api/v1/debug/breakpoints";
static FUNC_BREAKPOINTS_END_PT : &'static str = r"/api/v1/debug/breakpoints/[[:ascii:]]";
static DEBUG_EXEC_END_PT : &'static str = "/api/v1/debug/execute";

// @ /greet
fn basic_handler(_: Request, res: Response, c: Captures){
    println!("captures: {:?}", c);
    res.send(b"He who controls the spice...").unwrap();
}

// @ /api/v1/filesystem/:path*
fn filesystem_handler(_: Request, res: Response, c: Captures){
    println!("file system captures captures: {:?}", c); //debug line

    let c_str = &c.unwrap()[0];

    println!{"c_str value: {}", c_str}; //debug line

    let path = c_str.split("/api/v1/filesystem").nth(1).unwrap();

    println!("path value: {}", path);// debug line

    let file_meta = fs::metadata(path).unwrap();

    let mut file_type = "".to_string();

    if file_meta.is_dir(){
        file_type = "dir".to_string();
    } else{
        file_type = "file".to_string();
    }

    let my_file = File{name: path.to_string(), path: path.to_string(), f_type: file_type, contents: "Hello World".to_string()};

    let json_str = serde_json::to_string(&my_file).unwrap();

    res.send(&json_str.into_bytes()).unwrap();
}

// @ /processes
fn process_handler(_: Request, res: Response, c: Captures){
    println!("captures: {:?}", c);
    res.send(b"Here are the processes").unwrap();
}

fn main() {
    //install routes

    let mut router = Router::new();

    //host system info routes
    router.get("/greet", basic_handler);
    router.get(PROCESS_END_PT, process_handler);
    router.get(FILE_SYS_END_PT, filesystem_handler);

    //debug routes

    router.finalize().unwrap();

    let server = Server::http("127.0.0.1:3000").unwrap();
    server.handle(router).unwrap();
}
<commit_msg>more boilerplate stuff of registering rest end points and stubbing out the handlers for those end points<commit_after>extern crate hyper;
extern crate reroute;
extern crate serde;
extern crate serde_json;

//structs found in /serde_types.in.rs
//need this line to make serialization of structs work.
include!(concat!(env!("OUT_DIR"), "/serde_types.rs"));

use std::*;
use hyper::server::{Server, Request, Response};
use hyper::status::StatusCode;
use reroute::{Captures, Router};

//static VERSION : &'static str = "/api/v1/";

//REST ENDPOINTS
static FILE_SYS_END_PT : &'static str = r"/api/v1/filesystem/[[:ascii:]]*";
static PROCESS_END_PT : &'static str = "/api/v1/processes/";
static DEBUG_ATCH_PID_END_PT : &'static str = r"/api/v1/debug/attach/pid/[[:digit:]]*";
static DEBUG_ATCH_BIN_END_PT : &'static str = r"/api/v1/debug/attach/bin/[[:ascii:]]*";
static DEBUG_END_PT : &'static str = "/api/v1/debug";
static DEBUG_FUNC_LST_END_PT : &'static str = "/api/v1/debug/functions";
static DEBUG_FUNC_END_PT : &'static str = r"/api/v1/debug/functions/[[:ascii:]]*";
static BRKPNT_END_PT : &'static str = "/api/v1/debug/breakpoints";
static FUNC_BRKPNT_END_PT : &'static str = r"/api/v1/debug/breakpoints/[[:ascii:]]*"; //PUT AND DELETE
static DEBUG_EXEC_PROC_END_PT : &'static str = "/api/v1/debug/execute";
static DEBUG_EXEC_FUNC_END_PT : &'static str = r"/api/v1/debug/functions/[[:ascii:]]*/execute";

static DEBUG_EXEC_LST_END_PT : &'static str = "/api/v1/debug/executions";
static DEBUG_EXEC_STATUS_END_PT : &'static str = r"/api/v1/debug/executions/[[:digit:]]*";
static DEBUG_EXEC_TRACE_END_PT : &'static str = r"/api/v1/debug/executions/[[:digit:]]*/trace";
static DEBUG_EXEC_STOP_END_PT : &'static str = r"/api/v1/debug/executions/[[:digit:]]*/stop";

// @ /greet
fn basic_handler(_: Request, res: Response, c: Captures){
    println!("captures: {:?}", c);
    res.send(b"He who controls the spice...").unwrap();
}

// @ /filesystem/:path*
fn filesystem_handler(_: Request, res: Response, c: Captures){
    println!("file system captures captures: {:?}", c); //debug line

    let c_str = &c.unwrap()[0];

    println!{"c_str value: {}", c_str}; //debug line

    let path = c_str.split("/api/v1/filesystem").nth(1).unwrap();

    println!("path value: {}", path);// debug line

    let file_meta = fs::metadata(path).unwrap();

    let mut file_type = "".to_string();

    if file_meta.is_dir(){
        file_type = "dir".to_string();
    } else{
        file_type = "file".to_string();
    }

    let my_file = File{name: path.to_string(), path: path.to_string(), f_type: file_type, contents: "Hello World".to_string()};

    let json_str = serde_json::to_string(&my_file).unwrap();

    res.send(&json_str.into_bytes()).unwrap();
}

// @ /processes
fn process_handler(_: Request, res: Response, c: Captures){
    println!("captures: {:?}", c);
    res.send(b"Here are the processes").unwrap();
}

// @ /debug/attach/pid/:pid
fn attach_pid_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn attach_bin_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn debug_info_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn debug_list_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn function_info_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn list_breakpoints_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn set_breakpoint_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn del_breakpoint_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn launch_process_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn exec_func_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn list_execs_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn exec_status_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn exec_trace_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

// @ /debug/attach/bin/:function
fn stop_exec_handler(_:Request, res: Response, c: Captures){
    res.send(b"He who controls the spice...").unwrap();
}

fn main() {
    //install routes

    let mut router = Router::new();
    router.get("/greet", basic_handler); // debug line

    router.get(FILE_SYS_END_PT, filesystem_handler);
    router.get(PROCESS_END_PT, process_handler);
    router.post(DEBUG_ATCH_PID_END_PT, attach_pid_handler);
    router.post(DEBUG_ATCH_BIN_END_PT, attach_bin_handler);
    router.get(DEBUG_END_PT, debug_info_handler);
    router.get(DEBUG_FUNC_LST_END_PT, debug_list_handler);
    router.get(DEBUG_FUNC_END_PT, function_info_handler);
    router.get(BRKPNT_END_PT, list_breakpoints_handler);
    router.put(FUNC_BRKPNT_END_PT, set_breakpoint_handler);
    router.delete(FUNC_BRKPNT_END_PT, del_breakpoint_handler);
    router.post(DEBUG_EXEC_PROC_END_PT, launch_process_handler);
    router.post(DEBUG_EXEC_FUNC_END_PT, exec_func_handler);
    router.get(DEBUG_EXEC_LST_END_PT, list_execs_handler);
    router.get(DEBUG_EXEC_STATUS_END_PT, exec_status_handler);
    router.get(DEBUG_EXEC_TRACE_END_PT, exec_trace_handler);
    router.post(DEBUG_EXEC_STOP_END_PT, stop_exec_handler);

    router.finalize().unwrap();

    let server = Server::http("127.0.0.1:3000").unwrap();
    server.handle(router).unwrap();
}
<|endoftext|>


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

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

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

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

#![allow(unused_assignments, unused_must_use, deprecated, unused_extern_crates)]
extern crate hyper;
extern crate libproto;
extern crate protobuf;
#[macro_use]
extern crate log;
extern crate util;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate pubsub;
extern crate cpuprofiler;
extern crate jsonrpc_types;
extern crate dotenv;
extern crate logger;
extern crate threadpool;
extern crate num_cpus;
extern crate ws;
extern crate clap;
extern crate uuid;
extern crate error;

pub mod http_handler;
pub mod mq_hanlder;
pub mod base_hanlder;
pub mod ws_handler;
pub mod config;

use base_hanlder::TransferType;
use clap::App;
use config::ProfileConfig;
use cpuprofiler::PROFILER;
use dotenv::dotenv;
use http_handler::HttpHandler;
use hyper::server::Server;
use jsonrpc_types::method;
use libproto::communication::Message as CommMsg;
use libproto::request as reqlib;
use libproto::request::BatchRequest;
use protobuf::Message;
use protobuf::RepeatedField;
use pubsub::start_pubsub;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;
use std::time::SystemTime;
use util::{RwLock, Mutex};
use util::panichandler::set_panic_handler;
use uuid::Uuid;
use ws_handler::WsFactory;

pub const TOPIC_NEW_TX: &str = "jsonrpc.new_tx";
pub const TOPIC_NEW_TX_BATCH: &str = "jsonrpc.new_tx_batch";

fn start_profile(config: &ProfileConfig) {
    if config.enable {
        if config.flag_prof_start != 0 && config.flag_prof_duration != 0 {
            let start = config.flag_prof_start;
            let duration = config.flag_prof_duration;
            thread::spawn(move || {
                              thread::sleep(Duration::new(start, 0));
                              PROFILER.lock().unwrap().start("./jsonrpc.profile").expect("Couldn't start");
                              thread::sleep(Duration::new(duration, 0));
                              PROFILER.lock().unwrap().stop().unwrap();
                          });
        }

    }
}

fn main() {
    dotenv().ok();
    ::std::env::set_var("RUST_BACKTRACE", "full");
    //exit process when panic
    set_panic_handler();
    logger::init();
    info!("CITA:jsonrpc ");

    // todo load config
    let matches = App::new("JsonRpc")
        .version("0.1")
        .author("Cryptape")
        .about("CITA JSON-RPC by Rust")
        .args_from_usage("-c, --config=[FILE] 'Sets a custom config file'")
        .get_matches();

    let mut config_path = "./jsonrpc.json";
    if let Some(c) = matches.value_of("config") {
        info!("Value for config: {}", c);
        config_path = c;
    }

    let config = config::read_user_from_file(config_path).expect("config error!");
    info!("CITA:jsonrpc config \n {:?}", serde_json::to_string_pretty(&config).unwrap());

    //TODO not enable both HTTP and WebSocket server
    if config.ws_config.enable == config.http_config.enable {
        error!("not enable both HTTP and WebSocket server!");
        std::process::exit(-1);
    }

    start_profile(&config.profile_config);

    // init pubsub
    let (tx_sub, rx_sub) = channel();
    let (tx_pub, rx_pub) = channel();
    //used for buffer message
    let (tx_relay, rx_relay) = channel();
    start_pubsub("jsonrpc", vec!["auth.rpc", "chain.rpc"], tx_sub, rx_pub);

    //mq
    let mut mq_handle = mq_hanlder::MqHandler::new();

    //http
    if config.http_config.enable {
        mq_handle.set_http_or_ws(TransferType::HTTP);
        let http_responses = Arc::new(RwLock::new(HashMap::with_capacity(1000)));
        mq_handle.set_http(http_responses.clone());

        let http_config = config.http_config.clone();
        //let sender_mq_http = tx_pub.clone();
        let sender_mq_http = tx_relay.clone();
        thread::spawn(move || {
            let url = http_config.listen_ip.clone() + ":" + &http_config.listen_port.clone().to_string();
            let arc_tx = Arc::new(Mutex::new(sender_mq_http));
            info!("Http Listening on {}", url);
            let _ = Server::http(url).unwrap().handle_threads(HttpHandler {
                                                                  responses: http_responses,
                                                                  tx: arc_tx,
                                                                  sleep_duration: http_config.sleep_duration,
                                                                  timeout_count: http_config.timeout_count,
                                                                  method_handler: method::MethodHandler,
                                                              },
                                                              http_config.thread_number);
        });
    }

    //ws
    if config.ws_config.enable {
        mq_handle.set_http_or_ws(TransferType::WEBSOCKET);
        let ws_responses = Arc::new(Mutex::new(HashMap::with_capacity(1000)));
        mq_handle.set_ws(ws_responses.clone());
        let ws_config = config.ws_config.clone();
        thread::spawn(move || {
            let url = ws_config.listen_ip.clone() + ":" + &ws_config.listen_port.clone().to_string();
            //let factory = WsFactory::new(ws_responses, tx_pub, 0);
            let factory = WsFactory::new(ws_responses, tx_relay, 0);
            info!("WebSocket Listening on {}", url);
            let mut ws_build = ws::Builder::new();
            ws_build.with_settings(ws_config.into());
            let ws_server = ws_build.build(factory).unwrap();
            let _ = ws_server.listen(url);
        });
    }

    thread::spawn(move || {
        let mut new_tx_request_buffer = Vec::new();
        let mut time_stamp = SystemTime::now();
        loop {
            if let Ok(res) = rx_relay.try_recv() {
                let (topic, req): (String, reqlib::Request) = res;
                forward_service(topic, req, &mut new_tx_request_buffer, &mut time_stamp, tx_pub.clone(), &config);
            } else {
                if new_tx_request_buffer.len() > 1 {
                    batch_forward_new_tx(&mut new_tx_request_buffer, &mut time_stamp, tx_pub.clone());
                }
                thread::sleep(Duration::new(0, config.new_tx_flow_config.buffer_duration));
            }

        }
    });

    loop {
        let (key, msg) = rx_sub.recv().unwrap();
        mq_handle.handle(key, msg);
    }
}

fn batch_forward_new_tx(new_tx_request_buffer: &mut Vec<reqlib::Request>, time_stamp: &mut SystemTime, tx_pub: Sender<(String, Vec<u8>)>) {
    trace!("Going to send new tx batch to auth with {} new tx and buffer {} ns", new_tx_request_buffer.len(), time_stamp.elapsed().unwrap().subsec_nanos());

    let mut batch_request = BatchRequest::new();
    batch_request.set_new_tx_requests(RepeatedField::from_slice(&new_tx_request_buffer[..]));

    let request_id = Uuid::new_v4().as_bytes().to_vec();
    let mut request = reqlib::Request::new();
    request.set_batch_req(batch_request);
    request.set_request_id(request_id);

    let data: CommMsg = request.into();
    tx_pub.send((String::from(TOPIC_NEW_TX_BATCH), data.write_to_bytes().unwrap())).unwrap();
    *time_stamp = SystemTime::now();
    new_tx_request_buffer.clear();
}

fn forward_service(topic: String, req: reqlib::Request, new_tx_request_buffer: &mut Vec<reqlib::Request>, time_stamp: &mut SystemTime, tx_pub: Sender<(String, Vec<u8>)>, config: &config::Config) {
    if topic.as_str() != TOPIC_NEW_TX {
        let data: CommMsg = req.into();
        tx_pub.send((topic, data.write_to_bytes().unwrap())).unwrap();
    } else {
        new_tx_request_buffer.push(req);
        trace!("New tx is pushed and has {} new tx and buffer {} ns", new_tx_request_buffer.len(), time_stamp.elapsed().unwrap().subsec_nanos());
        if new_tx_request_buffer.len() > config.new_tx_flow_config.count_per_batch || time_stamp.elapsed().unwrap().subsec_nanos() > config.new_tx_flow_config.buffer_duration {
            batch_forward_new_tx(new_tx_request_buffer, time_stamp, tx_pub.clone());
        }
    }
}
<commit_msg>fix new tx timeout issue<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

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

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

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

#![allow(unused_assignments, unused_must_use, deprecated, unused_extern_crates)]
extern crate hyper;
extern crate libproto;
extern crate protobuf;
#[macro_use]
extern crate log;
extern crate util;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate pubsub;
extern crate cpuprofiler;
extern crate jsonrpc_types;
extern crate dotenv;
extern crate logger;
extern crate threadpool;
extern crate num_cpus;
extern crate ws;
extern crate clap;
extern crate uuid;
extern crate error;

pub mod http_handler;
pub mod mq_hanlder;
pub mod base_hanlder;
pub mod ws_handler;
pub mod config;

use base_hanlder::TransferType;
use clap::App;
use config::ProfileConfig;
use cpuprofiler::PROFILER;
use dotenv::dotenv;
use http_handler::HttpHandler;
use hyper::server::Server;
use jsonrpc_types::method;
use libproto::communication::Message as CommMsg;
use libproto::request as reqlib;
use libproto::request::BatchRequest;
use protobuf::Message;
use protobuf::RepeatedField;
use pubsub::start_pubsub;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::sync::mpsc::channel;
use std::thread;
use std::time::Duration;
use std::time::SystemTime;
use util::{RwLock, Mutex};
use util::panichandler::set_panic_handler;
use uuid::Uuid;
use ws_handler::WsFactory;

pub const TOPIC_NEW_TX: &str = "jsonrpc.new_tx";
pub const TOPIC_NEW_TX_BATCH: &str = "jsonrpc.new_tx_batch";

fn start_profile(config: &ProfileConfig) {
    if config.enable {
        if config.flag_prof_start != 0 && config.flag_prof_duration != 0 {
            let start = config.flag_prof_start;
            let duration = config.flag_prof_duration;
            thread::spawn(move || {
                              thread::sleep(Duration::new(start, 0));
                              PROFILER.lock().unwrap().start("./jsonrpc.profile").expect("Couldn't start");
                              thread::sleep(Duration::new(duration, 0));
                              PROFILER.lock().unwrap().stop().unwrap();
                          });
        }

    }
}

fn main() {
    dotenv().ok();
    ::std::env::set_var("RUST_BACKTRACE", "full");
    //exit process when panic
    set_panic_handler();
    logger::init();
    info!("CITA:jsonrpc ");

    // todo load config
    let matches = App::new("JsonRpc")
        .version("0.1")
        .author("Cryptape")
        .about("CITA JSON-RPC by Rust")
        .args_from_usage("-c, --config=[FILE] 'Sets a custom config file'")
        .get_matches();

    let mut config_path = "./jsonrpc.json";
    if let Some(c) = matches.value_of("config") {
        info!("Value for config: {}", c);
        config_path = c;
    }

    let config = config::read_user_from_file(config_path).expect("config error!");
    info!("CITA:jsonrpc config \n {:?}", serde_json::to_string_pretty(&config).unwrap());

    //TODO not enable both HTTP and WebSocket server
    if config.ws_config.enable == config.http_config.enable {
        error!("not enable both HTTP and WebSocket server!");
        std::process::exit(-1);
    }

    start_profile(&config.profile_config);

    // init pubsub
    let (tx_sub, rx_sub) = channel();
    let (tx_pub, rx_pub) = channel();
    //used for buffer message
    let (tx_relay, rx_relay) = channel();
    start_pubsub("jsonrpc", vec!["auth.rpc", "chain.rpc"], tx_sub, rx_pub);

    //mq
    let mut mq_handle = mq_hanlder::MqHandler::new();

    //http
    if config.http_config.enable {
        mq_handle.set_http_or_ws(TransferType::HTTP);
        let http_responses = Arc::new(RwLock::new(HashMap::with_capacity(1000)));
        mq_handle.set_http(http_responses.clone());

        let http_config = config.http_config.clone();
        //let sender_mq_http = tx_pub.clone();
        let sender_mq_http = tx_relay.clone();
        thread::spawn(move || {
            let url = http_config.listen_ip.clone() + ":" + &http_config.listen_port.clone().to_string();
            let arc_tx = Arc::new(Mutex::new(sender_mq_http));
            info!("Http Listening on {}", url);
            let _ = Server::http(url).unwrap().handle_threads(HttpHandler {
                                                                  responses: http_responses,
                                                                  tx: arc_tx,
                                                                  sleep_duration: http_config.sleep_duration,
                                                                  timeout_count: http_config.timeout_count,
                                                                  method_handler: method::MethodHandler,
                                                              },
                                                              http_config.thread_number);
        });
    }

    //ws
    if config.ws_config.enable {
        mq_handle.set_http_or_ws(TransferType::WEBSOCKET);
        let ws_responses = Arc::new(Mutex::new(HashMap::with_capacity(1000)));
        mq_handle.set_ws(ws_responses.clone());
        let ws_config = config.ws_config.clone();
        thread::spawn(move || {
            let url = ws_config.listen_ip.clone() + ":" + &ws_config.listen_port.clone().to_string();
            //let factory = WsFactory::new(ws_responses, tx_pub, 0);
            let factory = WsFactory::new(ws_responses, tx_relay, 0);
            info!("WebSocket Listening on {}", url);
            let mut ws_build = ws::Builder::new();
            ws_build.with_settings(ws_config.into());
            let ws_server = ws_build.build(factory).unwrap();
            let _ = ws_server.listen(url);
        });
    }

    thread::spawn(move || {
        let mut new_tx_request_buffer = Vec::new();
        let mut time_stamp = SystemTime::now();
        loop {
            if let Ok(res) = rx_relay.try_recv() {
                let (topic, req): (String, reqlib::Request) = res;
                forward_service(topic, req, &mut new_tx_request_buffer, &mut time_stamp, tx_pub.clone(), &config);
            } else {
                if new_tx_request_buffer.len() > 0 {
                    batch_forward_new_tx(&mut new_tx_request_buffer, &mut time_stamp, tx_pub.clone());
                }
                thread::sleep(Duration::new(0, config.new_tx_flow_config.buffer_duration));
            }

        }
    });

    loop {
        let (key, msg) = rx_sub.recv().unwrap();
        mq_handle.handle(key, msg);
    }
}

fn batch_forward_new_tx(new_tx_request_buffer: &mut Vec<reqlib::Request>, time_stamp: &mut SystemTime, tx_pub: Sender<(String, Vec<u8>)>) {
    trace!("Going to send new tx batch to auth with {} new tx and buffer time cost is {:?} ", new_tx_request_buffer.len(), time_stamp.elapsed().unwrap());

    let mut batch_request = BatchRequest::new();
    batch_request.set_new_tx_requests(RepeatedField::from_slice(&new_tx_request_buffer[..]));

    let request_id = Uuid::new_v4().as_bytes().to_vec();
    let mut request = reqlib::Request::new();
    request.set_batch_req(batch_request);
    request.set_request_id(request_id);

    let data: CommMsg = request.into();
    tx_pub.send((String::from(TOPIC_NEW_TX_BATCH), data.write_to_bytes().unwrap())).unwrap();
    *time_stamp = SystemTime::now();
    new_tx_request_buffer.clear();
}

fn forward_service(topic: String, req: reqlib::Request, new_tx_request_buffer: &mut Vec<reqlib::Request>, time_stamp: &mut SystemTime, tx_pub: Sender<(String, Vec<u8>)>, config: &config::Config) {
    if topic.as_str() != TOPIC_NEW_TX {
        let data: CommMsg = req.into();
        tx_pub.send((topic, data.write_to_bytes().unwrap())).unwrap();
    } else {
        new_tx_request_buffer.push(req);
        trace!("New tx is pushed and has {} new tx and buffer time cost is {:?}", new_tx_request_buffer.len(), time_stamp.elapsed().unwrap());
        if new_tx_request_buffer.len() > config.new_tx_flow_config.count_per_batch || time_stamp.elapsed().unwrap().subsec_nanos() > config.new_tx_flow_config.buffer_duration {
            batch_forward_new_tx(new_tx_request_buffer, time_stamp, tx_pub.clone());
        }
    }
}
<|endoftext|>


<commit_before>mod quick_error;

#[derive(Debug)]
pub struct ForeignError {
    pub description: String,
    pub display: String,
}

impl ForeignError {
    pub fn new<E>(e: &E) -> ForeignError
        where E: ::std::error::Error
    {
        ForeignError {
            description: e.description().to_string(),
            display: format!("{}", e)
        }
    }
}

#[macro_export]
macro_rules! declare_errors {
    (
        types {
            $error_name:ident, $error_kind_name:ident, $chain_error_name:ident, $result_name:ident;
        }

        links {
            $( $from_link_chain_path:path, $from_link_error_path:path, $from_link_variant:ident;  ) *
        }

        foreign_links {
            $( $foreign_link_error_path:path, $foreign_link_variant:ident;  ) *
        }

        errors {
            $( $error_chunks:tt ) *
        }

    ) => {

        pub type $result_name<T> = ::std::result::Result<T, $error_name>;

        pub trait $chain_error_name<T> {
            fn chain_error<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
                where F: FnOnce() -> EK,
                      EK: Into<$error_kind_name>;
        }

        impl<T, E> $chain_error_name<T> for ::std::result::Result<T, E>
            where E: ::std::error::Error + Send + 'static
        {
            fn chain_error<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
                where F: FnOnce() -> EK,
                      EK: Into<$error_kind_name>
            {
                self.map_err(move |e| {
                    $error_name::extend_chain(callback().into(), e)
                })
            }
        }

        #[derive(Debug)]
        pub struct $error_name(pub $error_kind_name, pub Option<Box<::std::error::Error + Send>>);

        impl $error_name {
            pub fn new_chain(e: $error_kind_name) -> Self {
                $error_name(e, None)
            }

            pub fn extend_chain<SE>(e: $error_kind_name, c: SE) -> Self
                where SE: ::std::error::Error + Send + 'static
            {
                $error_name(e, Some(Box::new(c)))
            }

            pub fn inner(&self) -> &$error_kind_name {
                &self.0
            }

            pub fn into_inner(self) -> $error_kind_name {
                self.0
            }
        }

        impl ::std::error::Error for $error_name {
            fn description(&self) -> &str { self.0.description() }
            fn cause(&self) -> Option<&::std::error::Error> {
                match self.1 {
                    Some(ref c) => Some(&**c),
                    None => None
                }
            }
        }

        impl ::std::fmt::Display for $error_name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                ::std::fmt::Display::fmt(&self.0, f)
            }
        }

        quick_error! {
            #[derive(Debug)]
            pub enum $error_kind_name {
                $(
                    $from_link_variant(e: $from_link_error_path) {
                        description(e.description())
                        display("{}", e)
                    }
                ) *

                $(
                    $foreign_link_variant(e: $crate::ForeignError) {
                        description(&e.description)
                        display("{}", e.display)
                    }
                ) *

                $($error_chunks)*
            }
        }

        impl $error_kind_name {
            pub fn unchained(self) -> $error_name {
                $error_name::new_chain(self)
            }

            pub fn chained<E>(self, e: E) -> $error_name
                where E: ::std::error::Error + Send + 'static
            {
                $error_name::extend_chain(self, e)
            }
        }

        $(
            impl From<$from_link_chain_path> for $error_name {
                fn from(e: $from_link_chain_path) -> Self {
                    $error_name($error_kind_name::$from_link_variant(e.0), e.1)
                }
            }
        ) *

        $(
            impl From<$foreign_link_error_path> for $error_name {
                fn from(e: $foreign_link_error_path) -> Self {
                    $error_name($error_kind_name::$foreign_link_variant(
                        $crate::ForeignError::new(&e)), Some(Box::new(e)))
                }
            }
        ) *

    };
}
<commit_msg>from_link -> link<commit_after>mod quick_error;

#[derive(Debug)]
pub struct ForeignError {
    pub description: String,
    pub display: String,
}

impl ForeignError {
    pub fn new<E>(e: &E) -> ForeignError
        where E: ::std::error::Error
    {
        ForeignError {
            description: e.description().to_string(),
            display: format!("{}", e)
        }
    }
}

#[macro_export]
macro_rules! declare_errors {
    (
        types {
            $error_name:ident, $error_kind_name:ident, $chain_error_name:ident, $result_name:ident;
        }

        links {
            $( $link_chain_path:path, $link_error_path:path, $link_variant:ident;  ) *
        }

        foreign_links {
            $( $foreign_link_error_path:path, $foreign_link_variant:ident;  ) *
        }

        errors {
            $( $error_chunks:tt ) *
        }

    ) => {

        pub type $result_name<T> = ::std::result::Result<T, $error_name>;

        pub trait $chain_error_name<T> {
            fn chain_error<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
                where F: FnOnce() -> EK,
                      EK: Into<$error_kind_name>;
        }

        impl<T, E> $chain_error_name<T> for ::std::result::Result<T, E>
            where E: ::std::error::Error + Send + 'static
        {
            fn chain_error<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
                where F: FnOnce() -> EK,
                      EK: Into<$error_kind_name>
            {
                self.map_err(move |e| {
                    $error_name::extend_chain(callback().into(), e)
                })
            }
        }

        #[derive(Debug)]
        pub struct $error_name(pub $error_kind_name, pub Option<Box<::std::error::Error + Send>>);

        impl $error_name {
            pub fn new_chain(e: $error_kind_name) -> Self {
                $error_name(e, None)
            }

            pub fn extend_chain<SE>(e: $error_kind_name, c: SE) -> Self
                where SE: ::std::error::Error + Send + 'static
            {
                $error_name(e, Some(Box::new(c)))
            }

            pub fn inner(&self) -> &$error_kind_name {
                &self.0
            }

            pub fn into_inner(self) -> $error_kind_name {
                self.0
            }
        }

        impl ::std::error::Error for $error_name {
            fn description(&self) -> &str { self.0.description() }
            fn cause(&self) -> Option<&::std::error::Error> {
                match self.1 {
                    Some(ref c) => Some(&**c),
                    None => None
                }
            }
        }

        impl ::std::fmt::Display for $error_name {
            fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                ::std::fmt::Display::fmt(&self.0, f)
            }
        }

        quick_error! {
            #[derive(Debug)]
            pub enum $error_kind_name {
                $(
                    $link_variant(e: $link_error_path) {
                        description(e.description())
                        display("{}", e)
                    }
                ) *

                $(
                    $foreign_link_variant(e: $crate::ForeignError) {
                        description(&e.description)
                        display("{}", e.display)
                    }
                ) *

                $($error_chunks)*
            }
        }

        impl $error_kind_name {
            pub fn unchained(self) -> $error_name {
                $error_name::new_chain(self)
            }

            pub fn chained<E>(self, e: E) -> $error_name
                where E: ::std::error::Error + Send + 'static
            {
                $error_name::extend_chain(self, e)
            }
        }

        $(
            impl From<$link_chain_path> for $error_name {
                fn from(e: $link_chain_path) -> Self {
                    $error_name($error_kind_name::$link_variant(e.0), e.1)
                }
            }
        ) *

        $(
            impl From<$foreign_link_error_path> for $error_name {
                fn from(e: $foreign_link_error_path) -> Self {
                    $error_name($error_kind_name::$foreign_link_variant(
                        $crate::ForeignError::new(&e)), Some(Box::new(e)))
                }
            }
        ) *

    };
}
<|endoftext|>


<commit_before>//! This module implements per-component parallelism.
//! It should be possible to implement per-row parallelism as well,
//! which should also boost performance of grayscale images
//! and allow scaling to more cores.
//! However, that would be more complex, so we use this as a starting point.

use decoder::MAX_COMPONENTS;
use error::Result;
use std::{mem, sync::mpsc::{self, Sender}};
use std::thread;
use super::{RowData, Worker};
use super::immediate::ImmediateWorker;

enum WorkerMsg {
    Start(RowData),
    AppendRow(Vec<i16>),
    GetResult(Sender<Vec<u8>>),
}
pub struct MultiThreadedWorker {
    senders: [Option<Sender<WorkerMsg>>; MAX_COMPONENTS]
}

impl Worker for MultiThreadedWorker {
    fn new() -> Result<Self> {
        Ok(MultiThreadedWorker {
            senders: [None, None, None, None]
        })
    }
    fn start(&mut self, row_data: RowData) -> Result<()> {
        // if there is no worker thread for this component yet, start one
        let component = row_data.index;
        if let None = self.senders[component] {
            let sender = spawn_worker_thread(component)?;
            self.senders[component] = Some(sender);
        }
        // we do the "take out value and put it back in once we're done" dance here
        // and in all other message-passing methods because there's not that many rows
        // and this should be cheaper than spawning MAX_COMPONENTS many threads up front
        let sender = mem::replace(&mut self.senders[component], None).unwrap();
        sender.send(WorkerMsg::Start(row_data)).expect("jpeg-decoder worker thread error");
        self.senders[component] = Some(sender);
        Ok(())
    }
    fn append_row(&mut self, row: (usize, Vec<i16>)) -> Result<()> {
        let component = row.0;
        let sender = mem::replace(&mut self.senders[component], None).unwrap();
        sender.send(WorkerMsg::AppendRow(row.1)).expect("jpeg-decoder worker thread error");
        self.senders[component] = Some(sender);
        Ok(())
    }
    fn get_result(&mut self, index: usize) -> Result<Vec<u8>> {
        let (tx, rx) = mpsc::channel();
        let sender = mem::replace(&mut self.senders[index], None).unwrap();
        sender.send(WorkerMsg::GetResult(tx)).expect("jpeg-decoder worker thread error");
        Ok(rx.recv().expect("jpeg-decoder worker thread error"))
    }
}

fn spawn_worker_thread(component: usize) -> Result<Sender<WorkerMsg>> {
    let thread_builder = thread::Builder::new().name(format!("worker thread for component {}", component));
    let (tx, rx) = mpsc::channel();

    thread_builder.spawn(move || {
        let mut worker = ImmediateWorker::new_immediate();

        while let Ok(message) = rx.recv() {
            match message {
                WorkerMsg::Start(mut data) => {
                    // we always set component index to 0 for worker threads
                    // because they only ever handle one per thread and we don't want them
                    // to attempt to access nonexistent components
                    data.index = 0;
                    worker.start_immediate(data);
                },
                WorkerMsg::AppendRow(row) => {
                    worker.append_row_immediate((0, row));
                },
                WorkerMsg::GetResult(chan) => {
                    let _ = chan.send(worker.get_result_immediate(0));
                    break;
                },
            }
        }
    })?;

    Ok(tx)
}<commit_msg>Use rayon threads when the rayon feature is enabled<commit_after>//! This module implements per-component parallelism.
//! It should be possible to implement per-row parallelism as well,
//! which should also boost performance of grayscale images
//! and allow scaling to more cores.
//! However, that would be more complex, so we use this as a starting point.

use decoder::MAX_COMPONENTS;
use error::Result;
use std::{mem, io, sync::mpsc::{self, Sender}};
use super::{RowData, Worker};
use super::immediate::ImmediateWorker;

enum WorkerMsg {
    Start(RowData),
    AppendRow(Vec<i16>),
    GetResult(Sender<Vec<u8>>),
}
pub struct MultiThreadedWorker {
    senders: [Option<Sender<WorkerMsg>>; MAX_COMPONENTS]
}

impl Worker for MultiThreadedWorker {
    fn new() -> Result<Self> {
        Ok(MultiThreadedWorker {
            senders: [None, None, None, None]
        })
    }
    fn start(&mut self, row_data: RowData) -> Result<()> {
        // if there is no worker thread for this component yet, start one
        let component = row_data.index;
        if let None = self.senders[component] {
            let sender = spawn_worker_thread(component)?;
            self.senders[component] = Some(sender);
        }
        // we do the "take out value and put it back in once we're done" dance here
        // and in all other message-passing methods because there's not that many rows
        // and this should be cheaper than spawning MAX_COMPONENTS many threads up front
        let sender = mem::replace(&mut self.senders[component], None).unwrap();
        sender.send(WorkerMsg::Start(row_data)).expect("jpeg-decoder worker thread error");
        self.senders[component] = Some(sender);
        Ok(())
    }
    fn append_row(&mut self, row: (usize, Vec<i16>)) -> Result<()> {
        let component = row.0;
        let sender = mem::replace(&mut self.senders[component], None).unwrap();
        sender.send(WorkerMsg::AppendRow(row.1)).expect("jpeg-decoder worker thread error");
        self.senders[component] = Some(sender);
        Ok(())
    }
    fn get_result(&mut self, index: usize) -> Result<Vec<u8>> {
        let (tx, rx) = mpsc::channel();
        let sender = mem::replace(&mut self.senders[index], None).unwrap();
        sender.send(WorkerMsg::GetResult(tx)).expect("jpeg-decoder worker thread error");
        Ok(rx.recv().expect("jpeg-decoder worker thread error"))
    }
}

fn spawn_worker_thread(component: usize) -> Result<Sender<WorkerMsg>> {
    let (tx, rx) = mpsc::channel();

    spawn(component, move || {
        let mut worker = ImmediateWorker::new_immediate();

        while let Ok(message) = rx.recv() {
            match message {
                WorkerMsg::Start(mut data) => {
                    // we always set component index to 0 for worker threads
                    // because they only ever handle one per thread and we don't want them
                    // to attempt to access nonexistent components
                    data.index = 0;
                    worker.start_immediate(data);
                },
                WorkerMsg::AppendRow(row) => {
                    worker.append_row_immediate((0, row));
                },
                WorkerMsg::GetResult(chan) => {
                    let _ = chan.send(worker.get_result_immediate(0));
                    break;
                },
            }
        }
    })?;

    Ok(tx)
}

#[cfg(feature = "rayon")]
fn spawn<F>(_component: usize, func: F) -> io::Result<()>
where
    F: FnOnce() + Send + 'static,
{
    rayon::spawn(func);
    Ok(())
}

#[cfg(not(feature = "rayon"))]
fn spawn<F>(component: usize, func: F) -> io::Result<()>
where
    F: FnOnce() + Send + 'static,
{
    let thread_builder =
        std::thread::Builder::new().name(format!("worker thread for component {}", component));
    thread_builder.spawn(func)?;
    Ok(())
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ByteOrder};
use std::io::Cursor;

pub struct IPv4Header {
    pub version: u8,
    pub header_length: u8,
    pub total_length: u16,
    pub protocol: Protocol,
    pub source: u32,
    pub destination: u32,
}

#[derive(Debug, PartialEq)]
pub enum Protocol {
    TCP,
    UDP,
    OTHER,
}

impl IPv4Header {
    pub fn parse(raw: &[u8]) -> IPv4Header {
        IPv4Header {
            version: raw[0] >> 4,
            header_length: (raw[0] & 0xf) << 2,
            total_length: BigEndian::read_u16(&raw[2..4]),
            protocol: match raw[9] {
                6 => Protocol::TCP,
                17 => Protocol::UDP,
                _ => Protocol::OTHER
            },
            source: BigEndian::read_u32(&raw[12..16]),
            destination: BigEndian::read_u32(&raw[16..20]),
        }
    }

    pub fn set_total_length(&mut self, raw: &mut [u8], total_length: u16) {
        self.total_length = total_length;
        BigEndian::write_u16(&mut raw[2..4], total_length);
    }

    pub fn set_source(&mut self, raw: &mut [u8], source: u32) {
        self.source = source;
        BigEndian::write_u32(&mut raw[12..16], source);
    }

    pub fn set_destination(&mut self, raw: &mut [u8], destination: u32) {
        self.destination = destination;
        BigEndian::write_u32(&mut raw[16..20], destination);
    }

    pub fn switch_source_and_destination(&mut self, raw: &mut [u8]) {
        let source = self.source;
        let destination = self.destination;
        self.set_source(raw, destination);
        self.set_destination(raw, source);
    }

    pub fn compute_checksum(&mut self, raw: &mut [u8]) {
        // reset checksum field
        self.set_checksum(raw, 0);

        let j = self.header_length as usize / 2;
        let mut sum = (0..j).map(|i| {
            let range = 2*i..2*(i+1);
            BigEndian::read_u16(&raw[range]) as u32
        }).sum::<u32>();
        while (sum & !0xffff) != 0 {
            sum = (sum & 0xffff) + (sum >> 16);
        }

        self.set_checksum(raw, !sum as u16);
    }

    fn get_checksum(&mut self, raw: &mut [u8]) -> u16 {
        BigEndian::read_u16(&raw[10..12])
    }

    fn set_checksum(&mut self, raw: &mut [u8], checksum: u16) {
        BigEndian::write_u16(&mut raw[10..12], checksum);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use byteorder::{BigEndian, WriteBytesExt};

    fn create_header() -> Vec<u8> {
        let mut raw: Vec<u8> = vec![];
        raw.reserve(20);
        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(28).unwrap(); // total length
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(17).unwrap(); // protocol (UDP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0x42424242).unwrap(); // destination address
        raw
    }

    #[test]
    fn parse_header() {
        let raw = &create_header()[..];
        let data = IPv4Header::parse(raw);
        assert_eq!(4, data.version);
        assert_eq!(20, data.header_length);
        assert_eq!(28, data.total_length);
        assert_eq!(Protocol::UDP, data.protocol);
        assert_eq!(0x12345678, data.source);
        assert_eq!(0x42424242, data.destination);
    }

    #[test]
    fn edit_header() {
        let raw = &mut create_header()[..];
        let mut header = IPv4Header::parse(raw);

        header.set_source(raw, 0x87654321);
        header.set_destination(raw, 0x24242424);
        header.set_total_length(raw, 42);
        assert_eq!(0x87654321, header.source);
        assert_eq!(0x24242424, header.destination);
        assert_eq!(42, header.total_length);

        // assert that the buffer has been modified
        let raw_source = BigEndian::read_u32(&raw[12..16]);
        let raw_destination = BigEndian::read_u32(&raw[16..20]);
        let raw_total_length = BigEndian::read_u16(&raw[2..4]);
        assert_eq!(0x87654321, raw_source);
        assert_eq!(0x24242424, raw_destination);
        assert_eq!(42, raw_total_length);

        header.switch_source_and_destination(raw);

        assert_eq!(0x24242424, header.source);
        assert_eq!(0x87654321, header.destination);

        let raw_source = BigEndian::read_u32(&raw[12..16]);
        let raw_destination = BigEndian::read_u32(&raw[16..20]);
        assert_eq!(0x24242424, raw_source);
        assert_eq!(0x87654321, raw_destination);
    }

    #[test]
    fn compute_checksum() {
        let mut raw = &mut create_header()[..];
        let mut header = IPv4Header::parse(raw);

        // set a fake checksum value to assert that it is correctly computed
        header.set_checksum(raw, 0x79);

        header.compute_checksum(raw);

        let mut sum = 0x4500u32 + 0x001Cu32 + 0x0000u32 + 0x0000u32 + 0x0011u32
                    + 0x0000u32 + 0x1234u32 + 0x5678u32 + 0x4242u32 + 0x4242u32;
        while (sum & !0xffff) != 0 {
            sum = (sum & 0xffff) + (sum >> 16);
        }
        let sum = !sum as u16;
        assert_eq!(sum, header.get_checksum(raw));
    }
}
<commit_msg>Remove useless mut<commit_after>use byteorder::{BigEndian, ByteOrder};
use std::io::Cursor;

pub struct IPv4Header {
    pub version: u8,
    pub header_length: u8,
    pub total_length: u16,
    pub protocol: Protocol,
    pub source: u32,
    pub destination: u32,
}

#[derive(Debug, PartialEq)]
pub enum Protocol {
    TCP,
    UDP,
    OTHER,
}

impl IPv4Header {
    pub fn parse(raw: &[u8]) -> IPv4Header {
        IPv4Header {
            version: raw[0] >> 4,
            header_length: (raw[0] & 0xf) << 2,
            total_length: BigEndian::read_u16(&raw[2..4]),
            protocol: match raw[9] {
                6 => Protocol::TCP,
                17 => Protocol::UDP,
                _ => Protocol::OTHER
            },
            source: BigEndian::read_u32(&raw[12..16]),
            destination: BigEndian::read_u32(&raw[16..20]),
        }
    }

    pub fn set_total_length(&mut self, raw: &mut [u8], total_length: u16) {
        self.total_length = total_length;
        BigEndian::write_u16(&mut raw[2..4], total_length);
    }

    pub fn set_source(&mut self, raw: &mut [u8], source: u32) {
        self.source = source;
        BigEndian::write_u32(&mut raw[12..16], source);
    }

    pub fn set_destination(&mut self, raw: &mut [u8], destination: u32) {
        self.destination = destination;
        BigEndian::write_u32(&mut raw[16..20], destination);
    }

    pub fn switch_source_and_destination(&mut self, raw: &mut [u8]) {
        let source = self.source;
        let destination = self.destination;
        self.set_source(raw, destination);
        self.set_destination(raw, source);
    }

    pub fn compute_checksum(&mut self, raw: &mut [u8]) {
        // reset checksum field
        self.set_checksum(raw, 0);

        let j = self.header_length as usize / 2;
        let mut sum = (0..j).map(|i| {
            let range = 2*i..2*(i+1);
            BigEndian::read_u16(&raw[range]) as u32
        }).sum::<u32>();
        while (sum & !0xffff) != 0 {
            sum = (sum & 0xffff) + (sum >> 16);
        }

        self.set_checksum(raw, !sum as u16);
    }

    fn get_checksum(&mut self, raw: &[u8]) -> u16 {
        BigEndian::read_u16(&raw[10..12])
    }

    fn set_checksum(&mut self, raw: &mut [u8], checksum: u16) {
        BigEndian::write_u16(&mut raw[10..12], checksum);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;
    use byteorder::{BigEndian, WriteBytesExt};

    fn create_header() -> Vec<u8> {
        let mut raw: Vec<u8> = vec![];
        raw.reserve(20);
        raw.write_u8(4u8 << 4 | 5).unwrap(); // version_and_ihl
        raw.write_u8(0).unwrap(); //ToS
        raw.write_u16::<BigEndian>(28).unwrap(); // total length
        raw.write_u32::<BigEndian>(0).unwrap(); // id_flags_fragment_offset
        raw.write_u8(0).unwrap(); // TTL
        raw.write_u8(17).unwrap(); // protocol (UDP)
        raw.write_u16::<BigEndian>(0).unwrap(); // checksum
        raw.write_u32::<BigEndian>(0x12345678).unwrap(); // source address
        raw.write_u32::<BigEndian>(0x42424242).unwrap(); // destination address
        raw
    }

    #[test]
    fn parse_header() {
        let raw = &create_header()[..];
        let data = IPv4Header::parse(raw);
        assert_eq!(4, data.version);
        assert_eq!(20, data.header_length);
        assert_eq!(28, data.total_length);
        assert_eq!(Protocol::UDP, data.protocol);
        assert_eq!(0x12345678, data.source);
        assert_eq!(0x42424242, data.destination);
    }

    #[test]
    fn edit_header() {
        let raw = &mut create_header()[..];
        let mut header = IPv4Header::parse(raw);

        header.set_source(raw, 0x87654321);
        header.set_destination(raw, 0x24242424);
        header.set_total_length(raw, 42);
        assert_eq!(0x87654321, header.source);
        assert_eq!(0x24242424, header.destination);
        assert_eq!(42, header.total_length);

        // assert that the buffer has been modified
        let raw_source = BigEndian::read_u32(&raw[12..16]);
        let raw_destination = BigEndian::read_u32(&raw[16..20]);
        let raw_total_length = BigEndian::read_u16(&raw[2..4]);
        assert_eq!(0x87654321, raw_source);
        assert_eq!(0x24242424, raw_destination);
        assert_eq!(42, raw_total_length);

        header.switch_source_and_destination(raw);

        assert_eq!(0x24242424, header.source);
        assert_eq!(0x87654321, header.destination);

        let raw_source = BigEndian::read_u32(&raw[12..16]);
        let raw_destination = BigEndian::read_u32(&raw[16..20]);
        assert_eq!(0x24242424, raw_source);
        assert_eq!(0x87654321, raw_destination);
    }

    #[test]
    fn compute_checksum() {
        let mut raw = &mut create_header()[..];
        let mut header = IPv4Header::parse(raw);

        // set a fake checksum value to assert that it is correctly computed
        header.set_checksum(raw, 0x79);

        header.compute_checksum(raw);

        let mut sum = 0x4500u32 + 0x001Cu32 + 0x0000u32 + 0x0000u32 + 0x0011u32
                    + 0x0000u32 + 0x1234u32 + 0x5678u32 + 0x4242u32 + 0x4242u32;
        while (sum & !0xffff) != 0 {
            sum = (sum & 0xffff) + (sum >> 16);
        }
        let sum = !sum as u16;
        assert_eq!(sum, header.get_checksum(raw));
    }
}
<|endoftext|>


<commit_before>#![allow(missing_doc)]

//! A First Person Shooter controller.

use std::num::{One, Zero};
use input::keyboard;
use {
    input,
    Camera,
    GameEvent,
    Input,
    Update,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// FPS controller settings.
pub struct FPSControllerSettings {
    /// Which key to press to move forward.
    pub move_forward_key: keyboard::Key,
    /// Which key to press to move backward.
    pub move_backward_key: keyboard::Key,
    /// Which key to press to strafe left.
    pub strafe_left_key: keyboard::Key,
    /// Which key to press to strafe right.
    pub strafe_right_key: keyboard::Key,
    /// Which key to press to fly up.
    pub fly_up_key: keyboard::Key,
    /// Which key to press to fly down.
    pub fly_down_key: keyboard::Key,
    /// Which key to press to move faster.
    pub move_faster_key: keyboard::Key,
}

impl FPSControllerSettings {
    /// Creates new FPS controller settings with defaults.
    pub fn default() -> FPSControllerSettings {
        FPSControllerSettings {
            move_forward_key: keyboard::W,
            move_backward_key: keyboard::S,
            strafe_left_key: keyboard::A,
            strafe_right_key: keyboard::D,
            fly_up_key: keyboard::Space,
            fly_down_key: keyboard::LShift,
            move_faster_key: keyboard::LCtrl,
        }
    }
}

/// Models a First Person Shooter (FPS) controller.
pub struct FPSController<T=f32> {
    /// The FPS controller settings.
    pub settings: FPSControllerSettings,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The keys that are pressed.
    pub keys: Keys,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FPSController<T> {
    /// Creates a new FPS controller.
    pub fn new(settings: FPSControllerSettings) -> FPSController<T> {
        let _0: T = Zero::zero();
        FPSController {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            velocity: One::one(),
        }
    }

    /// Handles game event and updates camera.
    pub fn event(&mut self, e: &GameEvent, camera: &mut Camera<T>) {
        let &FPSController {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            Update(args) => {
                let dt: T = FromPrimitive::from_f64(args.dt).unwrap();
                let dh = dt * *velocity * _3;
                let [dx, dy, dz] = *direction;
                let (s, c) = (yaw.sin(), yaw.cos());
                camera.position = [
                    camera.position[0] + (s * dx - c * dz) * dh,
                    camera.position[1] + dy * dt * _4,
                    camera.position[2] + (s * dz + c * dx) * dh
                ];
            },
            Input(input::MouseRelativeMove(args)) => {
                let dx: T = FromPrimitive::from_f64(args.dx).unwrap();
                let dy: T = FromPrimitive::from_f64(args.dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
                camera.set_yaw_pitch(*yaw, *pitch);
            },
            Input(input::KeyPress(args)) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match args.key {
                    x if x == settings.move_forward_key => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_key => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_key => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_key => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_key => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_key => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_key => *velocity = _2,
                    _ => {}
                }
            },
            Input(input::KeyRelease(args)) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match args.key {
                    x if x == settings.move_forward_key => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_key => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_key => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_key => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_key => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_key => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_key => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<commit_msg>Separated `event` into two methods<commit_after>#![allow(missing_doc)]

//! A First Person Shooter controller.

use std::num::{One, Zero};
use input::keyboard;
use {
    input,
    Camera,
};

bitflags!(flags Keys: u8 {
    static MoveForward = 0b00000001,
    static MoveBack    = 0b00000010,
    static StrafeLeft  = 0b00000100,
    static StrafeRight = 0b00001000,
    static FlyUp       = 0b00010000,
    static FlyDown     = 0b00100000
})

/// FPS controller settings.
pub struct FPSControllerSettings {
    /// Which key to press to move forward.
    pub move_forward_key: keyboard::Key,
    /// Which key to press to move backward.
    pub move_backward_key: keyboard::Key,
    /// Which key to press to strafe left.
    pub strafe_left_key: keyboard::Key,
    /// Which key to press to strafe right.
    pub strafe_right_key: keyboard::Key,
    /// Which key to press to fly up.
    pub fly_up_key: keyboard::Key,
    /// Which key to press to fly down.
    pub fly_down_key: keyboard::Key,
    /// Which key to press to move faster.
    pub move_faster_key: keyboard::Key,
}

impl FPSControllerSettings {
    /// Creates new FPS controller settings with defaults.
    pub fn default() -> FPSControllerSettings {
        FPSControllerSettings {
            move_forward_key: keyboard::W,
            move_backward_key: keyboard::S,
            strafe_left_key: keyboard::A,
            strafe_right_key: keyboard::D,
            fly_up_key: keyboard::Space,
            fly_down_key: keyboard::LShift,
            move_faster_key: keyboard::LCtrl,
        }
    }
}

/// Models a First Person Shooter (FPS) controller.
pub struct FPSController<T=f32> {
    /// The FPS controller settings.
    pub settings: FPSControllerSettings,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The keys that are pressed.
    pub keys: Keys,
    /// The direction we are heading.
    pub direction: [T, ..3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
}

impl<T: Float + FromPrimitive + Copy + FloatMath> FPSController<T> {
    /// Creates a new FPS controller.
    pub fn new(settings: FPSControllerSettings) -> FPSController<T> {
        let _0: T = Zero::zero();
        FPSController {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            velocity: One::one(),
        }
    }

    /// Updates camera.
    pub fn update(&self, dt: f64, camera: &mut Camera<T>) {
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * _3;
        let [dx, dy, dz] = self.direction;
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        camera.position = [
            camera.position[0] + (s * dx - c * dz) * dh,
            camera.position[1] + dy * dt * _4,
            camera.position[2] + (s * dz + c * dx) * dh
        ];
    }

    /// Handles game event and updates camera.
    pub fn input(&mut self, e: &input::InputEvent, camera: &mut Camera<T>) {
        let &FPSController {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
        } = self;

        let pi: T = Float::pi();
        let sqrt2: T = Float::sqrt2();
        let _0: T = Zero::zero();
        let _1: T = One::one();
        let _2: T = FromPrimitive::from_int(2).unwrap();
        let _3: T = FromPrimitive::from_int(3).unwrap();
        let _4: T = FromPrimitive::from_int(4).unwrap();
        let _360: T = FromPrimitive::from_int(360).unwrap();
        match *e {
            input::MouseRelativeMove(args) => {
                let dx: T = FromPrimitive::from_f64(args.dx).unwrap();
                let dy: T = FromPrimitive::from_f64(args.dy).unwrap();
                *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
                *pitch = *pitch + dy / _360 * pi / _4;
                *pitch = (*pitch).min(pi / _2).max(-pi / _2);
                camera.set_yaw_pitch(*yaw, *pitch);
            },
            input::KeyPress(args) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |k, x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                    keys.insert(k);
                };
                match args.key {
                    x if x == settings.move_forward_key => set(MoveForward, -_1, dy, dz),
                    x if x == settings.move_backward_key => set(MoveBack, _1, dy, dz),
                    x if x == settings.strafe_left_key => set(StrafeLeft, dx, dy, _1),
                    x if x == settings.strafe_right_key => set(StrafeRight, dx, dy, -_1),
                    x if x == settings.fly_up_key => set(FlyUp, dx, _1, dz),
                    x if x == settings.fly_down_key => set(FlyDown, dx, -_1, dz),
                    x if x == settings.move_faster_key => *velocity = _2,
                    _ => {}
                }
            },
            input::KeyRelease(args) => {
                let [dx, dy, dz] = *direction;
                let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
                let set = |x: T, y: T, z: T| {
                    let (x, z) = (sgn(x), sgn(z));
                    let (x, z) = if x != _0 && z != _0 {
                        (x / sqrt2, z / sqrt2)
                    } else {
                        (x, z)
                    };
                    *direction = [x, y, z];
                };
                let release = |key, rev_key, rev_val| {
                    keys.remove(key);
                    if keys.contains(rev_key) { rev_val } else { _0 }
                };
                match args.key {
                    x if x == settings.move_forward_key => set(release(MoveForward, MoveBack, _1), dy, dz),
                    x if x == settings.move_backward_key => set(release(MoveBack, MoveForward, -_1), dy, dz),
                    x if x == settings.strafe_left_key => set(dx, dy, release(StrafeLeft, StrafeRight, -_1)),
                    x if x == settings.strafe_right_key => set(dx, dy, release(StrafeRight, StrafeLeft, _1)),
                    x if x == settings.fly_up_key => set(dx, release(FlyUp, FlyDown, -_1), dz),
                    x if x == settings.fly_down_key => set(dx, release(FlyDown, FlyUp, _1), dz),
                    x if x == settings.move_faster_key => *velocity = _1,
                    _ => {}
                }
            },
            _ => {},
        }
    }
}

<|endoftext|>