<commit_before>use std;
use std::io::{Error, ErrorKind};
use std::thread;
use std::net::{ToSocketAddrs, SocketAddr};
use std::sync::mpsc;
use mio::{EventLoop, PollOpt, EventSet, Handler, Sender, Token};
use mio::udp::UdpSocket;
use message::packet::Packet;
use message::request::CoAPRequest;
use message::response::CoAPResponse;
use threadpool::ThreadPool;

const DEFAULT_WORKER_NUM: usize = 4;
type TxQueue = mpsc::Sender<QueuedResponse>;
type RxQueue = mpsc::Receiver<QueuedResponse>;

#[derive(Debug)]
pub enum CoAPServerError {
    NetworkError,
    EventLoopError,
    AnotherHandlerIsRunning,
}

#[derive(Debug)]
struct QueuedResponse {
    pub address: SocketAddr,
    pub response: CoAPResponse,
}

pub trait CoAPHandler: Sync + Send + Copy {
    fn handle(&self, CoAPRequest) -> Option<CoAPResponse>;
}

impl<F> CoAPHandler for F
    where F: Fn(CoAPRequest) -> Option<CoAPResponse>,
          F: Sync + Send + Copy
{
    fn handle(&self, request: CoAPRequest) -> Option<CoAPResponse> {
        return self(request);
    }
}

struct UdpHandler<H: CoAPHandler + 'static> {
    socket: UdpSocket,
    thread_pool: ThreadPool,
    tx_sender: TxQueue,
    coap_handler: H,
}

impl<H: CoAPHandler + 'static> UdpHandler<H> {
    fn new(socket: UdpSocket,
           thread_pool: ThreadPool,
           tx_sender: TxQueue,
           coap_handler: H)
           -> UdpHandler<H> {
        UdpHandler {
            socket: socket,
            thread_pool: thread_pool,
            tx_sender: tx_sender,
            coap_handler: coap_handler,
        }
    }
}

impl<H: CoAPHandler + 'static> Handler for UdpHandler<H> {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, _: &mut EventLoop<UdpHandler<H>>, _: Token, events: EventSet) {
        if !events.is_readable() {
            warn!("Unreadable Event");
            return;
        }

        let coap_handler = self.coap_handler;
        let mut buf = [0; 1500];

        match self.socket.recv_from(&mut buf) {
            Ok(Some((nread, src))) => {
                debug!("Handling request from {}", src);
                let response_q = self.tx_sender.clone();

                self.thread_pool.execute(move || {
                    match Packet::from_bytes(&buf[..nread]) {
                        Ok(packet) => {
                            // Dispatch user handler, if there is a response packet
                            //   send the reply via the TX thread
                            let rqst = CoAPRequest::from_packet(packet, &src);
                            match coap_handler.handle(rqst) {
                                Some(response) => {
                                    debug!("Response: {:?}", response);
                                    response_q.send(QueuedResponse {
                                            address: src,
                                            response: response,
                                        })
                                        .unwrap();
                                }
                                None => {
                                    debug!("No response");
                                }
                            };
                        }
                        Err(_) => {
                            error!("Failed to parse request");
                            return;
                        }
                    };
                });
            }
            _ => {
                error!("Failed to read from socket");
                panic!("unexpected error");
            }
        }

    }

    fn notify(&mut self, event_loop: &mut EventLoop<UdpHandler<H>>, _: ()) {
        info!("Shutting down request handler");
        event_loop.shutdown();
    }
}

pub struct CoAPServer {
    socket: UdpSocket,
    event_sender: Option<Sender<()>>,
    event_thread: Option<thread::JoinHandle<()>>,
    tx_thread: Option<thread::JoinHandle<()>>,
    worker_num: usize,
}

impl CoAPServer {
    /// Creates a CoAP server listening on the given address.
    pub fn new<A: ToSocketAddrs>(addr: A) -> std::io::Result<CoAPServer> {
        addr.to_socket_addrs().and_then(|mut iter| {
            match iter.next() {
                Some(ad) => {
                    UdpSocket::bound(&ad).and_then(|s| {
                        Ok(CoAPServer {
                            socket: s,
                            event_sender: None,
                            event_thread: None,
                            tx_thread: None,
                            worker_num: DEFAULT_WORKER_NUM,
                        })
                    })
                }
                None => Err(Error::new(ErrorKind::Other, "no address")),
            }
        })
    }

    /// Starts handling requests with the handler
    pub fn handle<H: CoAPHandler + 'static>(&mut self, handler: H) -> Result<(), CoAPServerError> {
        let socket;

        // Early return error checking
        if let Some(_) = self.event_sender {
            error!("Handler already running!");
            return Err(CoAPServerError::AnotherHandlerIsRunning);
        }
        match self.socket.try_clone() {
            Ok(good_socket) => socket = good_socket,
            Err(_) => {
                error!("Network Error!");
                return Err(CoAPServerError::NetworkError);
            }
        }

        // Create resources
        let worker_num = self.worker_num;
        let (tx, rx) = mpsc::channel();
        let (tx_send, tx_recv): (TxQueue, RxQueue) = mpsc::channel();
        let tx_only = self.socket.try_clone().unwrap();

        // Setup and spawn single TX thread
        let tx_thread = thread::spawn(move || {
            transmit_handler(tx_recv, tx_only);
        });

        // Setup and spawn event loop thread, which will spawn
        //   children threads which handle incomining requests
        let thread = thread::spawn(move || {
            let thread_pool = ThreadPool::new(worker_num);
            let mut event_loop = EventLoop::new().unwrap();
            event_loop.register(&socket, Token(0), EventSet::readable(), PollOpt::edge()).unwrap();

            tx.send(event_loop.channel()).unwrap();

            event_loop.run(&mut UdpHandler::new(socket, thread_pool, tx_send, handler)).unwrap();
        });

        // Ensure threads started successfully
        match rx.recv() {
            Ok(event_sender) => {
                self.event_sender = Some(event_sender);
                self.event_thread = Some(thread);
                self.tx_thread = Some(tx_thread);
                Ok(())
            }
            Err(_) => Err(CoAPServerError::EventLoopError),
        }
    }

    /// Stop the server.
    pub fn stop(&mut self) {
        let event_sender = self.event_sender.take();
        match event_sender {
            Some(ref sender) => {
                sender.send(()).unwrap();
                self.event_thread.take().map(|g| g.join());
            }
            _ => {}
        }
    }

    /// Set the number of threads for handling requests
    pub fn set_worker_num(&mut self, worker_num: usize) {
        self.worker_num = worker_num;
    }
}

fn transmit_handler(tx_recv: RxQueue, tx_only: UdpSocket) {
    // Note! We should only transmit with this UDP Socket
    // TODO: Add better support for failure detection or logging
    loop {
        match tx_recv.recv() {
            Ok(q_res) => {
                match q_res.response.message.to_bytes() {
                    Ok(bytes) => {
                        let _ = tx_only.send_to(&bytes[..], &q_res.address);
                    }
                    Err(_) => {
                        error!("Failed to decode response");
                    }
                }
            }
            // recv error occurs when all transmitters are terminited
            //   (when all UDP Handlers are closed)
            Err(_) => {
                info!("Shutting down Transmit Handler");
                break;
            }
        }
    }
}

impl Drop for CoAPServer {
    fn drop(&mut self) {
        self.stop();
    }
}

#[cfg(test)]
mod test {
    use client::CoAPClient;
    use message::header;
    use message::IsMessage;
    use message::packet::CoAPOption;
    use message::request::CoAPRequest;
    use message::response::CoAPResponse;
    use super::*;

    fn request_handler(req: CoAPRequest) -> Option<CoAPResponse> {
        let uri_path_list = req.get_option(CoAPOption::UriPath).unwrap();
        assert!(uri_path_list.len() == 1);

        match req.response {
            Some(mut response) => {
                response.set_payload(uri_path_list.front().unwrap().clone());
                Some(response)
            }
            _ => None,
        }
    }

    #[test]
    fn test_echo_server() {
        let mut server = CoAPServer::new("127.0.0.1:5683").unwrap();
        server.handle(request_handler).unwrap();

        let client = CoAPClient::new("127.0.0.1:5683").unwrap();
        let mut request = CoAPRequest::new();
        request.set_version(1);
        request.set_type(header::MessageType::Confirmable);
        request.set_code("0.01");
        request.set_message_id(1);
        request.set_token(vec![0x51, 0x55, 0x77, 0xE8]);
        request.add_option(CoAPOption::UriPath, b"test-echo".to_vec());
        client.send(&request).unwrap();

        let recv_packet = client.receive().unwrap();
        assert_eq!(recv_packet.message.payload, b"test-echo".to_vec());
    }

    #[test]
    fn test_echo_server_no_token() {
        let mut server = CoAPServer::new("127.0.0.1:5685").unwrap();
        server.handle(request_handler).unwrap();

        let client = CoAPClient::new("127.0.0.1:5685").unwrap();
        let mut packet = CoAPRequest::new();
        packet.set_version(1);
        packet.set_type(header::MessageType::Confirmable);
        packet.set_code("0.01");
        packet.set_message_id(1);
        packet.add_option(CoAPOption::UriPath, b"test-echo".to_vec());
        client.send(&packet).unwrap();

        let recv_packet = client.receive().unwrap();
        assert_eq!(recv_packet.message.payload, b"test-echo".to_vec());
    }
}
<commit_msg>put the response back in the queue when socket needs to wait<commit_after>use std;
use std::io::{Error, ErrorKind};
use std::thread;
use std::net::{ToSocketAddrs, SocketAddr};
use std::sync::mpsc;
use mio::{EventLoop, PollOpt, EventSet, Handler, Sender, Token};
use mio::udp::UdpSocket;
use message::packet::Packet;
use message::request::CoAPRequest;
use message::response::CoAPResponse;
use threadpool::ThreadPool;

const DEFAULT_WORKER_NUM: usize = 4;
type TxQueue = mpsc::Sender<QueuedResponse>;
type RxQueue = mpsc::Receiver<QueuedResponse>;

#[derive(Debug)]
pub enum CoAPServerError {
    NetworkError,
    EventLoopError,
    AnotherHandlerIsRunning,
}

#[derive(Debug)]
struct QueuedResponse {
    pub address: SocketAddr,
    pub response: CoAPResponse,
}

pub trait CoAPHandler: Sync + Send + Copy {
    fn handle(&self, CoAPRequest) -> Option<CoAPResponse>;
}

impl<F> CoAPHandler for F
    where F: Fn(CoAPRequest) -> Option<CoAPResponse>,
          F: Sync + Send + Copy
{
    fn handle(&self, request: CoAPRequest) -> Option<CoAPResponse> {
        return self(request);
    }
}

struct UdpHandler<H: CoAPHandler + 'static> {
    socket: UdpSocket,
    thread_pool: ThreadPool,
    tx_sender: TxQueue,
    coap_handler: H,
}

impl<H: CoAPHandler + 'static> UdpHandler<H> {
    fn new(socket: UdpSocket,
           thread_pool: ThreadPool,
           tx_sender: TxQueue,
           coap_handler: H)
           -> UdpHandler<H> {
        UdpHandler {
            socket: socket,
            thread_pool: thread_pool,
            tx_sender: tx_sender,
            coap_handler: coap_handler,
        }
    }
}

impl<H: CoAPHandler + 'static> Handler for UdpHandler<H> {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, _: &mut EventLoop<UdpHandler<H>>, _: Token, events: EventSet) {
        if !events.is_readable() {
            warn!("Unreadable Event");
            return;
        }

        let coap_handler = self.coap_handler;
        let mut buf = [0; 1500];

        match self.socket.recv_from(&mut buf) {
            Ok(Some((nread, src))) => {
                debug!("Handling request from {}", src);
                let response_q = self.tx_sender.clone();

                self.thread_pool.execute(move || {
                    match Packet::from_bytes(&buf[..nread]) {
                        Ok(packet) => {
                            // Dispatch user handler, if there is a response packet
                            //   send the reply via the TX thread
                            let rqst = CoAPRequest::from_packet(packet, &src);
                            match coap_handler.handle(rqst) {
                                Some(response) => {
                                    debug!("Response: {:?}", response);
                                    response_q.send(QueuedResponse {
                                            address: src,
                                            response: response,
                                        })
                                        .unwrap();
                                }
                                None => {
                                    debug!("No response");
                                }
                            };
                        }
                        Err(_) => {
                            error!("Failed to parse request");
                            return;
                        }
                    };
                });
            }
            _ => {
                error!("Failed to read from socket");
                panic!("unexpected error");
            }
        }

    }

    fn notify(&mut self, event_loop: &mut EventLoop<UdpHandler<H>>, _: ()) {
        info!("Shutting down request handler");
        event_loop.shutdown();
    }
}

pub struct CoAPServer {
    socket: UdpSocket,
    event_sender: Option<Sender<()>>,
    event_thread: Option<thread::JoinHandle<()>>,
    tx_thread: Option<thread::JoinHandle<()>>,
    worker_num: usize,
}

impl CoAPServer {
    /// Creates a CoAP server listening on the given address.
    pub fn new<A: ToSocketAddrs>(addr: A) -> std::io::Result<CoAPServer> {
        addr.to_socket_addrs().and_then(|mut iter| {
            match iter.next() {
                Some(ad) => {
                    UdpSocket::bound(&ad).and_then(|s| {
                        Ok(CoAPServer {
                            socket: s,
                            event_sender: None,
                            event_thread: None,
                            tx_thread: None,
                            worker_num: DEFAULT_WORKER_NUM,
                        })
                    })
                }
                None => Err(Error::new(ErrorKind::Other, "no address")),
            }
        })
    }

    /// Starts handling requests with the handler
    pub fn handle<H: CoAPHandler + 'static>(&mut self, handler: H) -> Result<(), CoAPServerError> {
        let socket;

        // Early return error checking
        if let Some(_) = self.event_sender {
            error!("Handler already running!");
            return Err(CoAPServerError::AnotherHandlerIsRunning);
        }
        match self.socket.try_clone() {
            Ok(good_socket) => socket = good_socket,
            Err(_) => {
                error!("Network Error!");
                return Err(CoAPServerError::NetworkError);
            }
        }

        // Create resources
        let worker_num = self.worker_num;
        let (tx, rx) = mpsc::channel();
        let (tx_send, tx_recv): (TxQueue, RxQueue) = mpsc::channel();
        let tx_only = self.socket.try_clone().unwrap();
        let tx_send2 = tx_send.clone();

        // Setup and spawn single TX thread
        let tx_thread = thread::spawn(move || {
            transmit_handler(tx_send2, tx_recv, tx_only);
        });

        // Setup and spawn event loop thread, which will spawn
        //   children threads which handle incomining requests
        let thread = thread::spawn(move || {
            let thread_pool = ThreadPool::new(worker_num);
            let mut event_loop = EventLoop::new().unwrap();
            event_loop.register(&socket, Token(0), EventSet::readable(), PollOpt::edge()).unwrap();

            tx.send(event_loop.channel()).unwrap();

            event_loop.run(&mut UdpHandler::new(socket, thread_pool, tx_send, handler)).unwrap();
        });

        // Ensure threads started successfully
        match rx.recv() {
            Ok(event_sender) => {
                self.event_sender = Some(event_sender);
                self.event_thread = Some(thread);
                self.tx_thread = Some(tx_thread);
                Ok(())
            }
            Err(_) => Err(CoAPServerError::EventLoopError),
        }
    }

    /// Stop the server.
    pub fn stop(&mut self) {
        let event_sender = self.event_sender.take();
        match event_sender {
            Some(ref sender) => {
                sender.send(()).unwrap();
                self.event_thread.take().map(|g| g.join());
            }
            _ => {}
        }
    }

    /// Set the number of threads for handling requests
    pub fn set_worker_num(&mut self, worker_num: usize) {
        self.worker_num = worker_num;
    }
}

fn transmit_handler(tx_send: TxQueue, tx_recv: RxQueue, tx_only: UdpSocket) {
    // Note! We should only transmit with this UDP Socket
    // TODO: Add better support for failure detection or logging
    loop {
        match tx_recv.recv() {
            Ok(q_res) => {
                match q_res.response.message.to_bytes() {
                    Ok(bytes) => {
                        match tx_only.send_to(&bytes[..], &q_res.address) {
                            Ok(None) => {
                                // try to send again, look at https://github.com/Covertness/coap-rs/issues/8 in detail
                                tx_send.send(q_res).unwrap()
                            }
                            Ok(_) => {
                                continue;
                            }
                            Err(_) => {
                                error!("Failed to send response");
                            }
                         }
                    }
                    Err(_) => {
                        error!("Failed to decode response");
                    }
                }
            }
            // recv error occurs when all transmitters are terminited
            //   (when all UDP Handlers are closed)
            Err(_) => {
                info!("Shutting down Transmit Handler");
                break;
            }
        }
    }
}

impl Drop for CoAPServer {
    fn drop(&mut self) {
        self.stop();
    }
}

#[cfg(test)]
mod test {
    use client::CoAPClient;
    use message::header;
    use message::IsMessage;
    use message::packet::CoAPOption;
    use message::request::CoAPRequest;
    use message::response::CoAPResponse;
    use super::*;

    fn request_handler(req: CoAPRequest) -> Option<CoAPResponse> {
        let uri_path_list = req.get_option(CoAPOption::UriPath).unwrap();
        assert!(uri_path_list.len() == 1);

        match req.response {
            Some(mut response) => {
                response.set_payload(uri_path_list.front().unwrap().clone());
                Some(response)
            }
            _ => None,
        }
    }

    #[test]
    fn test_echo_server() {
        let mut server = CoAPServer::new("127.0.0.1:5683").unwrap();
        server.handle(request_handler).unwrap();

        let client = CoAPClient::new("127.0.0.1:5683").unwrap();
        let mut request = CoAPRequest::new();
        request.set_version(1);
        request.set_type(header::MessageType::Confirmable);
        request.set_code("0.01");
        request.set_message_id(1);
        request.set_token(vec![0x51, 0x55, 0x77, 0xE8]);
        request.add_option(CoAPOption::UriPath, b"test-echo".to_vec());
        client.send(&request).unwrap();

        let recv_packet = client.receive().unwrap();
        assert_eq!(recv_packet.message.payload, b"test-echo".to_vec());
    }

    #[test]
    fn test_echo_server_no_token() {
        let mut server = CoAPServer::new("127.0.0.1:5685").unwrap();
        server.handle(request_handler).unwrap();

        let client = CoAPClient::new("127.0.0.1:5685").unwrap();
        let mut packet = CoAPRequest::new();
        packet.set_version(1);
        packet.set_type(header::MessageType::Confirmable);
        packet.set_code("0.01");
        packet.set_message_id(1);
        packet.add_option(CoAPOption::UriPath, b"test-echo".to_vec());
        client.send(&packet).unwrap();

        let recv_packet = client.receive().unwrap();
        assert_eq!(recv_packet.message.payload, b"test-echo".to_vec());
    }
}
<|endoftext|>


<commit_before>#[warn(unused_must_use)]

// copied mostly from public domain https://github.com/zmack/rust-socks/blob/master/src/server.rs
extern crate byteorder;
extern crate webextension_protocol as protocol;

use std::thread;
use std::time::Duration;
use std::io::Write;
use std::net::{TcpStream, Shutdown};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::lookup_host;
use std::io::{Error, copy};
use std::sync::mpsc::{Sender};
use std::convert::AsRef;

use helpers;

use std::io::Read;

use server::byteorder::{BigEndian, ReadBytesExt};

#[allow(dead_code)]
enum RocksError {
    Io(Error),
    Generic(String)
}

pub struct SocksServer {
    tcp_stream: TcpStream,
    sender: Sender<(Sender<String>, String)>,
}

impl SocksServer {

    #[allow(unused_must_use)]
    pub fn new(tcp_stream: TcpStream, sender: Sender<(Sender<String>, String)>) {
        let mut server = SocksServer {
            tcp_stream: tcp_stream,
            sender: sender,
        };
        server.handle_client();
    }

    #[allow(unused_must_use)]
    fn handle_client(&mut self) -> Result<(), RocksError> {
        loop {
            let version = match self.tcp_stream.read_u8() {
                Ok(v) => v ,
                _ => break,
            };
            if version == 5 {
                println_stderr!("wrong protocol version");
                let num_methods = self.tcp_stream.read_u8().unwrap();
                let mut methods = Vec::with_capacity(num_methods as usize);
                unsafe { methods.set_len(num_methods as usize) };
                self.tcp_stream.read_exact(&mut methods).unwrap();
                println_stderr!("num_methods is {:?}, methods is {:?}", num_methods, methods);
                if methods.contains(&2) {
                    // Authenticated
                    self.tcp_stream.write(&[5, 2]);
                    //self.authenticate().unwrap()
                } else {
                    // Unauthenticated
                    self.tcp_stream.write(&[5, 0]);
                }
                //
            } else {
                drop(&self.tcp_stream);
                println_stderr!("wrong protocol version");
                break
            }

            let v1 = self.tcp_stream.read_u8().unwrap();
            let c = self.tcp_stream.read_u8().unwrap();
            let res = self.tcp_stream.read_u8().unwrap();
            let addr_type = self.tcp_stream.read_u8().unwrap();

            println_stderr!("v1 is {:?}", v1);
            println_stderr!("c is {:?}", c);
            println_stderr!("res is {:?}", res);
            println_stderr!("Address type is {:?}", addr_type);
            let addr = self.get_remote_addr(addr_type).unwrap();

            println_stderr!("Address is {:?}", addr);

            let msg = helpers::js_message("getBlock".to_string(), "\"".to_string()+addr.to_string().as_str()+"\"");
            let response = helpers::send_sync(self.sender.clone(), msg);

            println_stderr!("jsengine response {}", response);

            match response.as_ref() {
                "false" => {
                },
                "true" => {
                    drop(&self.tcp_stream);
                    break;
                },
                _ => {},
            }

            println_stderr!("got a connection");
            let outbound = TcpStream::connect(addr).unwrap();
            outbound.set_read_timeout(Some(Duration::from_secs(5))).unwrap();

            self.tcp_stream.write(&[5, 0, 0, 1, 127, 0, 0, 1, 0, 0]).unwrap();
            println_stderr!("Wrote things");

            let mut client_reader = self.tcp_stream.try_clone().unwrap();
            let mut client_writer = self.tcp_stream.try_clone().unwrap();
            let mut socket_reader = outbound.try_clone().unwrap();
            let mut socket_writer = outbound.try_clone().unwrap();

            thread::spawn(move || {
                copy(&mut client_reader, &mut socket_writer);
                client_reader.shutdown(Shutdown::Read);
                socket_writer.shutdown(Shutdown::Write);
            });

            copy(&mut socket_reader, &mut client_writer);
            socket_reader.shutdown(Shutdown::Read);
            client_writer.shutdown(Shutdown::Write);
        }

        return Ok(())
    }

    #[allow(unused_must_use)]
    fn get_remote_addr(&mut self, addr_type: u8) -> Result<SocketAddr, String> {
        match addr_type {
            1 => {
                let mut ip_bytes = [0u8; 4];
                self.tcp_stream.read_exact(&mut ip_bytes);
                let ip = Ipv4Addr::from(ip_bytes);
                let port = self.tcp_stream.read_u16::<BigEndian>().unwrap();

                return Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)));
            },
            3 => {
                let num_str = self.tcp_stream.read_u8().unwrap();
                let mut hostname_vec = Vec::with_capacity(num_str as usize);
                unsafe { hostname_vec.set_len(num_str as usize) };
                self.tcp_stream.read_exact(&mut hostname_vec).unwrap();
                let port = self.tcp_stream.read_u16::<BigEndian>().unwrap();

                let hostname = match String::from_utf8(hostname_vec) { Ok(s) => s, _ => "".to_string() };
                let address = self.resolve_addr_with_cache(&hostname);

                if address.is_none() {
                    return Err(From::from("Empty Address".to_string()))
                } else {
                    // println!("Resolution succeeded for {?} - {?}", hostname, addresses);
                    let mut address = address.unwrap();
                    address.set_port(port);
                    return Ok(address);
                }
            },
            _ => return Err(From::from("Invalid Address Type".to_string()))
        }
    }

    fn resolve_addr_with_cache(&self, hostname: &str) -> Option<SocketAddr> {
        match lookup_host(&hostname) {
            Ok(mut a) => { a.nth(0) },
            _ => { None }
        }
    }
}
<commit_msg>Copying rust std::io::copy - to be replaced in future<commit_after>#[warn(unused_must_use)]

// copied mostly from public domain https://github.com/zmack/rust-socks/blob/master/src/server.rs
extern crate byteorder;
extern crate webextension_protocol as protocol;

use std::thread;
use std::time::Duration;
use std::io::Write;
use std::net::{TcpStream, Shutdown};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::net::lookup_host;
use std::io::{Error,ErrorKind};
use std::io;
use std::sync::mpsc::{Sender};
use std::convert::AsRef;
use helpers;

use std::io::Read;

use server::byteorder::{BigEndian, ReadBytesExt};

pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = [0; 8*1024];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

#[allow(dead_code)]
enum RocksError {
    Io(Error),
    Generic(String)
}

pub struct SocksServer {
    tcp_stream: TcpStream,
    sender: Sender<(Sender<String>, String)>,
}

impl SocksServer {

    #[allow(unused_must_use)]
    pub fn new(tcp_stream: TcpStream, sender: Sender<(Sender<String>, String)>) {
        let mut server = SocksServer {
            tcp_stream: tcp_stream,
            sender: sender,
        };
        server.handle_client();
    }

    #[allow(unused_must_use)]
    fn handle_client(&mut self) -> Result<(), RocksError> {
        loop {
            let version = match self.tcp_stream.read_u8() {
                Ok(v) => v ,
                _ => break,
            };
            if version == 5 {
                println_stderr!("wrong protocol version");
                let num_methods = self.tcp_stream.read_u8().unwrap();
                let mut methods = Vec::with_capacity(num_methods as usize);
                unsafe { methods.set_len(num_methods as usize) };
                self.tcp_stream.read_exact(&mut methods).unwrap();
                println_stderr!("num_methods is {:?}, methods is {:?}", num_methods, methods);
                if methods.contains(&2) {
                    // Authenticated
                    self.tcp_stream.write(&[5, 2]);
                    //self.authenticate().unwrap()
                } else {
                    // Unauthenticated
                    self.tcp_stream.write(&[5, 0]);
                }
                //
            } else {
                drop(&self.tcp_stream);
                println_stderr!("wrong protocol version");
                break
            }

            let v1 = self.tcp_stream.read_u8().unwrap();
            let c = self.tcp_stream.read_u8().unwrap();
            let res = self.tcp_stream.read_u8().unwrap();
            let addr_type = self.tcp_stream.read_u8().unwrap();

            println_stderr!("v1 is {:?}", v1);
            println_stderr!("c is {:?}", c);
            println_stderr!("res is {:?}", res);
            println_stderr!("Address type is {:?}", addr_type);
            let addr = self.get_remote_addr(addr_type).unwrap();

            println_stderr!("Address is {:?}", addr);

            let msg = helpers::js_message("getBlock".to_string(), "\"".to_string()+addr.to_string().as_str()+"\"");
            let response = helpers::send_sync(self.sender.clone(), msg);

            println_stderr!("jsengine response {}", response);

            match response.as_ref() {
                "false" => {
                },
                "true" => {
                    drop(&self.tcp_stream);
                    break;
                },
                _ => {},
            }

            println_stderr!("got a connection");
            let outbound = TcpStream::connect(addr).unwrap();
            outbound.set_read_timeout(Some(Duration::from_secs(5))).unwrap();

            self.tcp_stream.write(&[5, 0, 0, 1, 127, 0, 0, 1, 0, 0]).unwrap();
            println_stderr!("Wrote things");

            let mut client_reader = self.tcp_stream.try_clone().unwrap();
            let mut client_writer = self.tcp_stream.try_clone().unwrap();
            let mut socket_reader = outbound.try_clone().unwrap();
            let mut socket_writer = outbound.try_clone().unwrap();

            thread::spawn(move || {
                copy(&mut client_reader, &mut socket_writer);
                client_reader.shutdown(Shutdown::Read);
                socket_writer.shutdown(Shutdown::Write);
            });

            copy(&mut socket_reader, &mut client_writer);
            socket_reader.shutdown(Shutdown::Read);
            client_writer.shutdown(Shutdown::Write);
        }

        return Ok(())
    }

    #[allow(unused_must_use)]
    fn get_remote_addr(&mut self, addr_type: u8) -> Result<SocketAddr, String> {
        match addr_type {
            1 => {
                let mut ip_bytes = [0u8; 4];
                self.tcp_stream.read_exact(&mut ip_bytes);
                let ip = Ipv4Addr::from(ip_bytes);
                let port = self.tcp_stream.read_u16::<BigEndian>().unwrap();

                return Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)));
            },
            3 => {
                let num_str = self.tcp_stream.read_u8().unwrap();
                let mut hostname_vec = Vec::with_capacity(num_str as usize);
                unsafe { hostname_vec.set_len(num_str as usize) };
                self.tcp_stream.read_exact(&mut hostname_vec).unwrap();
                let port = self.tcp_stream.read_u16::<BigEndian>().unwrap();

                let hostname = match String::from_utf8(hostname_vec) { Ok(s) => s, _ => "".to_string() };
                let address = self.resolve_addr_with_cache(&hostname);

                if address.is_none() {
                    return Err(From::from("Empty Address".to_string()))
                } else {
                    // println!("Resolution succeeded for {?} - {?}", hostname, addresses);
                    let mut address = address.unwrap();
                    address.set_port(port);
                    return Ok(address);
                }
            },
            _ => return Err(From::from("Invalid Address Type".to_string()))
        }
    }

    fn resolve_addr_with_cache(&self, hostname: &str) -> Option<SocketAddr> {
        match lookup_host(&hostname) {
            Ok(mut a) => { a.nth(0) },
            _ => { None }
        }
    }
}
<|endoftext|>


<commit_before>//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period
//! of time.
//!
//! * `Sleep` is a future that does no work and completes at a specific `Instant`
//!   in time.
//!
//! * `Interval` is a stream yielding a value at a fixed period. It is
//!   initialized with a `Duration` and repeatedly yields each time the duration
//!   elapses.
//!
//! * `Timeout`: Wraps a future or stream, setting an upper bound to the amount
//!   of time it is allowed to execute. If the future or stream does not
//!   complete in time, then it is canceled and an error is returned.
//!
//! These types are sufficient for handling a large number of scenarios
//! involving time.
//!
//! These types must be used from within the context of the `Runtime`.
//!
//! # Examples
//!
//! Wait 100ms and print "100 ms have elapsed"
//!
//! ```
//! use tokio::time::sleep;
//!
//! use std::time::Duration;
//!
//!
//! #[tokio::main]
//! async fn main() {
//!     sleep(Duration::from_millis(100)).await;
//!     println!("100 ms have elapsed");
//! }
//! ```
//!
//! Require that an operation takes no more than 300ms.
//!
//! ```
//! use tokio::time::{timeout, Duration};
//!
//! async fn long_future() {
//!     // do work here
//! }
//!
//! # async fn dox() {
//! let res = timeout(Duration::from_secs(1), long_future()).await;
//!
//! if res.is_err() {
//!     println!("operation timed out");
//! }
//! # }
//! ```
//!
//! A simple example using [`interval`] to execute a task every two seconds.
//!
//! The difference between [`interval`] and [`sleep`] is that an [`interval`]
//! measures the time since the last tick, which means that `.tick().await`
//! may wait for a shorter time than the duration specified for the interval
//! if some time has passed between calls to `.tick().await`.
//!
//! If the tick in the example below was replaced with [`sleep`], the task
//! would only be executed once every three seconds, and not every two
//! seconds.
//!
//! ```
//! use tokio::time;
//!
//! async fn task_that_takes_a_second() {
//!     println!("hello");
//!     time::sleep(time::Duration::from_secs(1)).await
//! }
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut interval = time::interval(time::Duration::from_secs(2));
//!     for _i in 0..5 {
//!         interval.tick().await;
//!         task_that_takes_a_second().await;
//!     }
//! }
//! ```
//!
//! [`sleep`]: crate::time::sleep()
//! [`interval`]: crate::time::interval()

mod clock;
pub(crate) use self::clock::Clock;
#[cfg(feature = "test-util")]
pub use clock::{advance, pause, resume};

pub(crate) mod driver;

#[doc(inline)]
pub use driver::sleep::{sleep, sleep_until, Sleep};

pub mod error;

mod instant;
pub use self::instant::Instant;

mod interval;
pub use interval::{interval, interval_at, Interval};

mod timeout;
#[doc(inline)]
pub use timeout::{timeout, timeout_at, Timeout};

#[cfg(test)]
#[cfg(not(loom))]
mod tests;

// Re-export for convenience
#[doc(no_inline)]
pub use std::time::Duration;
<commit_msg>timer: fix double newline in module docs (#3617)<commit_after>//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period
//! of time.
//!
//! * `Sleep` is a future that does no work and completes at a specific `Instant`
//!   in time.
//!
//! * `Interval` is a stream yielding a value at a fixed period. It is
//!   initialized with a `Duration` and repeatedly yields each time the duration
//!   elapses.
//!
//! * `Timeout`: Wraps a future or stream, setting an upper bound to the amount
//!   of time it is allowed to execute. If the future or stream does not
//!   complete in time, then it is canceled and an error is returned.
//!
//! These types are sufficient for handling a large number of scenarios
//! involving time.
//!
//! These types must be used from within the context of the `Runtime`.
//!
//! # Examples
//!
//! Wait 100ms and print "100 ms have elapsed"
//!
//! ```
//! use std::time::Duration;
//! use tokio::time::sleep;
//!
//! #[tokio::main]
//! async fn main() {
//!     sleep(Duration::from_millis(100)).await;
//!     println!("100 ms have elapsed");
//! }
//! ```
//!
//! Require that an operation takes no more than 300ms.
//!
//! ```
//! use tokio::time::{timeout, Duration};
//!
//! async fn long_future() {
//!     // do work here
//! }
//!
//! # async fn dox() {
//! let res = timeout(Duration::from_secs(1), long_future()).await;
//!
//! if res.is_err() {
//!     println!("operation timed out");
//! }
//! # }
//! ```
//!
//! A simple example using [`interval`] to execute a task every two seconds.
//!
//! The difference between [`interval`] and [`sleep`] is that an [`interval`]
//! measures the time since the last tick, which means that `.tick().await`
//! may wait for a shorter time than the duration specified for the interval
//! if some time has passed between calls to `.tick().await`.
//!
//! If the tick in the example below was replaced with [`sleep`], the task
//! would only be executed once every three seconds, and not every two
//! seconds.
//!
//! ```
//! use tokio::time;
//!
//! async fn task_that_takes_a_second() {
//!     println!("hello");
//!     time::sleep(time::Duration::from_secs(1)).await
//! }
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut interval = time::interval(time::Duration::from_secs(2));
//!     for _i in 0..5 {
//!         interval.tick().await;
//!         task_that_takes_a_second().await;
//!     }
//! }
//! ```
//!
//! [`sleep`]: crate::time::sleep()
//! [`interval`]: crate::time::interval()

mod clock;
pub(crate) use self::clock::Clock;
#[cfg(feature = "test-util")]
pub use clock::{advance, pause, resume};

pub(crate) mod driver;

#[doc(inline)]
pub use driver::sleep::{sleep, sleep_until, Sleep};

pub mod error;

mod instant;
pub use self::instant::Instant;

mod interval;
pub use interval::{interval, interval_at, Interval};

mod timeout;
#[doc(inline)]
pub use timeout::{timeout, timeout_at, Timeout};

#[cfg(test)]
#[cfg(not(loom))]
mod tests;

// Re-export for convenience
#[doc(no_inline)]
pub use std::time::Duration;
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::iter;

pub trait Shrink {
    type Item;
    type Iterator: Iterator<Item=Self::Item>;

    fn shrink(value: &Self::Item) -> Self::Iterator;
}

pub struct Empty<T>(PhantomData<T>);

impl <T> Empty<T> {
    pub fn empty() -> Self { Empty(PhantomData) }
}

impl <T> Shrink for Empty<T> {
    type Item = T;
    type Iterator = iter::Empty<T>;

    fn shrink(_: &Self::Item) -> Self::Iterator {
        iter::empty()
    }
}

macro_rules! tuple_impls {
    ($first:ident $(, $rest:ident)*) => {
        impl <$first: 'static + Shrink $(, $rest: 'static + Shrink)*> Shrink for ($first, $($rest),*)
            where $first::Item: Clone $(, $rest::Item: Clone)*
        {
            type Item = ($first::Item, $($rest::Item),*);
            type Iterator = Box<Iterator<Item=Self::Item>>;

            #[inline]
            #[allow(unused_variables, non_snake_case)]
            fn shrink(value: &Self::Item) -> Self::Iterator {
                let ( ref $first, $(ref $rest),*) = *value;
                let t_rest: ($($rest::Item,)*) = ($($rest.clone(),)*);

                Box::new(
                    <$first as Shrink>::shrink($first)
                        .scan(t_rest.clone(), |rest, $first| {
                            let ($($rest,)*) = rest.clone();
                            Some(($first, $($rest),*))
                        })
                        .chain(
                            <($($rest,)*) as Shrink>::shrink(&t_rest)
                                .scan($first.clone(), |$first, ($($rest,)*)| {
                                    Some(($first.clone(), $($rest),*))
                                })
                        )
                )
            }
        }
    };
    () => {
        impl Shrink for () {
            type Item = ();
            type Iterator = iter::Empty<()>;

            #[inline]
            fn shrink(_: &()) -> Self::Iterator {
                iter::empty()
            }
        }
    }
}

macro_tuples_impl!{tuple_impls}

pub struct DefaultShrinker<T>(PhantomData<T>);

impl <T> DefaultShrinker<T>
    where DefaultShrinker<T>: Shrink
{
    pub fn new() -> Self { DefaultShrinker(PhantomData) }
}

impl Shrink for DefaultShrinker<bool> {
    type Item = bool;
    type Iterator = Box<Iterator<Item=bool>>;

    fn shrink(value: &bool) -> Self::Iterator {
        match *value {
            true => Box::new(iter::once(false)),
            false => Box::new(iter::empty())
        }
    }
}
<commit_msg>Integer shrink impls.<commit_after>use std::marker::PhantomData;
use std::iter;

pub trait Shrink {
    type Item;
    type Iterator: Iterator<Item=Self::Item>;

    fn shrink(value: &Self::Item) -> Self::Iterator;
}

pub struct Empty<T>(PhantomData<T>);

impl <T> Empty<T> {
    pub fn empty() -> Self { Empty(PhantomData) }
}

impl <T> Shrink for Empty<T> {
    type Item = T;
    type Iterator = iter::Empty<T>;

    fn shrink(_: &Self::Item) -> Self::Iterator {
        iter::empty()
    }
}

macro_rules! tuple_impls {
    ($first:ident $(, $rest:ident)*) => {
        impl <$first: 'static + Shrink $(, $rest: 'static + Shrink)*> Shrink for ($first, $($rest),*)
            where $first::Item: Clone $(, $rest::Item: Clone)*
        {
            type Item = ($first::Item, $($rest::Item),*);
            type Iterator = Box<Iterator<Item=Self::Item>>;

            #[inline]
            #[allow(unused_variables, non_snake_case)]
            fn shrink(value: &Self::Item) -> Self::Iterator {
                let ( ref $first, $(ref $rest),*) = *value;
                let t_rest: ($($rest::Item,)*) = ($($rest.clone(),)*);

                Box::new(
                    <$first as Shrink>::shrink($first)
                        .scan(t_rest.clone(), |rest, $first| {
                            let ($($rest,)*) = rest.clone();
                            Some(($first, $($rest),*))
                        })
                        .chain(
                            <($($rest,)*) as Shrink>::shrink(&t_rest)
                                .scan($first.clone(), |$first, ($($rest,)*)| {
                                    Some(($first.clone(), $($rest),*))
                                })
                        )
                )
            }
        }
    };
    () => {
        impl Shrink for () {
            type Item = ();
            type Iterator = iter::Empty<()>;

            #[inline]
            fn shrink(_: &()) -> Self::Iterator {
                iter::empty()
            }
        }
    }
}

macro_tuples_impl!{tuple_impls}

pub struct IntegerShrinker<T>(PhantomData<T>);

impl <T> IntegerShrinker<T> where IntegerShrinker<T>: Shrink
{
    pub fn new() -> Self { IntegerShrinker(PhantomData) }
}

macro_rules! int_impls {
    ($($ty:ty),*) => {
        $(
            impl Shrink for IntegerShrinker<$ty>
            {
                type Item = $ty;
                type Iterator = Box<Iterator<Item=Self::Item>>;

                #[inline]
                fn shrink(v: &$ty) -> Self::Iterator {
                    let v = *v;
                    let mut initials = vec![0];
                    if v < 0 { initials.push(-v); }
                    initials.push(v/2);
                    let range = 0..(v.abs());
                    if v < 0 {
                        Box::new(
                            initials.into_iter()
                                .chain(range.scan(v, |&mut v, r| Some(v + r)))
                        )
                    } else {
                        Box::new(
                            initials.into_iter()
                                .chain(range.scan(v, |&mut v, r| Some(v - r)))
                        )
                    }
                }
            }
        )*
    }
}

int_impls! { i8, i16, i32, i64, isize }

pub struct DefaultShrinker<T>(PhantomData<T>);

impl <T> DefaultShrinker<T>
    where DefaultShrinker<T>: Shrink
{
    pub fn new() -> Self { DefaultShrinker(PhantomData) }
}

impl Shrink for DefaultShrinker<bool> {
    type Item = bool;
    type Iterator = Box<Iterator<Item=bool>>;

    fn shrink(value: &bool) -> Self::Iterator {
        match *value {
            true => Box::new(iter::once(false)),
            false => Box::new(iter::empty())
        }
    }
}
<|endoftext|>


<commit_before>//! A splittable pseudo-random number generator based on the
//! SipHash function.  **This is not intended to be a
//! cryptographically secure PRNG.**
//!
//! This generator is broadly modeled after Claessen and Pałka's, a
//! version of which is implemented in the Haskell [`tf-random`
//! library](https://hackage.haskell.org/package/tf-random).  Instead
//! of the Skein hash function, however, we use SipHash as the
//! pseudo-random function.
//!
//!
//! ## References
//!
//! * Aumasson, Jean-Philippe and Daniel J. Bernstein.  2012.
//!   ["SipHash: a fast short-input
//!   PRF."](https://eprint.iacr.org/2012/351) Cryptology ePrint
//!   Archive, Report 2012/351.
//! * Claessen, Koen and Michał H. Pałka.  2013.  ["Splittable
//!   Pseudorandom Number Generators using Cryptographic
//!   Hashing."](http://publications.lib.chalmers.se/records/fulltext/183348/local_183348.pdf)
//!   *Haskell '13: Proceedings of the 2013 ACM SIGPLAN symposium on
//!   Haskell*, pp. 47-58.

use rand::{Rand, Rng, SeedableRng};
use super::{SplitRng, SplitPrf};
use std::mem;

/// A splittable pseudorandom generator based on SipHash.
pub struct SipRng {
    v0:  u64,
    v1:  u64,
    v2:  u64,
    v3:  u64,
    ctr: u64,
    len: usize
}

/// A PRF taken off a `SipRng`.
pub struct SipPrf(SipRng);

macro_rules! sipround {
    ($v0: expr, $v1: expr, $v2: expr, $v3: expr) => {
        $v0 = $v0.wrapping_add($v1); $v2 = $v2.wrapping_add($v3);
        $v1 = $v1.rotate_left(13);   $v3 = $v3.rotate_left(16);
        $v1 ^= $v0;                  $v3 ^= $v2;
        $v0 = $v0.rotate_left(32);

        $v2 = $v2.wrapping_add($v1); $v0 = $v0.wrapping_add($v3);
        $v1 = $v1.rotate_left(17);   $v3 = $v3.rotate_left(21);
        $v1 ^= $v2;                  $v3 ^= $v0;
        $v2 = $v0.rotate_left(32);
    }
}

const C0: u64 = 0x736f6d6570736575;
const C1: u64 = 0x646f72616e646f6d;
const C2: u64 = 0x6c7967656e657261;
const C3: u64 = 0x7465646279746573;

impl SipRng {
    /// Create a `SipRng` generator from two `u64`s given as seed.
    pub fn new(k0: u64, k1: u64) -> SipRng {
        SipRng {
            v0:  k0 ^ C0,
            v1:  k1 ^ C1,
            v2:  k0 ^ C2,
            v3:  k1 ^ C3,
            ctr: 0,
            len: 1
        }
    }

    fn clone(&self) -> SipRng {
        SipRng {
            v0:  self.v0,
            v1:  self.v1,
            v2:  self.v2,
            v3:  self.v3,
            ctr: self.ctr,
            len: self.len
        }
    }

    #[inline]
    fn advance(&mut self) {
        self.v3 ^= self.ctr;
        sipround!(self.v0, self.v1, self.v2, self.v3);
        self.v0 ^= self.ctr;
        self.ctr = self.ctr.wrapping_add(1);
        if self.ctr == 0 {
            self.descend(0);
        }
    }

    #[inline]
    fn descend(&mut self, i: u64) {
        self.v3 ^= i;
        sipround!(self.v0, self.v1, self.v2, self.v3);
        self.v0 ^= i;
        self.len = self.len.wrapping_add(1);
        self.ctr = 0;
    }

}

impl SplitPrf<SipRng> for SipPrf {
    fn call(&self, i: u64) -> SipRng {
        let mut r = self.0.clone();
        r.descend(i as u64);
        r
    }
}

impl SplitRng for SipRng {
    type Prf = SipPrf;

    fn split(&mut self) -> Self {
        let mut child = self.clone();
        self.descend(0);
        child.descend(1);
        child
    }

    fn splitn(&mut self) -> SipPrf {
        let child = self.split();
        SipPrf(child)
    }

}

impl Rng for SipRng {
    #[inline]
    fn next_u64(&mut self) -> u64 {
        self.advance();
        let (mut v0, mut v1, mut v2, mut v3) =
            (self.v0, self.v1, self.v2, self.v3);

        let len = (self.len as u64).wrapping_shl(56);
        v3 ^= len;
        sipround!(v0, v1, v2, v3);
        v0 ^= len;

        v2 ^= 0xff;
        sipround!(v0, v1, v2, v3);
        sipround!(v0, v1, v2, v3);
        sipround!(v0, v1, v2, v3);
        v0 ^ v1 ^ v2 ^ v3
    }

    #[inline]
    fn next_u32(&mut self) -> u32 {
        self.next_u64() as u32
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        for chunk in dest.chunks_mut(8) {
            let block = unsafe {
                mem::transmute::<u64, [u8; 8]>(self.next_u64())
            };
            for i in 0..chunk.len() {
                chunk[i] = block[i];
            }
        }
    }
}

impl SeedableRng<(u64, u64)> for SipRng {

    fn reseed(&mut self, seed: (u64, u64)) {
        self.v0 = seed.0 ^ C0;
        self.v1 = seed.1 ^ C1;
        self.v2 = seed.0 ^ C2;
        self.v3 = seed.1 ^ C3;
        self.len = 1;
        self.ctr = 0;
    }

    fn from_seed(seed: (u64, u64)) -> SipRng {
        let (k0, k1) = seed;
        SipRng::new(k0, k1)
    }
}

impl Rand for SipRng {
    fn rand<R: Rng>(other: &mut R) -> SipRng {
        let (k0, k1) = other.gen::<(u64, u64)>();
        SipRng::new(k0, k1)
    }
}

#[cfg(test)]
mod tests {
    use rand::Rng;
    use rand::os::OsRng;
    use siprng::SipRng;

    fn gen_siprng() -> SipRng {
        let mut osrng = OsRng::new().ok().expect("Could not create OsRng");
        osrng.gen()
    }

    #[test]
    fn test_split_rand_independence() {
        ::tests::test_split_rand_independence(&mut gen_siprng());
    }

    #[test]
    fn test_split_rand_closure() {
        ::tests::test_split_rand_closure(&mut gen_siprng());
    }

    #[test]
    fn test_split_rand_split() {
        ::tests::test_split_rand_split(&mut gen_siprng());
    }

    fn gen_seed() -> (u64, u64) {
        let mut osrng = OsRng::new().ok().expect("Could not create OsRng");
        osrng.gen()
    }

    #[test]
    fn test_rng_rand_seeded() {
        let seed = gen_seed();
        ::tests::test_rng_rand_seeded::<SipRng, (u64, u64)>(seed);
    }

    #[test]
    fn test_rng_seeded() {
        let seed = gen_seed();
        ::tests::test_rng_seeded::<SipRng, (u64, u64)>(seed);
    }

    #[test]
    fn test_rng_reseed() {
        let seed = gen_seed();
        ::tests::test_rng_reseed::<SipRng, (u64, u64)>(seed);
    }

}
<commit_msg>Fix some bugs in `SipRng`.<commit_after>//! A splittable pseudo-random number generator based on the
//! SipHash function.  **This is not intended to be a
//! cryptographically secure PRNG.**
//!
//! This generator is broadly modeled after Claessen and Pałka's, a
//! version of which is implemented in the Haskell [`tf-random`
//! library](https://hackage.haskell.org/package/tf-random).  Instead
//! of the Skein hash function, however, we use SipHash as the
//! pseudo-random function.
//!
//!
//! ## References
//!
//! * Aumasson, Jean-Philippe and Daniel J. Bernstein.  2012.
//!   ["SipHash: a fast short-input
//!   PRF."](https://eprint.iacr.org/2012/351) Cryptology ePrint
//!   Archive, Report 2012/351.
//! * Claessen, Koen and Michał H. Pałka.  2013.  ["Splittable
//!   Pseudorandom Number Generators using Cryptographic
//!   Hashing."](http://publications.lib.chalmers.se/records/fulltext/183348/local_183348.pdf)
//!   *Haskell '13: Proceedings of the 2013 ACM SIGPLAN symposium on
//!   Haskell*, pp. 47-58.

use rand::{Rand, Rng, SeedableRng};
use super::{SplitRng, SplitPrf};
use std::{self, mem};

/// A splittable pseudorandom generator based on SipHash.
pub struct SipRng {
    v0:  u64,
    v1:  u64,
    v2:  u64,
    v3:  u64,
    ctr: u64,
    len: u64
}

/// A PRF taken off a `SipRng`.
pub struct SipPrf(SipRng);

/// A round of the SipHash function.
macro_rules! sip_round {
    ($v0: expr, $v1: expr, $v2: expr, $v3: expr) => {
        $v0 = $v0.wrapping_add($v1); $v2 = $v2.wrapping_add($v3);
        $v1 = $v1.rotate_left(13);   $v3 = $v3.rotate_left(16);
        $v1 ^= $v0;                  $v3 ^= $v2;
        $v0 = $v0.rotate_left(32);

        $v2 = $v2.wrapping_add($v1); $v0 = $v0.wrapping_add($v3);
        $v1 = $v1.rotate_left(17);   $v3 = $v3.rotate_left(21);
        $v1 ^= $v2;                  $v3 ^= $v0;
        $v2 = $v0.rotate_left(32);
    }
}

/// Process one block of SipHash.  One block = one `u64`.
macro_rules! sip_block {
    ($v0: expr, $v1: expr, $v2: expr, $v3: expr, $block: expr) => {
        $v3 ^= $block;
        sip_round!($v0, $v1, $v2, $v3);
        $v0 ^= $block;
    }
}

/// Compute the result of SipHash.  `$len` is the amount of data
/// hashed, in bytes.
macro_rules! sip_finish {
    ($v0: expr, $v1: expr, $v2: expr, $v3: expr, $len: expr) => {
        {
            sip_block!($v0, $v1, $v2, $v3, $len.wrapping_shl(56));

            $v2 ^= 0xff;
            sip_round!($v0, $v1, $v2, $v3);
            sip_round!($v0, $v1, $v2, $v3);
            sip_round!($v0, $v1, $v2, $v3);
            $v0 ^ $v1 ^ $v2 ^ $v3
        }
    }
}

const C0: u64 = 0x736f6d6570736575;
const C1: u64 = 0x646f72616e646f6d;
const C2: u64 = 0x6c7967656e657261;
const C3: u64 = 0x7465646279746573;

impl SipRng {
    /// Create a `SipRng` generator from two `u64`s given as seed.
    pub fn new(k0: u64, k1: u64) -> SipRng {
        SipRng {
            v0:  k0 ^ C0,
            v1:  k1 ^ C1,
            v2:  k0 ^ C2,
            v3:  k1 ^ C3,
            ctr: 0,
            len: 1
        }
    }

    fn clone(&self) -> SipRng {
        SipRng {
            v0:  self.v0,
            v1:  self.v1,
            v2:  self.v2,
            v3:  self.v3,
            ctr: self.ctr,
            len: self.len
        }
    }

    /// Generate one block of sequential output.
    #[inline]
    fn advance(&mut self) -> u64 {
        sip_block!(self.v0, self.v1, self.v2, self.v3, self.ctr);
        sip_block!(self.v0, self.v1, self.v2, self.v3, std::u64::MAX);

        self.ctr = self.ctr.wrapping_add(1);
        if self.ctr == 0 {
            self.descend(0);
        }

        let (mut v0, mut v1, mut v2, mut v3) =
            (self.v0, self.v1, self.v2, self.v3);
        sip_finish!(v0, v1, v2, v3, self.len.wrapping_mul(8))
    }

    /// Go into the state for the `i`th branch from this generator
    /// state.  The "descend" name is due to Claessen & Pałka's
    /// exposition of their splittable RNG as a tree; splitting the
    /// generator means descending down one of the tree's branches
    /// (indexed by `i`).
    #[inline]
    fn descend(&mut self, i: u64) {
        sip_block!(self.v0, self.v1, self.v2, self.v3, i);
        sip_block!(self.v0, self.v1, self.v2, self.v3, 0);
        self.len = self.len.wrapping_add(1);
        self.ctr = 0;
    }

}

impl SplitPrf<SipRng> for SipPrf {
    fn call(&self, i: u64) -> SipRng {
        let mut r = self.0.clone();
        r.descend(i as u64);
        r
    }
}

impl SplitRng for SipRng {
    type Prf = SipPrf;

    fn split(&mut self) -> Self {
        let mut child = self.clone();
        self.descend(0);
        child.descend(1);
        child
    }

    fn splitn(&mut self) -> SipPrf {
        let child = self.split();
        SipPrf(child)
    }

}

impl Rng for SipRng {
    #[inline]
    fn next_u64(&mut self) -> u64 {
        self.advance()
    }

    #[inline]
    fn next_u32(&mut self) -> u32 {
        self.next_u64() as u32
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        for chunk in dest.chunks_mut(8) {
            let block = unsafe {
                mem::transmute::<u64, [u8; 8]>(self.next_u64())
            };
            for i in 0..chunk.len() {
                chunk[i] = block[i];
            }
        }
    }
}

impl SeedableRng<(u64, u64)> for SipRng {

    fn reseed(&mut self, seed: (u64, u64)) {
        self.v0 = seed.0 ^ C0;
        self.v1 = seed.1 ^ C1;
        self.v2 = seed.0 ^ C2;
        self.v3 = seed.1 ^ C3;
        self.len = 1;
        self.ctr = 0;
    }

    fn from_seed(seed: (u64, u64)) -> SipRng {
        let (k0, k1) = seed;
        SipRng::new(k0, k1)
    }
}

impl Rand for SipRng {
    fn rand<R: Rng>(other: &mut R) -> SipRng {
        let (k0, k1) = other.gen::<(u64, u64)>();
        SipRng::new(k0, k1)
    }
}

#[cfg(test)]
mod tests {
    use rand::Rng;
    use rand::os::OsRng;
    use siprng::SipRng;

    fn gen_siprng() -> SipRng {
        let mut osrng = OsRng::new().ok().expect("Could not create OsRng");
        osrng.gen()
    }

    #[test]
    fn test_split_rand_independence() {
        ::tests::test_split_rand_independence(&mut gen_siprng());
    }

    #[test]
    fn test_split_rand_closure() {
        ::tests::test_split_rand_closure(&mut gen_siprng());
    }

    #[test]
    fn test_split_rand_split() {
        ::tests::test_split_rand_split(&mut gen_siprng());
    }

    fn gen_seed() -> (u64, u64) {
        let mut osrng = OsRng::new().ok().expect("Could not create OsRng");
        osrng.gen()
    }

    #[test]
    fn test_rng_rand_seeded() {
        let seed = gen_seed();
        ::tests::test_rng_rand_seeded::<SipRng, (u64, u64)>(seed);
    }

    #[test]
    fn test_rng_seeded() {
        let seed = gen_seed();
        ::tests::test_rng_seeded::<SipRng, (u64, u64)>(seed);
    }

    #[test]
    fn test_rng_reseed() {
        let seed = gen_seed();
        ::tests::test_rng_reseed::<SipRng, (u64, u64)>(seed);
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Raspberry Pi system-related tools.
//!
//! Use [`DeviceInfo`] to identify what Raspberry Pi model and SoC the software is
//! running on. This information is used internally to calculate the correct memory
//! locations for the various BCM283x peripherals.
//!
//! [`DeviceInfo`]: struct.DeviceInfo.html

use std::fmt;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::result;

const PERIPHERAL_BASE_RPI: u32 = 0x20_000_000;
const PERIPHERAL_BASE_RPI2: u32 = 0x3f_000_000;
const GPIO_OFFSET: u32 = 0x200_000;

quick_error! {
/// Errors that can occur when trying to identify the Raspberry Pi hardware.
    #[derive(Debug)]
    pub enum Error {
/// Unknown model.
///
/// Based on the output of `/proc/cpuinfo`, it wasn't possible to identify the Raspberry Pi
/// model.
        UnknownModel { description("unknown Raspberry Pi model") }
/// Can't access `/proc/cpuinfo`.
///
/// Unable to read the contents of `/proc/cpuinfo`. This could be an issue with permissions, or
/// a Linux distribution is used that doesn't provide access to this virtual file.
        CantAccessProcCpuInfo { description("can't access /proc/cpuinfo") }
    }
}

/// Result type returned from methods that can have `system::Error`s.
pub type Result<T> = result::Result<T, Error>;

/// Identifiable Raspberry Pi models.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Model {
    RaspberryPiA,
    RaspberryPiAPlus,
    RaspberryPiB,
    RaspberryPiBPlus,
    RaspberryPi2B,
    RaspberryPi3B,
    RaspberryPi3BPlus,
    RaspberryPiComputeModule,
    RaspberryPiComputeModule3,
    RaspberryPiZero,
    RaspberryPiZeroW,
}

impl fmt::Display for Model {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Model::RaspberryPiA => write!(f, "Raspberry Pi A"),
            Model::RaspberryPiAPlus => write!(f, "Raspberry Pi A+"),
            Model::RaspberryPiB => write!(f, "Raspberry Pi B"),
            Model::RaspberryPiBPlus => write!(f, "Raspberry Pi B+"),
            Model::RaspberryPi2B => write!(f, "Raspberry Pi 2 B"),
            Model::RaspberryPi3B => write!(f, "Raspberry Pi 3 B"),
            Model::RaspberryPi3BPlus => write!(f, "Raspberry Pi 3 B+"),
            Model::RaspberryPiComputeModule => write!(f, "Raspberry Pi Compute Module"),
            Model::RaspberryPiComputeModule3 => write!(f, "Raspberry Pi Compute Module 3"),
            Model::RaspberryPiZero => write!(f, "Raspberry Pi Zero"),
            Model::RaspberryPiZeroW => write!(f, "Raspberry Pi Zero W"),
        }
    }
}

/// Identifiable Raspberry Pi SoCs.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SoC {
    Bcm2835,
    Bcm2836,
    Bcm2837A1,
    Bcm2837B0,
}

impl fmt::Display for SoC {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SoC::Bcm2835 => write!(f, "BCM2835"),
            SoC::Bcm2836 => write!(f, "BCM2836"),
            SoC::Bcm2837A1 => write!(f, "BCM2837A1"),
            SoC::Bcm2837B0 => write!(f, "BCM2837B0"),
        }
    }
}

/// Retrieves Raspberry Pi device information.
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct DeviceInfo {
    model: Model,
    soc: SoC,
    peripheral_base: u32,
    gpio_offset: u32,
}

impl DeviceInfo {
    /// Constructs a new `DeviceInfo`.
    ///
    /// `new` parses the contents of `/proc/cpuinfo` to identify the Raspberry
    /// Pi's model and SoC.
    pub fn new() -> Result<DeviceInfo> {
        // Parse /proc/cpuinfo to extract hardware/revision
        let proc_cpuinfo = BufReader::new(match File::open("/proc/cpuinfo") {
            Err(_) => return Err(Error::CantAccessProcCpuInfo),
            Ok(file) => file,
        });

        let mut hardware: String = String::new();
        let mut revision: String = String::new();
        for line_result in proc_cpuinfo.lines() {
            if let Ok(line) = line_result {
                if line.starts_with("Hardware\t: ") {
                    hardware = String::from(&line[11..]);
                } else if line.starts_with("Revision\t: ") {
                    revision = String::from(&line[11..]).to_lowercase();
                }
            }
        }

        // Return an error if we don't recognize the SoC. This check is
        // done to prevent accidentally identifying a non-Pi SBC as a Pi
        // solely based on the revision field.
        match &hardware[..] {
            "BCM2708" | "BCM2835" | "BCM2709" | "BCM2836" | "BCM2710" | "BCM2837" | "BCM2837A1"
            | "BCM2837B0" => {}
            _ => return Err(Error::UnknownModel),
        }

        let model = if (revision.len() == 4) || (revision.len() == 8) {
            // Older revisions are 4 characters long, or 8 if they've been over-volted
            match &revision[revision.len() - 4..] {
                "0007" | "0008" | "0009" | "0015" => Model::RaspberryPiA,
                "Beta" | "0002" | "0003" | "0004" | "0005" | "0006" | "000d" | "000e" | "000f" => {
                    Model::RaspberryPiB
                }
                "0012" => Model::RaspberryPiAPlus,
                "0010" | "0013" => Model::RaspberryPiBPlus,
                "0011" | "0014" => Model::RaspberryPiComputeModule,
                _ => return Err(Error::UnknownModel),
            }
        } else if revision.len() >= 6 {
            // Newer revisions consist of at least 6 characters
            match &revision[revision.len() - 3..revision.len() - 1] {
                "00" => Model::RaspberryPiA,
                "01" => Model::RaspberryPiB,
                "02" => Model::RaspberryPiAPlus,
                "03" => Model::RaspberryPiBPlus,
                "04" => Model::RaspberryPi2B,
                "06" => Model::RaspberryPiComputeModule,
                "08" => Model::RaspberryPi3B,
                "09" => Model::RaspberryPiZero,
                "0a" => Model::RaspberryPiComputeModule3,
                "0c" => Model::RaspberryPiZeroW,
                "0d" => Model::RaspberryPi3BPlus,
                _ => return Err(Error::UnknownModel),
            }
        } else {
            return Err(Error::UnknownModel);
        };

        // Set SoC and memory offsets based on model
        match model {
            Model::RaspberryPiA
            | Model::RaspberryPiAPlus
            | Model::RaspberryPiB
            | Model::RaspberryPiBPlus
            | Model::RaspberryPiComputeModule
            | Model::RaspberryPiZero
            | Model::RaspberryPiZeroW => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2835,
                peripheral_base: PERIPHERAL_BASE_RPI,
                gpio_offset: GPIO_OFFSET,
            }),
            Model::RaspberryPi2B => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2836,
                peripheral_base: PERIPHERAL_BASE_RPI2,
                gpio_offset: GPIO_OFFSET,
            }),
            Model::RaspberryPi3B | Model::RaspberryPiComputeModule3 => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2837A1,
                peripheral_base: PERIPHERAL_BASE_RPI2,
                gpio_offset: GPIO_OFFSET,
            }),
            Model::RaspberryPi3BPlus => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2837B0,
                peripheral_base: PERIPHERAL_BASE_RPI2,
                gpio_offset: GPIO_OFFSET,
            }),
        }
    }

    /// Returns the Raspberry Pi's model.
    pub fn model(&self) -> Model {
        self.model
    }

    /// Returns the Raspberry Pi's SoC.
    pub fn soc(&self) -> SoC {
        self.soc
    }

    /// Returns the base memory address for the BCM283x peripherals.
    pub fn peripheral_base(&self) -> u32 {
        self.peripheral_base
    }

    /// Returns the offset from the base memory address for the GPIO section.
    pub fn gpio_offset(&self) -> u32 {
        self.gpio_offset
    }
}
<commit_msg>Differentiate between Model B Rev 1 and Rev 2<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Raspberry Pi system-related tools.
//!
//! Use [`DeviceInfo`] to identify what Raspberry Pi model and SoC the software is
//! running on. This information is used internally to calculate the correct memory
//! locations for the various BCM283x peripherals.
//!
//! [`DeviceInfo`]: struct.DeviceInfo.html

use std::fmt;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::result;

const PERIPHERAL_BASE_RPI: u32 = 0x20_000_000;
const PERIPHERAL_BASE_RPI2: u32 = 0x3f_000_000;
const GPIO_OFFSET: u32 = 0x200_000;

quick_error! {
/// Errors that can occur when trying to identify the Raspberry Pi hardware.
    #[derive(Debug)]
    pub enum Error {
/// Unknown model.
///
/// Based on the output of `/proc/cpuinfo`, it wasn't possible to identify the Raspberry Pi
/// model.
        UnknownModel { description("unknown Raspberry Pi model") }
/// Can't access `/proc/cpuinfo`.
///
/// Unable to read the contents of `/proc/cpuinfo`. This could be an issue with permissions, or
/// a Linux distribution is used that doesn't provide access to this virtual file.
        CantAccessProcCpuInfo { description("can't access /proc/cpuinfo") }
    }
}

/// Result type returned from methods that can have `system::Error`s.
pub type Result<T> = result::Result<T, Error>;

/// Identifiable Raspberry Pi models.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Model {
    RaspberryPiA,
    RaspberryPiAPlus,
    RaspberryPiBRev1,
    RaspberryPiBRev2,
    RaspberryPiBPlus,
    RaspberryPi2B,
    RaspberryPi3B,
    RaspberryPi3BPlus,
    RaspberryPiComputeModule,
    RaspberryPiComputeModule3,
    RaspberryPiZero,
    RaspberryPiZeroW,
}

impl fmt::Display for Model {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Model::RaspberryPiA => write!(f, "Raspberry Pi A"),
            Model::RaspberryPiAPlus => write!(f, "Raspberry Pi A+"),
            Model::RaspberryPiBRev1 => write!(f, "Raspberry Pi B Rev 1"),
            Model::RaspberryPiBRev2 => write!(f, "Raspberry Pi B Rev 2"),
            Model::RaspberryPiBPlus => write!(f, "Raspberry Pi B+"),
            Model::RaspberryPi2B => write!(f, "Raspberry Pi 2 B"),
            Model::RaspberryPi3B => write!(f, "Raspberry Pi 3 B"),
            Model::RaspberryPi3BPlus => write!(f, "Raspberry Pi 3 B+"),
            Model::RaspberryPiComputeModule => write!(f, "Raspberry Pi Compute Module"),
            Model::RaspberryPiComputeModule3 => write!(f, "Raspberry Pi Compute Module 3"),
            Model::RaspberryPiZero => write!(f, "Raspberry Pi Zero"),
            Model::RaspberryPiZeroW => write!(f, "Raspberry Pi Zero W"),
        }
    }
}

/// Identifiable Raspberry Pi SoCs.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SoC {
    Bcm2835,
    Bcm2836,
    Bcm2837A1,
    Bcm2837B0,
}

impl fmt::Display for SoC {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SoC::Bcm2835 => write!(f, "BCM2835"),
            SoC::Bcm2836 => write!(f, "BCM2836"),
            SoC::Bcm2837A1 => write!(f, "BCM2837A1"),
            SoC::Bcm2837B0 => write!(f, "BCM2837B0"),
        }
    }
}

/// Retrieves Raspberry Pi device information.
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct DeviceInfo {
    model: Model,
    soc: SoC,
    peripheral_base: u32,
    gpio_offset: u32,
}

impl DeviceInfo {
    /// Constructs a new `DeviceInfo`.
    ///
    /// `new` parses the contents of `/proc/cpuinfo` to identify the Raspberry
    /// Pi's model and SoC.
    pub fn new() -> Result<DeviceInfo> {
        // Parse /proc/cpuinfo to extract hardware/revision
        let proc_cpuinfo = BufReader::new(match File::open("/proc/cpuinfo") {
            Err(_) => return Err(Error::CantAccessProcCpuInfo),
            Ok(file) => file,
        });

        let mut hardware: String = String::new();
        let mut revision: String = String::new();
        for line_result in proc_cpuinfo.lines() {
            if let Ok(line) = line_result {
                if line.starts_with("Hardware\t: ") {
                    hardware = String::from(&line[11..]);
                } else if line.starts_with("Revision\t: ") {
                    revision = String::from(&line[11..]).to_lowercase();
                }
            }
        }

        // Return an error if we don't recognize the SoC. This check is
        // done to prevent accidentally identifying a non-Pi SBC as a Pi
        // solely based on the revision field.
        match &hardware[..] {
            "BCM2708" | "BCM2835" | "BCM2709" | "BCM2836" | "BCM2710" | "BCM2837" | "BCM2837A1"
            | "BCM2837B0" => {}
            _ => return Err(Error::UnknownModel),
        }

        let model = if (revision.len() == 4) || (revision.len() == 8) {
            // Older revisions are 4 characters long, or 8 if they've been over-volted
            match &revision[revision.len() - 4..] {
                "0007" | "0008" | "0009" | "0015" => Model::RaspberryPiA,
                "Beta" | "0002" | "0003" => Model::RaspberryPiBRev1,
                "0004" | "0005" | "0006" | "000d" | "000e" | "000f" => Model::RaspberryPiBRev2,
                "0012" => Model::RaspberryPiAPlus,
                "0010" | "0013" => Model::RaspberryPiBPlus,
                "0011" | "0014" => Model::RaspberryPiComputeModule,
                _ => return Err(Error::UnknownModel),
            }
        } else if revision.len() >= 6 {
            // Newer revisions consist of at least 6 characters
            match &revision[revision.len() - 3..revision.len() - 1] {
                "00" => Model::RaspberryPiA,
                "01" => Model::RaspberryPiBRev2,
                "02" => Model::RaspberryPiAPlus,
                "03" => Model::RaspberryPiBPlus,
                "04" => Model::RaspberryPi2B,
                "06" => Model::RaspberryPiComputeModule,
                "08" => Model::RaspberryPi3B,
                "09" => Model::RaspberryPiZero,
                "0a" => Model::RaspberryPiComputeModule3,
                "0c" => Model::RaspberryPiZeroW,
                "0d" => Model::RaspberryPi3BPlus,
                _ => return Err(Error::UnknownModel),
            }
        } else {
            return Err(Error::UnknownModel);
        };

        // Set SoC and memory offsets based on model
        match model {
            Model::RaspberryPiA
            | Model::RaspberryPiAPlus
            | Model::RaspberryPiBRev1
            | Model::RaspberryPiBRev2
            | Model::RaspberryPiBPlus
            | Model::RaspberryPiComputeModule
            | Model::RaspberryPiZero
            | Model::RaspberryPiZeroW => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2835,
                peripheral_base: PERIPHERAL_BASE_RPI,
                gpio_offset: GPIO_OFFSET,
            }),
            Model::RaspberryPi2B => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2836,
                peripheral_base: PERIPHERAL_BASE_RPI2,
                gpio_offset: GPIO_OFFSET,
            }),
            Model::RaspberryPi3B | Model::RaspberryPiComputeModule3 => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2837A1,
                peripheral_base: PERIPHERAL_BASE_RPI2,
                gpio_offset: GPIO_OFFSET,
            }),
            Model::RaspberryPi3BPlus => Ok(DeviceInfo {
                model,
                soc: SoC::Bcm2837B0,
                peripheral_base: PERIPHERAL_BASE_RPI2,
                gpio_offset: GPIO_OFFSET,
            }),
        }
    }

    /// Returns the Raspberry Pi's model.
    pub fn model(&self) -> Model {
        self.model
    }

    /// Returns the Raspberry Pi's SoC.
    pub fn soc(&self) -> SoC {
        self.soc
    }

    /// Returns the base memory address for the BCM283x peripherals.
    pub fn peripheral_base(&self) -> u32 {
        self.peripheral_base
    }

    /// Returns the offset from the base memory address for the GPIO section.
    pub fn gpio_offset(&self) -> u32 {
        self.gpio_offset
    }
}
<|endoftext|>


<commit_before>//! Time-related utilities

use time;

/// Animation cycle based on system clock.
pub fn cycle_anim(period_s: f64, num_frames: usize) -> usize {
    debug_assert!(period_s > 0.0);
    debug_assert!(num_frames > 0);
    (time::precise_time_s() / period_s) as usize % num_frames
}

/// Time-plot that spikes at given intervals for the given time.
pub fn spike(down_s: f64, up_s: f64) -> bool { time::precise_time_s() % (down_s + up_s) > down_s }

pub fn single_anim(start_s: f64, period_s: f64, num_frames: usize) -> usize {
    debug_assert!(period_s > 0.0);
    debug_assert!(num_frames > 0);
    let mut idx = ((time::precise_time_s() - start_s) / period_s) as i32;
    if idx < 0 {
        idx = 0;
    }
    if idx >= num_frames as i32 {
        idx = num_frames as i32 - 1;
    }

    idx as usize
}

pub struct TimestepLoop {
    timestep_s: f64,
    current_time: f64,
    accum: f64,
    /// Weight given to latest render duration when updating average duration.
    update_weight: f64,
    average_frame_s: f64,
    current_tick: u64,
}

/// Utility structure for tracking FPS and fixed step physics updates.
///
/// Inspired by https://gafferongames.com/post/fix_your_timestep/
///
/// ```
/// use calx::TimestepLoop;
///
/// fn update_physics() {
///     // Physics update here
/// }
///
/// fn render_frame() {
///     // Draw graphics here
/// }
///
/// let mut timestep_loop = TimestepLoop::new(1.0 / 30.0);
///
/// /* loop */ {
///     while timestep_loop.should_update() {
///         update_physics();
///     }
///
///     render_frame();
///     timestep_loop.observe_render();
///     println!("tick: {}, FPS: {}",
///         timestep_loop.current_tick(),
///         1.0 / timestep_loop.average_frame_s());
/// }
/// ```
impl TimestepLoop {
    pub fn new(timestep_s: f64) -> TimestepLoop {
        TimestepLoop {
            timestep_s,
            current_time: time::precise_time_s(),
            accum: 0.0,

            // XXX: Arbitrarily chosen weight parameter
            update_weight: 0.05,

            average_frame_s: 1.0,
            current_tick: 0,
        }
    }

    /// Add to timestep accumulator and update frame duration counter.
    pub fn observe_render(&mut self) {
        let current_time = time::precise_time_s();
        let delta = current_time - self.current_time;
        self.current_time = current_time;
        self.accum += current_time;
        self.average_frame_s =
            self.average_frame_s * (1.0 - self.update_weight) + delta * self.update_weight;
    }

    /// Consume accumulation and return true if accumulation is sufficient for a physics update.
    pub fn should_update(&mut self) -> bool {
        if self.accum < self.timestep_s {
            return false;
        }

        self.accum -= self.timestep_s;
        self.current_tick += 1;
        true
    }

    /// Return length of the update tick in seconds
    pub fn timestep_s(&self) -> f64 { self.timestep_s }

    /// Return the number of update ticks observed since `TimestepLoop` creation.
    pub fn current_tick(&self) -> u64 { self.current_tick }

    /// Return the average render frame duration in seconds.
    pub fn average_frame_s(&self) -> f64 { self.average_frame_s }
}
<commit_msg>Query for time to update in timestep<commit_after>//! Time-related utilities

use time;

/// Animation cycle based on system clock.
pub fn cycle_anim(period_s: f64, num_frames: usize) -> usize {
    debug_assert!(period_s > 0.0);
    debug_assert!(num_frames > 0);
    (time::precise_time_s() / period_s) as usize % num_frames
}

/// Time-plot that spikes at given intervals for the given time.
pub fn spike(down_s: f64, up_s: f64) -> bool { time::precise_time_s() % (down_s + up_s) > down_s }

pub fn single_anim(start_s: f64, period_s: f64, num_frames: usize) -> usize {
    debug_assert!(period_s > 0.0);
    debug_assert!(num_frames > 0);
    let mut idx = ((time::precise_time_s() - start_s) / period_s) as i32;
    if idx < 0 {
        idx = 0;
    }
    if idx >= num_frames as i32 {
        idx = num_frames as i32 - 1;
    }

    idx as usize
}

pub struct TimestepLoop {
    timestep_s: f64,
    current_time: f64,
    accum: f64,
    /// Weight given to latest render duration when updating average duration.
    update_weight: f64,
    average_frame_s: f64,
    current_tick: u64,
}

/// Utility structure for tracking FPS and fixed step physics updates.
///
/// Inspired by https://gafferongames.com/post/fix_your_timestep/
///
/// ```
/// use calx::TimestepLoop;
///
/// fn update_physics() {
///     // Physics update here
/// }
///
/// fn render_frame() {
///     // Draw graphics here
/// }
///
/// let mut timestep_loop = TimestepLoop::new(1.0 / 30.0);
///
/// /* loop */ {
///     while timestep_loop.should_update() {
///         update_physics();
///     }
///
///     render_frame();
///     timestep_loop.observe_render();
///     println!("tick: {}, FPS: {}",
///         timestep_loop.current_tick(),
///         1.0 / timestep_loop.average_frame_s());
/// }
/// ```
impl TimestepLoop {
    pub fn new(timestep_s: f64) -> TimestepLoop {
        TimestepLoop {
            timestep_s,
            current_time: time::precise_time_s(),
            accum: 0.0,

            // XXX: Arbitrarily chosen weight parameter
            update_weight: 0.05,

            average_frame_s: 1.0,
            current_tick: 0,
        }
    }

    /// Add to timestep accumulator and update frame duration counter.
    pub fn observe_render(&mut self) {
        let current_time = time::precise_time_s();
        let delta = current_time - self.current_time;
        self.current_time = current_time;
        self.accum += current_time;
        self.average_frame_s =
            self.average_frame_s * (1.0 - self.update_weight) + delta * self.update_weight;
    }

    /// Consume accumulation and return true if accumulation is sufficient for a physics update.
    pub fn should_update(&mut self) -> bool {
        if self.accum < self.timestep_s {
            return false;
        }

        self.accum -= self.timestep_s;
        self.current_tick += 1;
        true
    }

    /// Return remaining time until the next update.
    ///
    /// If this is positive, the caller can sleep between frames
    pub fn time_until_update(&self) -> f64 { self.timestep_s - self.accum }

    /// Return length of the update tick in seconds
    pub fn timestep_s(&self) -> f64 { self.timestep_s }

    /// Return the number of update ticks observed since `TimestepLoop` creation.
    pub fn current_tick(&self) -> u64 { self.current_tick }

    /// Return the average render frame duration in seconds.
    pub fn average_frame_s(&self) -> f64 { self.average_frame_s }
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};

/// Trait represents global state of the
/// entire simulation which can updated
/// independently from any particular cell.
/// Consider to store there as much as you can
/// because this data will be created only once
/// and will not be copied.
pub trait EvolutionState {
    /// Method is called once between cells' updates.
    fn update(&mut self);
}

pub trait Cell: Serialize + Deserialize {
    type Coord: Coord;
    type State: EvolutionState;

    fn update<'a, I>(&'a mut self, old: &'a Self, neighbors: I, &Self::State)
        where I: Iterator<Item = Option<&'a Self>>;

    fn with_coord<C: Coord>(C) -> Self;
    fn coord(&self) -> &Self::Coord;
    fn set_coord<C: Coord>(&mut self, &C);
}

pub trait Nhood {
    type Coord: Coord;

    fn neighbors(&self, &Self::Coord) -> Vec<Self::Coord>;
    fn neighbors_count(&self) -> usize;
}

pub trait Coord: Clone + Serialize + Deserialize {
    fn from_2d(x: i32, y: i32) -> Self;

    fn x(&self) -> i32;
    fn y(&self) -> i32;
    fn z(&self) -> i32 { 0 }
}

pub trait Grid {
    type Cell: Cell;
    type Coord: Coord;

    fn update(&mut self);

    fn state(&self) -> &<<Self as Grid>::Cell as Cell>::State;
    fn cells(&self) -> &Vec<Self::Cell>;
    fn dimensions(&self) -> Self::Coord;

    fn set_cells(&mut self, Vec<Self::Cell>);
}

pub trait Consumer {
    type Cell: Cell;

    fn consume<G>(&mut self, &mut G)
        where G: Grid<Cell = Self::Cell>;
}

/// Interlayer between grid and consumer(s).
pub trait Engine {
    fn run_times(&mut self, i64);
}
<commit_msg>Note about Consumer.<commit_after>use serde::{Deserialize, Serialize};

/// Trait represents global state of the
/// entire simulation which can updated
/// independently from any particular cell.
/// Consider to store there as much as you can
/// because this data will be created only once
/// and will not be copied.
pub trait EvolutionState {
    /// Method is called once between cells' updates.
    fn update(&mut self);
}

pub trait Cell: Serialize + Deserialize {
    type Coord: Coord;
    type State: EvolutionState;

    fn update<'a, I>(&'a mut self, old: &'a Self, neighbors: I, &Self::State)
        where I: Iterator<Item = Option<&'a Self>>;

    fn with_coord<C: Coord>(C) -> Self;
    fn coord(&self) -> &Self::Coord;
    fn set_coord<C: Coord>(&mut self, &C);
}

pub trait Nhood {
    type Coord: Coord;

    fn neighbors(&self, &Self::Coord) -> Vec<Self::Coord>;
    fn neighbors_count(&self) -> usize;
}

pub trait Coord: Clone + Serialize + Deserialize {
    fn from_2d(x: i32, y: i32) -> Self;

    fn x(&self) -> i32;
    fn y(&self) -> i32;
    fn z(&self) -> i32 { 0 }
}

pub trait Grid {
    type Cell: Cell;
    type Coord: Coord;

    fn update(&mut self);

    fn state(&self) -> &<<Self as Grid>::Cell as Cell>::State;
    fn cells(&self) -> &Vec<Self::Cell>;
    fn dimensions(&self) -> Self::Coord;

    fn set_cells(&mut self, Vec<Self::Cell>);
}

/// Interface to the outer world.
pub trait Consumer {
    /// Cells supported by this consumer. Helps
    /// to use cells from grid directly if grid
    /// has the same cell in it.
    type Cell: Cell;

    /// Called once when all cells has been updated.
    fn consume<G>(&mut self, &mut G)
        where G: Grid<Cell = Self::Cell>;
}

/// Interlayer between grid and consumer(s).
pub trait Engine {
    fn run_times(&mut self, i64);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```
//! # use std::fmt;
//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> !
//! # { loop {} }
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_docs)]
#![unstable(feature = "core_panic",
            reason = "internal details of the implementation of the `panic!` \
                      and related macros",
            issue = "0")]

use fmt;

#[cold] #[inline(never)] // this is the slow path, always
#[cfg_attr(not(stage0), lang = "panic")]
pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
    // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
    // reduce size overhead. The format_args! macro uses str's Display trait to
    // write expr, which calls Formatter::pad, which must accommodate string
    // truncation and padding (even though none is used here). Using
    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
    // output binary, saving up to a few kilobytes.
    let (expr, file, line, col) = *expr_file_line_col;
    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
}

// FIXME: remove when SNAP
#[cold] #[inline(never)]
#[cfg(stage0)]
#[lang = "panic"]
pub fn panic_old(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
    let (expr, file, line) = *expr_file_line;
    let expr_file_line_col = (expr, file, line, 0);
    panic(&expr_file_line_col)
}

#[cold] #[inline(never)]
#[cfg_attr(not(stage0), lang = "panic_bounds_check")]
fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
                     index: usize, len: usize) -> ! {
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), file_line_col)
}

// FIXME: remove when SNAP
#[cold] #[inline(never)]
#[cfg(stage0)]
#[lang = "panic_bounds_check"]
fn panic_bounds_check_old(file_line: &(&'static str, u32),
                     index: usize, len: usize) -> ! {
    let (file, line) = *file_line;
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), &(file, line, 0))
}

#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
    #[allow(improper_ctypes)]
    extern {
        #[lang = "panic_fmt"]
        #[unwind]
        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col :u32) -> !;
    }
    let (file, line, col) = *file_line_col;
    unsafe { panic_impl(fmt, file, line, col) }
}
<commit_msg>Style fix<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Panic support for libcore
//!
//! The core library cannot define panicking, but it does *declare* panicking. This
//! means that the functions inside of libcore are allowed to panic, but to be
//! useful an upstream crate must define panicking for libcore to use. The current
//! interface for panicking is:
//!
//! ```
//! # use std::fmt;
//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> !
//! # { loop {} }
//! ```
//!
//! This definition allows for panicking with any general message, but it does not
//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
//! is not allowed to allocate.
//!
//! This module contains a few other panicking functions, but these are just the
//! necessary lang items for the compiler. All panics are funneled through this
//! one function. Currently, the actual symbol is declared in the standard
//! library, but the location of this may change over time.

#![allow(dead_code, missing_docs)]
#![unstable(feature = "core_panic",
            reason = "internal details of the implementation of the `panic!` \
                      and related macros",
            issue = "0")]

use fmt;

#[cold] #[inline(never)] // this is the slow path, always
#[cfg_attr(not(stage0), lang = "panic")]
pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
    // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
    // reduce size overhead. The format_args! macro uses str's Display trait to
    // write expr, which calls Formatter::pad, which must accommodate string
    // truncation and padding (even though none is used here). Using
    // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
    // output binary, saving up to a few kilobytes.
    let (expr, file, line, col) = *expr_file_line_col;
    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
}

// FIXME: remove when SNAP
#[cold] #[inline(never)]
#[cfg(stage0)]
#[lang = "panic"]
pub fn panic_old(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
    let (expr, file, line) = *expr_file_line;
    let expr_file_line_col = (expr, file, line, 0);
    panic(&expr_file_line_col)
}

#[cold] #[inline(never)]
#[cfg_attr(not(stage0), lang = "panic_bounds_check")]
fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
                     index: usize, len: usize) -> ! {
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), file_line_col)
}

// FIXME: remove when SNAP
#[cold] #[inline(never)]
#[cfg(stage0)]
#[lang = "panic_bounds_check"]
fn panic_bounds_check_old(file_line: &(&'static str, u32),
                     index: usize, len: usize) -> ! {
    let (file, line) = *file_line;
    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                           len, index), &(file, line, 0))
}

#[cold] #[inline(never)]
pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
    #[allow(improper_ctypes)]
    extern {
        #[lang = "panic_fmt"]
        #[unwind]
        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !;
    }
    let (file, line, col) = *file_line_col;
    unsafe { panic_impl(fmt, file, line, col) }
}
<|endoftext|>