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

//!
//! Implements the Roughenough server functionality.
//!

use hex;
use std::io::ErrorKind;
use std::net::{SocketAddr, IpAddr};
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use std::io::Write;

use byteorder::{LittleEndian, WriteBytesExt};

use humansize::{FileSize, file_size_opts as fsopts};

use mio::net::{TcpListener, UdpSocket};
use mio::{Events, Poll, PollOpt, Ready, Token};
use mio::tcp::Shutdown;
use mio_extras::timer::Timer;

use crate::{Error, RtMessage, Tag, MIN_REQUEST_LENGTH};
use crate::config::ServerConfig;
use crate::grease::Grease;
use crate::key::{LongTermKey, OnlineKey};
use crate::kms;
use crate::merkle::MerkleTree;
use crate::stats::{AggregatedStats, PerClientStats, ServerStats, ClientStatEntry};

macro_rules! check_ctrlc {
    ($keep_running:expr) => {
        if !$keep_running.load(Ordering::Acquire) {
            warn!("Ctrl-C caught, exiting...");
            return true;
        }
    };
}

// mio event registrations
const EVT_MESSAGE: Token = Token(0);
const EVT_STATUS_UPDATE: Token = Token(1);
const EVT_HEALTH_CHECK: Token = Token(2);

// Canned response to health check request
const HTTP_RESPONSE: &str = "HTTP/1.1 200 OK\nContent-Length: 0\nConnection: close\n\n";

/// The main Roughenough server instance.
///
/// The [ServerConfig](../config/trait.ServerConfig.html) trait specifies the required and optional
/// parameters available for configuring a Roughenoguh server instance.
///
/// Implementations of `ServerConfig` obtain configurations from different back-end sources
/// such as files or environment variables.
///
/// See [the config module](../config/index.html) for more information.
///
pub struct Server {
    config: Box<dyn ServerConfig>,
    online_key: OnlineKey,
    cert_bytes: Vec<u8>,

    socket: UdpSocket,
    health_listener: Option<TcpListener>,
    keep_running: Arc<AtomicBool>,
    poll_duration: Option<Duration>,
    grease: Grease,
    timer: Timer<()>,
    poll: Poll,
    merkle: MerkleTree,
    requests: Vec<(Vec<u8>, SocketAddr)>,
    buf: [u8; 65_536],

    public_key: String,

    stats: Box<dyn ServerStats>,

    // Used to send requests to ourselves in fuzzing mode
    #[cfg(fuzzing)]
    fake_client_socket: UdpSocket,
}

impl Server {
    ///
    /// Create a new server instance from the provided
    /// [`ServerConfig`](../config/trait.ServerConfig.html) trait object instance.
    ///
    pub fn new(config: Box<dyn ServerConfig>) -> Server {
        let online_key = OnlineKey::new();
        let public_key: String;

        let cert_bytes = {
            let seed = match kms::load_seed(config.as_ref()) {
                Ok(seed) => seed,
                Err(e) => {
                    error!("Failed to load seed: {:#?}", e);
                    process::exit(1);
                }
            };
            let mut long_term_key = LongTermKey::new(&seed);
            public_key = hex::encode(long_term_key.public_key());

            long_term_key.make_cert(&online_key).encode().unwrap()
        };

        let keep_running = Arc::new(AtomicBool::new(true));

        let sock_addr = config.udp_socket_addr().expect("udp sock addr");
        let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");

        let poll_duration = Some(Duration::from_millis(100));

        let mut timer: Timer<()> = Timer::default();
        timer.set_timeout(config.status_interval(), ());

        let poll = Poll::new().unwrap();
        poll.register(&socket, EVT_MESSAGE, Ready::readable(), PollOpt::edge())
            .unwrap();
        poll.register(&timer, EVT_STATUS_UPDATE, Ready::readable(), PollOpt::edge())
            .unwrap();

        let health_listener = if let Some(hc_port) = config.health_check_port() {
            let hc_sock_addr: SocketAddr = format!("{}:{}", config.interface(), hc_port)
                .parse()
                .unwrap();

            let tcp_listener = TcpListener::bind(&hc_sock_addr)
                .expect("failed to bind TCP listener for health check");

            poll.register(&tcp_listener, EVT_HEALTH_CHECK, Ready::readable(), PollOpt::edge())
                .unwrap();

            Some(tcp_listener)
        } else {
            None
        };

        let stats: Box<dyn ServerStats> = if config.client_stats_enabled() {
            Box::new(PerClientStats::new())
        } else {
            Box::new(AggregatedStats::new())
        };

        let grease = Grease::new(config.fault_percentage());
        let merkle = MerkleTree::new();
        let requests = Vec::with_capacity(config.batch_size() as usize);

        Server {
            config,
            online_key,
            cert_bytes,

            socket,
            health_listener,

            keep_running,
            poll_duration,
            grease,
            timer,
            poll,
            merkle,
            requests,
            buf: [0u8; 65_536],

            public_key,

            stats,

            #[cfg(fuzzing)]
            fake_client_socket: UdpSocket::bind(&"127.0.0.1:0".parse().unwrap()).unwrap(),
        }
    }

    /// Returns a reference to the server's long-term public key
    pub fn get_public_key(&self) -> &str {
        &self.public_key
    }

    /// Returns a reference to the server's on-line (delegated) key
    pub fn get_online_key(&self) -> &OnlineKey {
        &self.online_key
    }

    /// Returns a reference to the `ServerConfig` this server was configured with
    pub fn get_config(&self) -> &dyn ServerConfig {
        self.config.as_ref()
    }

    /// Returns a reference counted pointer the this server's `keep_running` value.
    pub fn get_keep_running(&self) -> Arc<AtomicBool> {
        self.keep_running.clone()
    }

    #[cfg(fuzzing)]
    pub fn send_to_self(&mut self, data: &[u8]) {
        let res = self
            .fake_client_socket
            .send_to(data, &self.socket.local_addr().unwrap());
        info!("Sent to self: {:?}", res);
    }

    /// The main processing function for incoming connections. This method should be
    /// called repeatedly in a loop to process requests. It returns 'true' when the
    /// server has shutdown (due to keep_running being set to 'false').
    ///
    pub fn process_events(&mut self, events: &mut Events) -> bool {
        self.poll
            .poll(events, self.poll_duration)
            .expect("server event poll failed; cannot recover");

        for msg in events.iter() {
            match msg.token() {
                EVT_MESSAGE => {
                    loop {
                        check_ctrlc!(self.keep_running);

                        self.merkle.reset();
                        self.requests.clear();

                        let socket_now_empty = self.collect_requests();

                        if self.requests.is_empty() {
                            break;
                        }

                        self.send_responses();

                        if socket_now_empty {
                            break;
                        }
                    }
                },
                EVT_HEALTH_CHECK => self.handle_health_check(),
                EVT_STATUS_UPDATE => self.handle_status_update(),
                _ => unreachable!(),
            }
        }
        false
    }

    // Read and process client requests from socket until empty or 'batch_size' number of
    // requests have been read.
    fn collect_requests(&mut self) -> bool {
        for i in 0..self.config.batch_size() {
            match self.socket.recv_from(&mut self.buf) {
                Ok((num_bytes, src_addr)) => {
                    match self.nonce_from_request(&self.buf, num_bytes) {
                        Ok(nonce) => {
                            self.stats.add_valid_request(&src_addr.ip());
                            self.requests.push((Vec::from(nonce), src_addr));
                            self.merkle.push_leaf(nonce);
                        }
                        Err(e) => {
                            self.stats.add_invalid_request(&src_addr.ip());

                            info!(
                                "Invalid request: '{:?}' ({} bytes) from {} (#{} in batch, resp #{})",
                                e, num_bytes, src_addr, i,
                                self.stats.total_responses_sent() + u64::from(i)
                            );
                        }
                    }
                }
                Err(e) => match e.kind() {
                    ErrorKind::WouldBlock => {
                        return true;
                    }
                    _ => {
                        error!("Error receiving from socket: {:?}: {:?}", e.kind(), e);
                        return false;
                    }
                },
            };
        }

        false
    }

    // extract the client's nonce from its request
    fn nonce_from_request<'a>(&self, buf: &'a [u8], num_bytes: usize) -> Result<&'a [u8], Error> {
        if num_bytes < MIN_REQUEST_LENGTH as usize {
            return Err(Error::RequestTooShort);
        }

        let tag_count = &buf[..4];
        let expected_nonc = &buf[8..12];
        let expected_pad = &buf[12..16];

        let tag_count_is_2 = tag_count == [0x02, 0x00, 0x00, 0x00];
        let tag1_is_nonc = expected_nonc == Tag::NONC.wire_value();
        let tag2_is_pad = expected_pad == Tag::PAD.wire_value();

        if tag_count_is_2 && tag1_is_nonc && tag2_is_pad {
            Ok(&buf[0x10..0x50])
        } else {
            Err(Error::InvalidRequest)
        }
    }

    fn send_responses(&mut self) {
        let merkle_root = self.merkle.compute_root();

        // The SREP tag is identical for each response
        let srep = self.online_key.make_srep(SystemTime::now(), &merkle_root);

        for (i, &(ref nonce, ref src_addr)) in self.requests.iter().enumerate() {
            let paths = self.merkle.get_paths(i);
            let resp_msg = {
                let r = self.make_response(&srep, &self.cert_bytes, &paths, i as u32);
                if self.grease.should_add_error() { self.grease.add_errors(&r) } else { r }
            };
            let resp_bytes = resp_msg.encode().unwrap();

            let bytes_sent = self
                .socket
                .send_to(&resp_bytes, &src_addr)
                .expect("send_to failed");

            self.stats.add_response(&src_addr.ip(), bytes_sent);

            info!(
                "Responded {} bytes to {} for '{}..' (#{} in batch, resp #{})",
                bytes_sent,
                src_addr,
                hex::encode(&nonce[0..4]),
                i + 1,
                self.stats.total_responses_sent()
            );
        }
    }

    fn make_response(&self, srep: &RtMessage, cert_bytes: &[u8], path: &[u8], idx: u32) -> RtMessage {
        let mut index = [0; 4];
        (&mut index as &mut [u8])
            .write_u32::<LittleEndian>(idx)
            .unwrap();

        let sig_bytes = srep.get_field(Tag::SIG).unwrap();
        let srep_bytes = srep.get_field(Tag::SREP).unwrap();

        let mut response = RtMessage::new(5);
        response.add_field(Tag::SIG, sig_bytes).unwrap();
        response.add_field(Tag::PATH, path).unwrap();
        response.add_field(Tag::SREP, srep_bytes).unwrap();
        response.add_field(Tag::CERT, cert_bytes).unwrap();
        response.add_field(Tag::INDX, &index).unwrap();

        response
    }

    fn handle_health_check(&mut self) {
        let listener = self.health_listener.as_ref().unwrap();
        match listener.accept() {
            Ok((ref mut stream, src_addr)) => {
                info!("health check from {}", src_addr);
                self.stats.add_health_check(&src_addr.ip());

                match stream.write(HTTP_RESPONSE.as_bytes()) {
                    Ok(_) => (),
                    Err(e) => warn!("error writing health check {}", e),
                };

                match stream.shutdown(Shutdown::Both) {
                    Ok(_) => (),
                    Err(e) => warn!("error in health check socket shutdown {}", e),
                }
            }
            Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                debug!("blocking in TCP health check");
            }
            Err(e) => {
                warn!("unexpected health check error {}", e);
            }
        }
    }

    fn handle_status_update(&mut self) {
        let mut vec: Vec<(&IpAddr, &ClientStatEntry)> = self.stats.iter().collect();
        // sort in descending order
        vec.sort_by(|lhs, rhs| rhs.1.valid_requests.cmp(&lhs.1.valid_requests));

        for (addr, counts) in vec {
            info!(
                "{:16}: {} valid, {} invalid requests; {} responses ({} sent)",
                format!("{}", addr), counts.valid_requests, counts.invalid_requests,
                counts.responses_sent,
                counts.bytes_sent.file_size(fsopts::BINARY).unwrap()
            );
        }

        info!(
            "Totals: {} unique clients; {} valid, {} invalid requests; {} responses ({} sent)",
            self.stats.total_unique_clients(),
            self.stats.total_valid_requests(), self.stats.total_invalid_requests(),
            self.stats.total_responses_sent(),
            self.stats.total_bytes_sent().file_size(fsopts::BINARY).unwrap()
        );

        self.timer.set_timeout(self.config.status_interval(), ());
    }
}
<commit_msg>cleanups: rustfmt, import tidying<commit_after>// Copyright 2017-2019 int08h LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//!
//! Implements the Roughenough server functionality.
//!

use hex;
use std::io::ErrorKind;
use std::io::Write;
use std::net::{IpAddr, Shutdown, SocketAddr};
use std::process;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::{Duration, SystemTime};

use byteorder::{LittleEndian, WriteBytesExt};

use humansize::{file_size_opts as fsopts, FileSize};

use mio::net::{TcpListener, UdpSocket};
use mio::{Events, Poll, PollOpt, Ready, Token};
use mio_extras::timer::Timer;

use crate::config::ServerConfig;
use crate::grease::Grease;
use crate::key::{LongTermKey, OnlineKey};
use crate::kms;
use crate::merkle::MerkleTree;
use crate::stats::{AggregatedStats, ClientStatEntry, PerClientStats, ServerStats};
use crate::{Error, RtMessage, Tag, MIN_REQUEST_LENGTH};

macro_rules! check_ctrlc {
    ($keep_running:expr) => {
        if !$keep_running.load(Ordering::Acquire) {
            warn!("Ctrl-C caught, exiting...");
            return true;
        }
    };
}

// mio event registrations
const EVT_MESSAGE: Token = Token(0);
const EVT_STATUS_UPDATE: Token = Token(1);
const EVT_HEALTH_CHECK: Token = Token(2);

// Canned response to health check request
const HTTP_RESPONSE: &str = "HTTP/1.1 200 OK\nContent-Length: 0\nConnection: close\n\n";

/// The main Roughenough server instance.
///
/// The [ServerConfig](../config/trait.ServerConfig.html) trait specifies the required and optional
/// parameters available for configuring a Roughenoguh server instance.
///
/// Implementations of `ServerConfig` obtain configurations from different back-end sources
/// such as files or environment variables.
///
/// See [the config module](../config/index.html) for more information.
///
pub struct Server {
    config: Box<dyn ServerConfig>,
    online_key: OnlineKey,
    cert_bytes: Vec<u8>,

    socket: UdpSocket,
    health_listener: Option<TcpListener>,
    keep_running: Arc<AtomicBool>,
    poll_duration: Option<Duration>,
    grease: Grease,
    timer: Timer<()>,
    poll: Poll,
    merkle: MerkleTree,
    requests: Vec<(Vec<u8>, SocketAddr)>,
    buf: [u8; 65_536],

    public_key: String,

    stats: Box<dyn ServerStats>,

    // Used to send requests to ourselves in fuzzing mode
    #[cfg(fuzzing)]
    fake_client_socket: UdpSocket,
}

impl Server {
    ///
    /// Create a new server instance from the provided
    /// [`ServerConfig`](../config/trait.ServerConfig.html) trait object instance.
    ///
    pub fn new(config: Box<dyn ServerConfig>) -> Server {
        let online_key = OnlineKey::new();
        let public_key: String;

        let cert_bytes = {
            let seed = match kms::load_seed(config.as_ref()) {
                Ok(seed) => seed,
                Err(e) => {
                    error!("Failed to load seed: {:#?}", e);
                    process::exit(1);
                }
            };
            let mut long_term_key = LongTermKey::new(&seed);
            public_key = hex::encode(long_term_key.public_key());

            long_term_key.make_cert(&online_key).encode().unwrap()
        };

        let keep_running = Arc::new(AtomicBool::new(true));

        let sock_addr = config.udp_socket_addr().expect("udp sock addr");
        let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");

        let poll_duration = Some(Duration::from_millis(100));

        let mut timer: Timer<()> = Timer::default();
        timer.set_timeout(config.status_interval(), ());

        let poll = Poll::new().unwrap();
        poll.register(&socket, EVT_MESSAGE, Ready::readable(), PollOpt::edge())
            .unwrap();
        poll.register(&timer, EVT_STATUS_UPDATE, Ready::readable(), PollOpt::edge())
            .unwrap();

        let health_listener = if let Some(hc_port) = config.health_check_port() {
            let hc_sock_addr: SocketAddr = format!("{}:{}", config.interface(), hc_port)
                .parse()
                .unwrap();

            let tcp_listener = TcpListener::bind(&hc_sock_addr)
                .expect("failed to bind TCP listener for health check");

            poll.register(&tcp_listener, EVT_HEALTH_CHECK, Ready::readable(), PollOpt::edge())
                .unwrap();

            Some(tcp_listener)
        } else {
            None
        };

        let stats: Box<dyn ServerStats> = if config.client_stats_enabled() {
            Box::new(PerClientStats::new())
        } else {
            Box::new(AggregatedStats::new())
        };

        let grease = Grease::new(config.fault_percentage());
        let merkle = MerkleTree::new();
        let requests = Vec::with_capacity(config.batch_size() as usize);

        Server {
            config,
            online_key,
            cert_bytes,

            socket,
            health_listener,

            keep_running,
            poll_duration,
            grease,
            timer,
            poll,
            merkle,
            requests,
            buf: [0u8; 65_536],

            public_key,

            stats,

            #[cfg(fuzzing)]
            fake_client_socket: UdpSocket::bind(&"127.0.0.1:0".parse().unwrap()).unwrap(),
        }
    }

    /// Returns a reference to the server's long-term public key
    pub fn get_public_key(&self) -> &str {
        &self.public_key
    }

    /// Returns a reference to the server's on-line (delegated) key
    pub fn get_online_key(&self) -> &OnlineKey {
        &self.online_key
    }

    /// Returns a reference to the `ServerConfig` this server was configured with
    pub fn get_config(&self) -> &dyn ServerConfig {
        self.config.as_ref()
    }

    /// Returns a reference counted pointer the this server's `keep_running` value.
    pub fn get_keep_running(&self) -> Arc<AtomicBool> {
        self.keep_running.clone()
    }

    #[cfg(fuzzing)]
    pub fn send_to_self(&mut self, data: &[u8]) {
        let res = self
            .fake_client_socket
            .send_to(data, &self.socket.local_addr().unwrap());
        info!("Sent to self: {:?}", res);
    }

    /// The main processing function for incoming connections. This method should be
    /// called repeatedly in a loop to process requests. It returns 'true' when the
    /// server has shutdown (due to keep_running being set to 'false').
    ///
    pub fn process_events(&mut self, events: &mut Events) -> bool {
        self.poll
            .poll(events, self.poll_duration)
            .expect("server event poll failed; cannot recover");

        for msg in events.iter() {
            match msg.token() {
                EVT_MESSAGE => loop {
                    check_ctrlc!(self.keep_running);

                    self.merkle.reset();
                    self.requests.clear();

                    let socket_now_empty = self.collect_requests();

                    if self.requests.is_empty() {
                        break;
                    }

                    self.send_responses();

                    if socket_now_empty {
                        break;
                    }
                },
                EVT_HEALTH_CHECK => self.handle_health_check(),
                EVT_STATUS_UPDATE => self.handle_status_update(),
                _ => unreachable!(),
            }
        }
        false
    }

    // Read and process client requests from socket into `self.requests` and `self.merkle` until
    // socket is empty or 'batch_size' number of requests have been read.
    fn collect_requests(&mut self) -> bool {
        for i in 0..self.config.batch_size() {
            match self.socket.recv_from(&mut self.buf) {
                Ok((num_bytes, src_addr)) => {
                    match self.nonce_from_request(&self.buf, num_bytes) {
                        Ok(nonce) => {
                            self.stats.add_valid_request(&src_addr.ip());
                            self.requests.push((Vec::from(nonce), src_addr));
                            self.merkle.push_leaf(nonce);
                        }
                        Err(e) => {
                            self.stats.add_invalid_request(&src_addr.ip());

                            info!(
                                "Invalid request: '{:?}' ({} bytes) from {} (#{} in batch, resp #{})",
                                e, num_bytes, src_addr, i,
                                self.stats.total_responses_sent() + u64::from(i)
                            );
                        }
                    }
                }
                Err(e) => match e.kind() {
                    ErrorKind::WouldBlock => {
                        return true;
                    }
                    _ => {
                        error!("Error receiving from socket: {:?}: {:?}", e.kind(), e);
                        return false;
                    }
                },
            };
        }

        false
    }

    // extract the client's nonce from its request
    fn nonce_from_request<'a>(&self, buf: &'a [u8], num_bytes: usize) -> Result<&'a [u8], Error> {
        if num_bytes < MIN_REQUEST_LENGTH as usize {
            return Err(Error::RequestTooShort);
        }

        let tag_count = &buf[..4];
        let expected_nonc = &buf[8..12];
        let expected_pad = &buf[12..16];

        let tag_count_is_2 = tag_count == [0x02, 0x00, 0x00, 0x00];
        let tag1_is_nonc = expected_nonc == Tag::NONC.wire_value();
        let tag2_is_pad = expected_pad == Tag::PAD.wire_value();

        if tag_count_is_2 && tag1_is_nonc && tag2_is_pad {
            Ok(&buf[0x10..0x50])
        } else {
            Err(Error::InvalidRequest)
        }
    }

    fn send_responses(&mut self) {
        let merkle_root = self.merkle.compute_root();

        // The SREP tag is identical for each response
        let srep = self.online_key.make_srep(SystemTime::now(), &merkle_root);

        for (i, &(ref nonce, ref src_addr)) in self.requests.iter().enumerate() {
            let paths = self.merkle.get_paths(i);
            let resp_msg = {
                let r = self.make_response(&srep, &self.cert_bytes, &paths, i as u32);
                if self.grease.should_add_error() { self.grease.add_errors(&r) } else { r }
            };
            let resp_bytes = resp_msg.encode().unwrap();

            let bytes_sent = self
                .socket
                .send_to(&resp_bytes, &src_addr)
                .expect("send_to failed");

            self.stats.add_response(&src_addr.ip(), bytes_sent);

            info!(
                "Responded {} bytes to {} for '{}..' (#{} in batch, resp #{})",
                bytes_sent,
                src_addr,
                hex::encode(&nonce[0..4]),
                i + 1,
                self.stats.total_responses_sent()
            );
        }
    }

    fn make_response(&self, srep: &RtMessage, cert_bytes: &[u8], path: &[u8], idx: u32) -> RtMessage {
        let mut index = [0; 4];
        (&mut index as &mut [u8])
            .write_u32::<LittleEndian>(idx)
            .unwrap();

        let sig_bytes = srep.get_field(Tag::SIG).unwrap();
        let srep_bytes = srep.get_field(Tag::SREP).unwrap();

        let mut response = RtMessage::new(5);
        response.add_field(Tag::SIG, sig_bytes).unwrap();
        response.add_field(Tag::PATH, path).unwrap();
        response.add_field(Tag::SREP, srep_bytes).unwrap();
        response.add_field(Tag::CERT, cert_bytes).unwrap();
        response.add_field(Tag::INDX, &index).unwrap();

        response
    }

    fn handle_health_check(&mut self) {
        let listener = self.health_listener.as_ref().unwrap();
        match listener.accept() {
            Ok((ref mut stream, src_addr)) => {
                info!("health check from {}", src_addr);
                self.stats.add_health_check(&src_addr.ip());

                match stream.write(HTTP_RESPONSE.as_bytes()) {
                    Ok(_) => (),
                    Err(e) => warn!("error writing health check {}", e),
                };

                match stream.shutdown(Shutdown::Both) {
                    Ok(_) => (),
                    Err(e) => warn!("error in health check socket shutdown {}", e),
                }
            }
            Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
                debug!("blocking in TCP health check");
            }
            Err(e) => {
                warn!("unexpected health check error {}", e);
            }
        }
    }

    fn handle_status_update(&mut self) {
        let mut vec: Vec<(&IpAddr, &ClientStatEntry)> = self.stats.iter().collect();
        // sort in descending order
        vec.sort_by(|lhs, rhs| rhs.1.valid_requests.cmp(&lhs.1.valid_requests));

        for (addr, counts) in vec {
            info!(
                "{:16}: {} valid, {} invalid requests; {} responses ({} sent)",
                format!("{}", addr),
                counts.valid_requests,
                counts.invalid_requests,
                counts.responses_sent,
                counts.bytes_sent.file_size(fsopts::BINARY).unwrap()
            );
        }

        info!(
            "Totals: {} unique clients; {} valid, {} invalid requests; {} responses ({} sent)",
            self.stats.total_unique_clients(),
            self.stats.total_valid_requests(),
            self.stats.total_invalid_requests(),
            self.stats.total_responses_sent(),
            self.stats
                .total_bytes_sent()
                .file_size(fsopts::BINARY)
                .unwrap()
        );

        self.timer.set_timeout(self.config.status_interval(), ());
    }
}
<|endoftext|>


<commit_before>use std::ptr;
use gl;
use gl::types::*;
use context::Context;
use types::GLError;

pub struct Shader {
    gl_id: GLuint
}

impl Shader {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteShader(self.gl_id);
        }
    }
}

unsafe fn _get_shader_iv(shader: &Shader,
                         pname: GLenum,
                         params: *mut GLint)
{
    gl::GetShaderiv(shader.gl_id(), pname, params);
    dbg_gl_sanity_check! {
        GLError::InvalidEnum => "`pname` is not an accepted value",
        GLError::InvalidValue => "`shader` is not a value generated by OpenGL",
        GLError::InvalidOperation => "`shader` is not a shader object, or `pname` is GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH or GL_SHADER_SOURCE_LENGTH but a shader compiler is not supported",
        _ => "Unknown error"
    }
}

pub struct ShaderBuilder<'a> {
    gl: &'a Context,
    ty: ShaderType,
    source: &'a str
}

impl<'a> ShaderBuilder<'a> {
    fn new(gl: &'a Context, ty: ShaderType, source: &'a str) -> Self {
        ShaderBuilder { gl: gl, ty: ty, source: source }
    }

    pub fn try_unwrap(self) -> Result<Shader, GLError> {
        unsafe {
            let mut shader = try! {
                self.gl.create_shader(self.ty).or_else(|_| {
                    let msg = "Error creating OpenGL shader";
                    Err(GLError::Message(msg.to_owned()))
                })
            };

            self.gl.shader_source(&mut shader, self.source);
            try!(self.gl.compile_shader(&mut shader));
            Ok(shader)
        }
    }

    pub fn unwrap(self) -> Shader {
        self.try_unwrap().unwrap()
    }
}

impl Context {
    pub fn build_shader<'a>(&'a self, ty: ShaderType, source: &'a str)
        -> ShaderBuilder<'a>
    {
        ShaderBuilder::new(self, ty, source)
    }

    pub unsafe fn create_shader(&self, shader_type: ShaderType)
        -> Result<Shader, ()>
    {
        let id = gl::CreateShader(shader_type.gl_enum());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`shaderType` is not an accepted value",
            _ => "Unknown error"
        }
        if id > 0 {
            Ok(Shader { gl_id: id })
        }
        else {
            Err(())
        }
    }

    pub fn shader_source(&self, shader: &mut Shader, source: &str) {
        unsafe {
            let source_ptr = source.as_ptr() as *const GLchar;
            let source_len = source.len() as GLint;

            gl::ShaderSource(shader.gl_id(), 1,
                             &source_ptr as *const *const GLchar,
                             &source_len as *const GLint);
            dbg_gl_error! {
                GLError::InvalidOperation => "`shader` is not a shader object or shader compiler is not supported",
                GLError::InvalidValue => "`shader` is not a value generated by OpenGL or `count` < 0",
                _ => "Unknown error"
            }
        }
    }

    pub fn compile_shader(&self, shader: &mut Shader) -> Result<(), GLError> {
        let success = unsafe {
            gl::CompileShader(shader.gl_id());
            dbg_gl_error! {
                GLError::InvalidOperation => "`shader` is not a shader object or shader compiler is not supported",
                GLError::InvalidValue => "`shader` is not a value generated by OpenGL",
                _ => "Unknown error"
            }

            let mut compile_status : GLint = 0;
            _get_shader_iv(shader,
                           gl::COMPILE_STATUS,
                           &mut compile_status as *mut GLint);

            compile_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            let msg = match self.get_shader_info_log(&shader) {
                Some(s) => { s },
                None => { String::from("[Unknown shader error]") }
            };
            Err(GLError::Message(msg))
        }
    }

    pub fn get_shader_info_log(&self, shader: &Shader) -> Option<String> {
        unsafe {
            let mut info_length : GLint = 0;
            _get_shader_iv(shader,
                           gl::INFO_LOG_LENGTH,
                           &mut info_length as *mut GLint);

            if info_length > 0 {
                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetShaderInfoLog(shader.gl_id(),
                                     info_length,
                                     ptr::null_mut(),
                                     bytes.as_mut_ptr() as *mut GLchar);
                dbg_gl_sanity_check! {
                    GLError::InvalidValue => "`shader` is not a value generated by OpenGL, or `maxLength` < 0",
                    GLError::InvalidOperation => "`shader` is not a shader object",
                    _ => "Unknown error"
                }

                bytes.set_len((info_length - 1) as usize);

                String::from_utf8(bytes).ok()
            }
            else {
                None
            }
        }
    }
}

gl_enum! {
    pub gl_enum ShaderType {
        VertexShader as VERTEX_SHADER = gl::VERTEX_SHADER,
        FragmentShader as FRAGMENT_SHADER = gl::FRAGMENT_SHADER
    }
}
<commit_msg>Add `build_fragment_shader()` and `build_vertex_shader()` helper methods<commit_after>use std::ptr;
use gl;
use gl::types::*;
use context::Context;
use types::GLError;

pub struct Shader {
    gl_id: GLuint
}

impl Shader {
    pub fn gl_id(&self) -> GLuint {
        self.gl_id
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl::DeleteShader(self.gl_id);
        }
    }
}

unsafe fn _get_shader_iv(shader: &Shader,
                         pname: GLenum,
                         params: *mut GLint)
{
    gl::GetShaderiv(shader.gl_id(), pname, params);
    dbg_gl_sanity_check! {
        GLError::InvalidEnum => "`pname` is not an accepted value",
        GLError::InvalidValue => "`shader` is not a value generated by OpenGL",
        GLError::InvalidOperation => "`shader` is not a shader object, or `pname` is GL_COMPILE_STATUS, GL_INFO_LOG_LENGTH or GL_SHADER_SOURCE_LENGTH but a shader compiler is not supported",
        _ => "Unknown error"
    }
}

pub struct ShaderBuilder<'a> {
    gl: &'a Context,
    ty: ShaderType,
    source: &'a str
}

impl<'a> ShaderBuilder<'a> {
    fn new(gl: &'a Context, ty: ShaderType, source: &'a str) -> Self {
        ShaderBuilder { gl: gl, ty: ty, source: source }
    }

    pub fn try_unwrap(self) -> Result<Shader, GLError> {
        unsafe {
            let mut shader = try! {
                self.gl.create_shader(self.ty).or_else(|_| {
                    let msg = "Error creating OpenGL shader";
                    Err(GLError::Message(msg.to_owned()))
                })
            };

            self.gl.shader_source(&mut shader, self.source);
            try!(self.gl.compile_shader(&mut shader));
            Ok(shader)
        }
    }

    pub fn unwrap(self) -> Shader {
        self.try_unwrap().unwrap()
    }
}

impl Context {
    pub fn build_shader<'a>(&'a self, ty: ShaderType, source: &'a str)
        -> ShaderBuilder<'a>
    {
        ShaderBuilder::new(self, ty, source)
    }

    pub fn build_fragment_shader<'a>(&'a self, source: &'a str)
        -> ShaderBuilder<'a>
    {
        ShaderBuilder::new(self, ShaderType::FragmentShader, source)
    }

    pub fn build_vertex_shader<'a>(&'a self, source: &'a str)
        -> ShaderBuilder<'a>
    {
        ShaderBuilder::new(self, ShaderType::VertexShader, source)
    }

    pub unsafe fn create_shader(&self, shader_type: ShaderType)
        -> Result<Shader, ()>
    {
        let id = gl::CreateShader(shader_type.gl_enum());
        dbg_gl_sanity_check! {
            GLError::InvalidEnum => "`shaderType` is not an accepted value",
            _ => "Unknown error"
        }
        if id > 0 {
            Ok(Shader { gl_id: id })
        }
        else {
            Err(())
        }
    }

    pub fn shader_source(&self, shader: &mut Shader, source: &str) {
        unsafe {
            let source_ptr = source.as_ptr() as *const GLchar;
            let source_len = source.len() as GLint;

            gl::ShaderSource(shader.gl_id(), 1,
                             &source_ptr as *const *const GLchar,
                             &source_len as *const GLint);
            dbg_gl_error! {
                GLError::InvalidOperation => "`shader` is not a shader object or shader compiler is not supported",
                GLError::InvalidValue => "`shader` is not a value generated by OpenGL or `count` < 0",
                _ => "Unknown error"
            }
        }
    }

    pub fn compile_shader(&self, shader: &mut Shader) -> Result<(), GLError> {
        let success = unsafe {
            gl::CompileShader(shader.gl_id());
            dbg_gl_error! {
                GLError::InvalidOperation => "`shader` is not a shader object or shader compiler is not supported",
                GLError::InvalidValue => "`shader` is not a value generated by OpenGL",
                _ => "Unknown error"
            }

            let mut compile_status : GLint = 0;
            _get_shader_iv(shader,
                           gl::COMPILE_STATUS,
                           &mut compile_status as *mut GLint);

            compile_status == gl::TRUE as GLint
        };

        if success {
            Ok(())
        }
        else {
            let msg = match self.get_shader_info_log(&shader) {
                Some(s) => { s },
                None => { String::from("[Unknown shader error]") }
            };
            Err(GLError::Message(msg))
        }
    }

    pub fn get_shader_info_log(&self, shader: &Shader) -> Option<String> {
        unsafe {
            let mut info_length : GLint = 0;
            _get_shader_iv(shader,
                           gl::INFO_LOG_LENGTH,
                           &mut info_length as *mut GLint);

            if info_length > 0 {
                let mut bytes = Vec::<u8>::with_capacity(info_length as usize);

                gl::GetShaderInfoLog(shader.gl_id(),
                                     info_length,
                                     ptr::null_mut(),
                                     bytes.as_mut_ptr() as *mut GLchar);
                dbg_gl_sanity_check! {
                    GLError::InvalidValue => "`shader` is not a value generated by OpenGL, or `maxLength` < 0",
                    GLError::InvalidOperation => "`shader` is not a shader object",
                    _ => "Unknown error"
                }

                bytes.set_len((info_length - 1) as usize);

                String::from_utf8(bytes).ok()
            }
            else {
                None
            }
        }
    }
}

gl_enum! {
    pub gl_enum ShaderType {
        VertexShader as VERTEX_SHADER = gl::VERTEX_SHADER,
        FragmentShader as FRAGMENT_SHADER = gl::FRAGMENT_SHADER
    }
}
<|endoftext|>


<commit_before>use ::{Guard, Nav};

use std::cell::RefCell;
use std::rc::Rc;

struct TreeInternal<T> {
    data: RefCell<T>, children: RefCell<Vec<Tree<T>>>,
}

pub struct Tree<T> {
    internal: Rc<TreeInternal<T>>,
}

pub struct DataGuard<'a, T: 'a> {
    cell: &'a RefCell<T>,
}

impl<'a, T: 'a> Guard<'a, RefCell<T>> for DataGuard<'a, T> {
    fn super_deref<'s>(&'s self) -> &'a RefCell<T> {
        self.cell
    }
}

pub struct Navigator<'a, T: 'a> {
    here: &'a Tree<T>, path: Vec<&'a Tree<T>>,
}

impl<'a, T: 'a> Nav<'a> for Navigator<'a, T> {
    type Data = RefCell<T>;
    type DataGuard = DataGuard<'a, T>;

    fn seek_sibling(&mut self, offset: isize) {
        // TODO
    }

    fn seek_child(&mut self, index: usize) {
        // TODO
    }

    fn child_count(&self) -> usize {
        self.here.internal.children.borrow().len()
    }

    fn is_root(&self) -> bool {
        self.path.is_empty()
    }

    fn to_parent(&mut self) {
        self.here = self.path.pop().expect("Already at root");
    }

    fn data(&self) -> DataGuard<'a, T> {
        DataGuard { cell: &self.here.internal.data, }
    }
}
<commit_msg>Progress in getting shared into shape.<commit_after>use ::{Guard, Nav};
use ::util::{ChildIndex, SiblingIndex};

use std::cell::RefCell;
use std::rc::Rc;

struct TreeInternal<T> {
    data: RefCell<T>, children: RefCell<Vec<Tree<T>>>,
}

pub struct Tree<T> {
    internal: Rc<TreeInternal<T>>,
}

pub struct DataGuard<'a, T: 'a> {
    cell: &'a RefCell<T>,
}

impl<'a, T: 'a> Guard<'a, RefCell<T>> for DataGuard<'a, T> {
    fn super_deref<'s>(&'s self) -> &'a RefCell<T> {
        self.cell
    }
}

pub struct Navigator<'a, T: 'a> {
    here: &'a Tree<T>, path: Vec<(&'a Tree<T>, usize)>,
}

impl<'a, T: 'a> Nav<'a> for Navigator<'a, T> {
    type Data = RefCell<T>;
    type DataGuard = DataGuard<'a, T>;

    fn seek_sibling(&mut self, offset: isize) {
        let new_index = {
            if self.at_root() {
                SiblingIndex::Root
            } else {
                let (parent, here_index) = self.path[self.path.len() - 1];
                SiblingIndex::compute(parent.internal.children.borrow().len(),
                                      here_index,
                                      offset)
            }
        }.unwrap();
        let (parent, _) = self.path.pop().unwrap();
        self.path.push((parent, new_index));
        self.here = &parent.internal.children.borrow()[new_index];
    }

    fn seek_child(&mut self, index: usize) {
        let new_index =
            ChildIndex::compute(self.here.internal.children.borrow().len(), index).unwrap();
        self.path.push((self.here, new_index));
        self.here = &self.here.internal.children.borrow()[new_index];
    }

    fn child_count(&self) -> usize {
        self.here.internal.children.borrow().len()
    }

    fn at_root(&self) -> bool {
        self.path.is_empty()
    }

    fn to_parent(&mut self) {
        let (parent, _) = self.path.pop().expect("already at root");
        self.here = parent;
    }

    fn to_root(&mut self) {
        if ! self.at_root() {
            let (root, _) = self.path[0];
            self.here = root;
            self.path.clear();
        }
    }

    fn data(&self) -> DataGuard<'a, T> {
        DataGuard { cell: &self.here.internal.data, }
    }
}
<|endoftext|>


<commit_before>use std::any::{Any, TypeId};
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::hash_map::HashMap;

pub type CallbackID = usize;

pub struct Event<T>
{
   pub args: T
}

struct CallbackEntry<T>
{
   callback: Rc<RefCell<FnMut(&Event<T>)>>
}

struct DataEntry<T>
{
   target: Rc<Any>,
   callback: Rc<RefCell<FnMut(&Any, &Event<T>)>>
}

pub struct Signal<T>
{
   entries: Vec<Box<SignalEntry<T>>>
}

trait SignalEntry<T>
{
//   fn get_id() -> usize;
   fn call(&self, event: &Event<T>);
}

impl<T> SignalEntry<T> for CallbackEntry<T>
{
   fn call(&self, event: &Event<T>)
   {
      (&mut *(self.callback.borrow_mut()))(&event);
   }
}

impl<T> SignalEntry<T> for DataEntry<T>
{
   fn call(&self, event: &Event<T>)
   {
      (&mut *(self.callback.borrow_mut()))(&(*self.target), &event);
   }
}

impl<T> Signal<T>
{
   pub fn new() -> Signal<T>
   {
      Signal {entries: Vec::<Box<SignalEntry<T>>>::new()}
   }

   pub fn connect_with_data<F>(&mut self, data: Rc<Any>, callback: F)
      where F: FnMut(&Any, &Event<T>) + 'static,
            T: 'static
   {
      let entry: DataEntry<T>;
      let cell: Rc<RefCell<F>>;

      println!("Callback passed:  {:?}", callback as *mut F);

      cell = Rc::new(RefCell::new(callback));
      entry = DataEntry {target: data, callback: cell};
      self.entries.push(Box::new(entry));
   }

   pub fn connect<F>(&mut self, callback: F)
      where F: FnMut(&Event<T>) + 'static,
            T: 'static
   {
      let entry: CallbackEntry<T>;
      let cell: Rc<RefCell<F>>;

      cell = Rc::new(RefCell::new(callback));
      entry = CallbackEntry {callback: cell};
      self.entries.push(Box::new(entry));
   }

   pub fn disconnect_with_data<F>(&mut self, callback: F)
      where F: FnMut(&Any, &Event<T>) + 'static,
            T: 'static
   {
      println!("Callback passed:  {:?}", callback as *mut F);
   }

   pub fn call(&mut self, event: &Event<T>)
   {
      for entry in self.entries.iter()
      {
         entry.call(event);
      }
   }
}
<commit_msg>Forgot to remove the print statements that stopped the code from building.<commit_after>use std::any::{Any, TypeId};
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::hash_map::HashMap;

pub type CallbackID = usize;

pub struct Event<T>
{
   pub args: T
}

struct CallbackEntry<T>
{
   callback: Rc<RefCell<FnMut(&Event<T>)>>
}

struct DataEntry<T>
{
   target: Rc<Any>,
   callback: Rc<RefCell<FnMut(&Any, &Event<T>)>>
}

pub struct Signal<T>
{
   entries: Vec<Box<SignalEntry<T>>>
}

trait SignalEntry<T>
{
//   fn get_id() -> usize;
   fn call(&self, event: &Event<T>);
}

impl<T> SignalEntry<T> for CallbackEntry<T>
{
   fn call(&self, event: &Event<T>)
   {
      (&mut *(self.callback.borrow_mut()))(&event);
   }
}

impl<T> SignalEntry<T> for DataEntry<T>
{
   fn call(&self, event: &Event<T>)
   {
      (&mut *(self.callback.borrow_mut()))(&(*self.target), &event);
   }
}

impl<T> Signal<T>
{
   pub fn new() -> Signal<T>
   {
      Signal {entries: Vec::<Box<SignalEntry<T>>>::new()}
   }

   pub fn connect_with_data<F>(&mut self, data: Rc<Any>, callback: F)
      where F: FnMut(&Any, &Event<T>) + 'static,
            T: 'static
   {
      let entry: DataEntry<T>;
      let cell: Rc<RefCell<F>>;

      cell = Rc::new(RefCell::new(callback));
      entry = DataEntry {target: data, callback: cell};
      self.entries.push(Box::new(entry));
   }

   pub fn connect<F>(&mut self, callback: F)
      where F: FnMut(&Event<T>) + 'static,
            T: 'static
   {
      let entry: CallbackEntry<T>;
      let cell: Rc<RefCell<F>>;

      cell = Rc::new(RefCell::new(callback));
      entry = CallbackEntry {callback: cell};
      self.entries.push(Box::new(entry));
   }

   pub fn disconnect_with_data<F>(&mut self, callback: F)
      where F: FnMut(&Any, &Event<T>) + 'static,
            T: 'static
   {
   }

   pub fn call(&mut self, event: &Event<T>)
   {
      for entry in self.entries.iter()
      {
         entry.call(event);
      }
   }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::sync::mpsc;
use std::fmt;
use types::{MaybeOwned, Storage};
use stream::Stream;

use self::SigValue::*;

/// Represents a discrete value that changes over time.
///
/// Signals are usually constructed by stream operations and can be read using the `sample` or
/// `sample_with` methods.
#[derive(Debug)]
pub struct Signal<T>(SigValue<T>);

enum SigValue<T>
{
    /// A signal with constant value.
    ///
    /// We store the value in a Rc to provide Clone support without a `T: Clone` bound.
    Constant(Rc<T>),
    /// A signal that generates it's values from a function.
    ///
    /// This is produced by `Signal::from_fn`
    Dynamic(Rc<Fn() -> T>),
    /// A signal that contains shared data.
    ///
    /// This is produced by stream methods that create a signal.
    /// It contains an updater function and a value storage.
    Shared(Rc<Fn()>, Rc<Storage<T>>),
    /// A signal that contains a signal, and allows sampling the inner signal directly.
    ///
    /// This is produced by `Signal::switch`
    Nested(Rc<Fn() -> Signal<T>>),
}

impl<T> Signal<T>
{
    /// Creates a signal with constant value.
    ///
    /// The value is assumed to be constant, so changing it while it's stored on the
    /// signal is a logic error and will cause unexpected results.
    pub fn constant<V: Into<Rc<T>>>(val: V) -> Self
    {
        Signal(Constant(val.into()))
    }

    /// Creates a signal that samples it's values from an external source.
    ///
    /// The closure is meant to sample a continuous value from the real world,
    /// so the signal value is assumed to be always changing.
    pub fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        Signal(Dynamic(Rc::new(f)))
    }

    /// Checks if the signal has changed since the last time it was sampled.
    pub fn has_changed(&self) -> bool
    {
        match self.0 {
            Constant(_) => false,
            Dynamic(_) | Nested(_) => true,
            Shared(_, ref st) => st.must_update(),
        }
    }

    /// Sample by reference.
    ///
    /// This is meant to be the most efficient way when cloning is undesirable,
    /// but it requires a callback to prevent outliving internal borrows.
    pub fn sample_with<F, R>(&self, cb: F) -> R
        where F: FnOnce(MaybeOwned<T>) -> R
    {
        match self.0
        {
            Constant(ref val) => cb(MaybeOwned::Borrowed(val)),
            Dynamic(ref f) => cb(MaybeOwned::Owned(f())),
            Shared(ref f, ref st) => { f(); st.borrow(cb) },
            Nested(ref f) => f().sample_with(cb),
        }
    }
}

impl<T: Clone> Signal<T>
{
    /// Sample by value.
    ///
    /// This will clone the content of the signal.
    pub fn sample(&self) -> T
    {
        match self.0
        {
            Constant(ref val) => (**val).clone(),
            Dynamic(ref f) => f(),
            Shared(ref f, ref st) => { f(); st.get() },
            Nested(ref f) => f().sample(),
        }
    }
}

impl<T: 'static> Signal<T>
{
    /// Maps a signal with the provided function.
    ///
    /// The closure is called only when the parent signal changes.
    pub fn map<F, R>(&self, f: F) -> Signal<R>
        where F: Fn(MaybeOwned<T>) -> R + 'static,
        R: 'static
    {
        match self.0 {
            // constant signal: apply f once to produce another constant signal
            Constant(ref val) => {
                Signal::constant(f(MaybeOwned::Borrowed(val)))
            }
            // shared signal: apply f only when the parent signal has changed
            Shared(ref upd_, ref st) => {
                let updater = upd_.clone();
                let parent_st = st.clone();
                // the storage inherits the root serial so we can track changes at the source
                let storage = Rc::new(Storage::empty(st.root_ser.clone()));
                let st_cloned = storage.clone();
                Signal(Shared(Rc::new(move || {
                    if storage.must_update()
                    {
                        // sample and map the parent signal
                        updater();
                        storage.set_local(parent_st.borrow(&f))
                    }
                }), st_cloned))
            }
            // dynamic/nested signal: apply f unconditionally
            Dynamic(_) | Nested(_) => {
                let this = self.clone();
                Signal::from_fn(move || this.sample_with(&f))
            }
        }
    }

    /// Samples the value of this signal every time the trigger stream fires.
    pub fn snapshot<S, F, R>(&self, trigger: &Stream<S>, f: F) -> Stream<R>
        where F: Fn(MaybeOwned<T>, MaybeOwned<S>) -> R + 'static,
        S: 'static, R: 'static
    {
        let this = self.clone();
        trigger.map(move |b| this.sample_with(|a| f(a, b)))
    }

    /// Creates a signal from a shared value.
    pub(crate) fn from_storage<A: 'static>(storage: Rc<Storage<T>>, keepalive: A) -> Self
    {
        Signal(Shared(Rc::new(move || {
            // the closure owns and does type erasure on the value
            let _keepalive = &keepalive;
        }), storage))
    }

    /// Stores the last value sent to a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and returns the last value seen.
    pub fn from_channel(initial: T, rx: mpsc::Receiver<T>) -> Self
    {
        let storage = Rc::new(Storage::new(initial));
        let st_cloned = storage.clone();
        Signal(Shared(Rc::new(move || {
            let last = rx.try_iter().last();
            if let Some(val) = last { storage.set(val); }
        }), st_cloned))
    }

    /// Creates a signal that folds the values from a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and folds them using the current signal value as the
    /// initial accumulator state.
    pub fn fold_channel<V, F>(initial: T, rx: mpsc::Receiver<V>, f: F) -> Self
        where F: Fn(T, V) -> T + 'static,
        V: 'static
    {
        let storage = Rc::new(Storage::new(initial));
        let st_cloned = storage.clone();
        Signal(Shared(Rc::new(move || {
            if let Ok(first) = rx.try_recv()
            {
                let acc = f(storage.take(), first);
                let current = rx.try_iter().fold(acc, &f);
                storage.set(current);
            }
        }), st_cloned))
    }
}

impl<T: 'static> Signal<Signal<T>>
{
    /// Creates a new signal that samples the inner value of a nested signal.
    pub fn switch(&self) -> Signal<T>
    {
        match self.0
        {
            // constant signal: just extract the inner signal
            Constant(ref sig) => (**sig).clone(),
            // dynamic signal: re-label as nested
            Dynamic(ref f) => Signal(Nested(f.clone())),
            // shared signal: sample to extract the inner signal
            Shared(ref upd, ref st) => {
                let updater = upd.clone();
                let storage = st.clone();
                Signal(Nested(Rc::new(move || { updater(); storage.get() })))
            }
            // nested signal: remove one layer
            Nested(ref f_) => {
                let f = f_.clone();
                Signal(Nested(Rc::new(move || f().sample())))
            }
        }
    }
}

impl<T: Default> Default for Signal<T>
{
    /// Creates a constant signal with T's default value.
    #[inline]
    fn default() -> Self
    {
        Signal::constant(T::default())
    }
}

impl<T> From<T> for Signal<T>
{
    /// Creates a constant signal from T.
    #[inline]
    fn from(val: T) -> Self
    {
        Signal::constant(val)
    }
}

impl<T> From<Rc<T>> for Signal<T>
{
    /// Creates a constant signal from T (avoids re-wrapping the Rc).
    #[inline]
    fn from(val: Rc<T>) -> Self
    {
        Signal(Constant(val))
    }
}

// the derive impl adds a `T: Clone` we don't want
impl<T> Clone for Signal<T>
{
    /// Creates a copy of this signal that references the same value.
    fn clone(&self) -> Self
    {
        Signal(match self.0
        {
            Constant(ref val) => Constant(val.clone()),
            Dynamic(ref rf) => Dynamic(rf.clone()),
            Shared(ref rf, ref st) => Shared(rf.clone(), st.clone()),
            Nested(ref rf) => Nested(rf.clone()),
        })
    }
}

impl<T: fmt::Debug> fmt::Debug for SigValue<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            Constant(ref val) => write!(f, "Constant({:?})", val),
            Dynamic(ref rf) => write!(f, "Dynamic(Fn@{:p})", rf),
            Shared(ref rf, ref st) => write!(f, "Shared(Fn@{:p}, {:?})", rf, st),
            Nested(ref rf) => write!(f, "Nested(Fn@{:p})", rf),
        }
    }
}

impl<T: fmt::Display> fmt::Display for Signal<T>
{
    /// Samples the signal and formats the value.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        self.sample_with(|val| fmt::Display::fmt(&*val, f))
    }
}

#[cfg(test)]
mod tests
{
    use super::*;
    use std::rc::Rc;
    use std::cell::Cell;
    use std::time::Instant;

    #[test]
    fn signal_basic()
    {
        let signal = Signal::constant(42);
        let double = signal.map(|a| *a * 2);
        let plusone = double.map(|a| *a + 1);
        assert_eq!(signal.sample(), 42);
        assert_eq!(double.sample(), 84);
        assert_eq!(plusone.sample(), 85);
        signal.sample_with(|val| assert_eq!(*val, 42));
    }

    #[test]
    fn signal_shared()
    {
        let st = Rc::new(Storage::new(1));
        let signal = Signal::from_storage(st.clone(), ());
        let double = signal.map(|a| *a * 2);

        assert_eq!(signal.sample(), 1);
        assert_eq!(double.sample(), 2);
        st.set(42);
        assert_eq!(signal.sample(), 42);
        assert_eq!(double.sample(), 84);
    }

    #[test]
    fn signal_dynamic()
    {
        let t = Instant::now();
        let signal = Signal::from_fn(move || t);
        assert_eq!(signal.sample(), t);
        signal.sample_with(|val| assert_eq!(*val, t));

        let n = Rc::new(Cell::new(1));
        let cloned = n.clone();
        let signal = Signal::from_fn(move || cloned.get());
        let double = signal.map(|a| *a * 2);
        let plusone = double.map(|a| *a + 1);
        assert_eq!(signal.sample(), 1);
        assert_eq!(double.sample(), 2);
        assert_eq!(plusone.sample(), 3);
        n.set(13);
        assert_eq!(signal.sample(), 13);
        assert_eq!(double.sample(), 26);
        assert_eq!(plusone.sample(), 27);
    }
}
<commit_msg>added internal helper to simplify code<commit_after>use std::rc::Rc;
use std::sync::mpsc;
use std::fmt;
use types::{MaybeOwned, Storage};
use stream::Stream;

use self::SigValue::*;

/// Represents a discrete value that changes over time.
///
/// Signals are usually constructed by stream operations and can be read using the `sample` or
/// `sample_with` methods.
#[derive(Debug)]
pub struct Signal<T>(SigValue<T>);

enum SigValue<T>
{
    /// A signal with constant value.
    ///
    /// We store the value in a Rc to provide Clone support without a `T: Clone` bound.
    Constant(Rc<T>),
    /// A signal that generates it's values from a function.
    ///
    /// This is produced by `Signal::from_fn`
    Dynamic(Rc<Fn() -> T>),
    /// A signal that contains shared data.
    ///
    /// This is produced by stream methods that create a signal.
    /// It contains an updater function and a value storage.
    Shared(Rc<Fn()>, Rc<Storage<T>>),
    /// A signal that contains a signal, and allows sampling the inner signal directly.
    ///
    /// This is produced by `Signal::switch`
    Nested(Rc<Fn() -> Signal<T>>),
}

impl<T> Signal<T>
{
    /// Creates a signal with constant value.
    ///
    /// The value is assumed to be constant, so changing it while it's stored on the
    /// signal is a logic error and will cause unexpected results.
    pub fn constant<V: Into<Rc<T>>>(val: V) -> Self
    {
        Signal(Constant(val.into()))
    }

    /// Creates a signal that samples it's values from an external source.
    ///
    /// The closure is meant to sample a continuous value from the real world,
    /// so the signal value is assumed to be always changing.
    pub fn from_fn<F>(f: F) -> Self
        where F: Fn() -> T + 'static
    {
        Signal(Dynamic(Rc::new(f)))
    }

    /// Creates a new shared signal.
    fn shared<F>(storage: Rc<Storage<T>>, updater: F) -> Self
        where F: Fn() + 'static
    {
        Signal(Shared(Rc::new(updater), storage))
    }

    /// Checks if the signal has changed since the last time it was sampled.
    pub fn has_changed(&self) -> bool
    {
        match self.0 {
            Constant(_) => false,
            Dynamic(_) | Nested(_) => true,
            Shared(_, ref st) => st.must_update(),
        }
    }

    /// Sample by reference.
    ///
    /// This is meant to be the most efficient way when cloning is undesirable,
    /// but it requires a callback to prevent outliving internal borrows.
    pub fn sample_with<F, R>(&self, cb: F) -> R
        where F: FnOnce(MaybeOwned<T>) -> R
    {
        match self.0
        {
            Constant(ref val) => cb(MaybeOwned::Borrowed(val)),
            Dynamic(ref f) => cb(MaybeOwned::Owned(f())),
            Shared(ref f, ref st) => { f(); st.borrow(cb) },
            Nested(ref f) => f().sample_with(cb),
        }
    }
}

impl<T: Clone> Signal<T>
{
    /// Sample by value.
    ///
    /// This will clone the content of the signal.
    pub fn sample(&self) -> T
    {
        match self.0
        {
            Constant(ref val) => (**val).clone(),
            Dynamic(ref f) => f(),
            Shared(ref f, ref st) => { f(); st.get() },
            Nested(ref f) => f().sample(),
        }
    }
}

impl<T: 'static> Signal<T>
{
    /// Maps a signal with the provided function.
    ///
    /// The closure is called only when the parent signal changes.
    pub fn map<F, R>(&self, f: F) -> Signal<R>
        where F: Fn(MaybeOwned<T>) -> R + 'static,
        R: 'static
    {
        match self.0 {
            // constant signal: apply f once to produce another constant signal
            Constant(ref val) => {
                Signal::constant(f(MaybeOwned::Borrowed(val)))
            }
            // shared signal: apply f only when the parent signal has changed
            Shared(ref upd_, ref st) => {
                let updater = upd_.clone();
                let parent_st = st.clone();
                // the storage inherits the root serial so we can track changes at the source
                let storage = Rc::new(Storage::empty(st.root_ser.clone()));
                Signal::shared(storage.clone(), move || {
                    if storage.must_update()
                    {
                        // sample and map the parent signal
                        updater();
                        storage.set_local(parent_st.borrow(&f))
                    }
                })
            }
            // dynamic/nested signal: apply f unconditionally
            Dynamic(_) | Nested(_) => {
                let this = self.clone();
                Signal::from_fn(move || this.sample_with(&f))
            }
        }
    }

    /// Samples the value of this signal every time the trigger stream fires.
    pub fn snapshot<S, F, R>(&self, trigger: &Stream<S>, f: F) -> Stream<R>
        where F: Fn(MaybeOwned<T>, MaybeOwned<S>) -> R + 'static,
        S: 'static, R: 'static
    {
        let this = self.clone();
        trigger.map(move |b| this.sample_with(|a| f(a, b)))
    }

    /// Creates a signal from a shared value.
    pub(crate) fn from_storage<A: 'static>(storage: Rc<Storage<T>>, keepalive: A) -> Self
    {
        Signal::shared(storage, move || {
            // the closure owns and does type erasure on the value
            let _keepalive = &keepalive;
        })
    }

    /// Stores the last value sent to a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and returns the last value seen.
    pub fn from_channel(initial: T, rx: mpsc::Receiver<T>) -> Self
    {
        let storage = Rc::new(Storage::new(initial));
        Signal::shared(storage.clone(), move || {
            let last = rx.try_iter().last();
            if let Some(val) = last { storage.set(val); }
        })
    }

    /// Creates a signal that folds the values from a channel.
    ///
    /// When sampled, the resulting signal consumes all the current values on the channel
    /// (using non-blocking operations) and folds them using the current signal value as the
    /// initial accumulator state.
    pub fn fold_channel<V, F>(initial: T, rx: mpsc::Receiver<V>, f: F) -> Self
        where F: Fn(T, V) -> T + 'static,
        V: 'static
    {
        let storage = Rc::new(Storage::new(initial));
        Signal::shared(storage.clone(), move || {
            if let Ok(first) = rx.try_recv()
            {
                let acc = f(storage.take(), first);
                let current = rx.try_iter().fold(acc, &f);
                storage.set(current);
            }
        })
    }
}

impl<T: 'static> Signal<Signal<T>>
{
    /// Creates a new signal that samples the inner value of a nested signal.
    pub fn switch(&self) -> Signal<T>
    {
        match self.0
        {
            // constant signal: just extract the inner signal
            Constant(ref sig) => (**sig).clone(),
            // dynamic signal: re-label as nested
            Dynamic(ref f) => Signal(Nested(f.clone())),
            // shared signal: sample to extract the inner signal
            Shared(ref upd, ref st) => {
                let updater = upd.clone();
                let storage = st.clone();
                Signal(Nested(Rc::new(move || { updater(); storage.get() })))
            }
            // nested signal: remove one layer
            Nested(ref f_) => {
                let f = f_.clone();
                Signal(Nested(Rc::new(move || f().sample())))
            }
        }
    }
}

impl<T: Default> Default for Signal<T>
{
    /// Creates a constant signal with T's default value.
    #[inline]
    fn default() -> Self
    {
        Signal::constant(T::default())
    }
}

impl<T> From<T> for Signal<T>
{
    /// Creates a constant signal from T.
    #[inline]
    fn from(val: T) -> Self
    {
        Signal::constant(val)
    }
}

impl<T> From<Rc<T>> for Signal<T>
{
    /// Creates a constant signal from T (avoids re-wrapping the Rc).
    #[inline]
    fn from(val: Rc<T>) -> Self
    {
        Signal(Constant(val))
    }
}

// the derive impl adds a `T: Clone` we don't want
impl<T> Clone for Signal<T>
{
    /// Creates a copy of this signal that references the same value.
    fn clone(&self) -> Self
    {
        Signal(match self.0
        {
            Constant(ref val) => Constant(val.clone()),
            Dynamic(ref rf) => Dynamic(rf.clone()),
            Shared(ref rf, ref st) => Shared(rf.clone(), st.clone()),
            Nested(ref rf) => Nested(rf.clone()),
        })
    }
}

impl<T: fmt::Debug> fmt::Debug for SigValue<T>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            Constant(ref val) => write!(f, "Constant({:?})", val),
            Dynamic(ref rf) => write!(f, "Dynamic(Fn@{:p})", rf),
            Shared(ref rf, ref st) => write!(f, "Shared(Fn@{:p}, {:?})", rf, st),
            Nested(ref rf) => write!(f, "Nested(Fn@{:p})", rf),
        }
    }
}

impl<T: fmt::Display> fmt::Display for Signal<T>
{
    /// Samples the signal and formats the value.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        self.sample_with(|val| fmt::Display::fmt(&*val, f))
    }
}

#[cfg(test)]
mod tests
{
    use super::*;
    use std::rc::Rc;
    use std::cell::Cell;
    use std::time::Instant;

    #[test]
    fn signal_basic()
    {
        let signal = Signal::constant(42);
        let double = signal.map(|a| *a * 2);
        let plusone = double.map(|a| *a + 1);
        assert_eq!(signal.sample(), 42);
        assert_eq!(double.sample(), 84);
        assert_eq!(plusone.sample(), 85);
        signal.sample_with(|val| assert_eq!(*val, 42));
    }

    #[test]
    fn signal_shared()
    {
        let st = Rc::new(Storage::new(1));
        let signal = Signal::from_storage(st.clone(), ());
        let double = signal.map(|a| *a * 2);

        assert_eq!(signal.sample(), 1);
        assert_eq!(double.sample(), 2);
        st.set(42);
        assert_eq!(signal.sample(), 42);
        assert_eq!(double.sample(), 84);
    }

    #[test]
    fn signal_dynamic()
    {
        let t = Instant::now();
        let signal = Signal::from_fn(move || t);
        assert_eq!(signal.sample(), t);
        signal.sample_with(|val| assert_eq!(*val, t));

        let n = Rc::new(Cell::new(1));
        let cloned = n.clone();
        let signal = Signal::from_fn(move || cloned.get());
        let double = signal.map(|a| *a * 2);
        let plusone = double.map(|a| *a + 1);
        assert_eq!(signal.sample(), 1);
        assert_eq!(double.sample(), 2);
        assert_eq!(plusone.sample(), 3);
        n.set(13);
        assert_eq!(signal.sample(), 13);
        assert_eq!(double.sample(), 26);
        assert_eq!(plusone.sample(), 27);
    }
}
<|endoftext|>


<commit_before>use std::thread::{self};
use std::sync::{Arc, Mutex};
use std::io::Read;
use std::net::TcpStream;
use std::mem;
use hyper::server::{Handler, Server, Request, Response};
use hyper::header::ContentLength;
use hyper::method::{Method};
use hyper::status::StatusCode;
use serde_json;
use {Matcher, Mock, MockResponse, SERVER_ADDRESS};

#[derive(Debug)]
enum CreateMockError {
    MethodMissing,
    PathMissing,
    ContentLengthMissing,
    InvalidMockResponse,
}

struct RequestHandler {
    mocks: Arc<Mutex<Vec<Mock>>>,
}

impl RequestHandler {
    pub fn new(mocks: Arc<Mutex<Vec<Mock>>>) -> Self {
        RequestHandler {
            mocks: mocks,
        }
    }

    #[allow(unused_variables)]
    fn handle_create_mock(&self, request: Request, mut response: Response) {
        match Self::mock_from(request) {
            Ok(mock) => {
                self.mocks.lock().unwrap().push(mock);
            },
            Err(e) => {
                // TODO: implement Display for CreateMockError
                mem::replace(response.status_mut(), StatusCode::UnprocessableEntity);
            }
        }
    }

    #[allow(unused_variables)]
    fn handle_delete_mocks(&self, request: Request, response: Response) {
        match request.headers.iter().find(|header| { header.name().to_lowercase() == "x-mock-id" }) {
            // Remove the element with x-mock-id
            Some(header) => {
                let id = header.value_string();
                let mut mocks = self.mocks.lock().unwrap();
                match mocks.iter().position(|mock| mock.id == id) {
                    Some(pos) => { mocks.remove(pos); },
                    None => {},
                };
            },
            // Remove all elements
            None => { self.mocks.lock().unwrap().clear(); }
        }
    }

    fn handle_default(&self, request: Request, mut response: Response) {
        let mocks = self.mocks.lock().unwrap();

        match mocks.iter().rev().find(|mock| mock.matches(&request)) {
            Some(mock) => {
                // Set the response status code
                // TODO: StatusCode::Unregistered labels everything as `<unknown status code>`
                mem::replace(response.status_mut(), StatusCode::Unregistered(mock.response.status as u16));

                // Set the response headers
                for (field, value) in &mock.response.headers {
                    response.headers_mut().set_raw(field.to_owned(), vec!(value.as_bytes().to_vec()));
                }

                // Set the response body
                response.send(mock.response.body.as_bytes()).unwrap();
            },
            None => {
                mem::replace(response.status_mut(), StatusCode::NotImplemented);
                response.send("".as_bytes()).unwrap();
            },
        };
    }

    fn mock_from(request: Request) -> Result<Mock, CreateMockError> {
        let method: String = try!(
            request.headers.iter()
                .find(|header| { header.name().to_lowercase() == "x-mock-method" })
                .ok_or(CreateMockError::MethodMissing)
            ).value_string();

        let path: String = try!(
            request.headers.iter()
                .find(|header| { header.name().to_lowercase() == "x-mock-path" })
                .ok_or(CreateMockError::PathMissing)
            ).value_string();

        let mut mock = Mock::new(&method, &path);

        match request.headers.iter().find(|header| { header.name().to_lowercase() == "x-mock-id" }) {
            Some(header) => { mock.id = header.value_string(); },
            None => {},
        };

        for header in request.headers.iter() {
            let field = header.name().to_lowercase();
            if field.starts_with("x-mock-") && field != "x-mock-id" && field != "x-mock-method" && field != "x-mock-path" {
                let (header_field, header_value) =
                    match field.as_ref() {
                        "x-mock-header-any" => (header.value_string(), Matcher::Any),
                        "x-mock-header-missing" => (header.value_string(), Matcher::Missing),
                        _ => (field.replace("x-mock-", ""), Matcher::Exact(header.value_string())),
                    };

                mock.match_header(&header_field, header_value);
            }
        }

        let content_length: ContentLength = *try!(request.headers.get().ok_or(CreateMockError::ContentLengthMissing));

        let mut body = String::new();
        request.take(content_length.0).read_to_string(&mut body).unwrap();

        let response: MockResponse = try!(serde_json::from_str(&body).map_err(|_| CreateMockError::InvalidMockResponse));
        mock.response = response;

        Ok(mock)
    }
}

impl Handler for RequestHandler {
    fn handle(&self, request: Request, response: Response) {
        match (&request.method, &*request.uri.to_string()) {
            (&Method::Post, "/mocks") => self.handle_create_mock(request, response),
            (&Method::Delete, "/mocks") => self.handle_delete_mocks(request, response),
            _ => self.handle_default(request, response),
        };
    }
}

pub fn try_start() {
    if is_listening() { return }

    start()
}

fn start() {
    thread::spawn(move || {
        let mocks: Arc<Mutex<Vec<Mock>>> = Arc::new(Mutex::new(vec!()));

        match Server::http(SERVER_ADDRESS) {
            Ok(server) => { server.handle(RequestHandler::new(mocks)).unwrap(); },
            Err(_) => {},
        };
    });

    while !is_listening() {}
}

fn is_listening() -> bool {
    TcpStream::connect(SERVER_ADDRESS).is_ok()
}
<commit_msg>Expose mock server errors in the server response<commit_after>use std::thread::{self};
use std::sync::{Arc, Mutex};
use std::io::Read;
use std::net::TcpStream;
use std::mem;
use hyper::server::{Handler, Server, Request, Response};
use hyper::header::ContentLength;
use hyper::method::{Method};
use hyper::status::StatusCode;
use serde_json;
use {Matcher, Mock, MockResponse, SERVER_ADDRESS};

#[derive(Debug)]
enum CreateMockError {
    MethodMissing,
    PathMissing,
    ContentLengthMissing,
    InvalidMockResponse,
}

struct RequestHandler {
    mocks: Arc<Mutex<Vec<Mock>>>,
}

impl RequestHandler {
    pub fn new(mocks: Arc<Mutex<Vec<Mock>>>) -> Self {
        RequestHandler {
            mocks: mocks,
        }
    }

    #[allow(unused_variables)]
    fn handle_create_mock(&self, request: Request, mut response: Response) {
        match Self::mock_from(request) {
            Ok(mock) => {
                self.mocks.lock().unwrap().push(mock);
            },
            Err(e) => {
                *response.status_mut() = StatusCode::UnprocessableEntity;
                let _ = response.send(&format!("{:?}", e).as_bytes());
            }
        }
    }

    #[allow(unused_variables)]
    fn handle_delete_mocks(&self, request: Request, response: Response) {
        match request.headers.iter().find(|header| { header.name().to_lowercase() == "x-mock-id" }) {
            // Remove the element with x-mock-id
            Some(header) => {
                let id = header.value_string();
                let mut mocks = self.mocks.lock().unwrap();
                match mocks.iter().position(|mock| mock.id == id) {
                    Some(pos) => { mocks.remove(pos); },
                    None => {},
                };
            },
            // Remove all elements
            None => { self.mocks.lock().unwrap().clear(); }
        }
    }

    fn handle_default(&self, request: Request, mut response: Response) {
        let mocks = self.mocks.lock().unwrap();

        match mocks.iter().rev().find(|mock| mock.matches(&request)) {
            Some(mock) => {
                // Set the response status code
                // TODO: StatusCode::Unregistered labels everything as `<unknown status code>`
                mem::replace(response.status_mut(), StatusCode::Unregistered(mock.response.status as u16));

                // Set the response headers
                for (field, value) in &mock.response.headers {
                    response.headers_mut().set_raw(field.to_owned(), vec!(value.as_bytes().to_vec()));
                }

                // Set the response body
                response.send(mock.response.body.as_bytes()).unwrap();
            },
            None => {
                mem::replace(response.status_mut(), StatusCode::NotImplemented);
                response.send("".as_bytes()).unwrap();
            },
        };
    }

    fn mock_from(request: Request) -> Result<Mock, CreateMockError> {
        let method: String = try!(
            request.headers.iter()
                .find(|header| { header.name().to_lowercase() == "x-mock-method" })
                .ok_or(CreateMockError::MethodMissing)
            ).value_string();

        let path: String = try!(
            request.headers.iter()
                .find(|header| { header.name().to_lowercase() == "x-mock-path" })
                .ok_or(CreateMockError::PathMissing)
            ).value_string();

        let mut mock = Mock::new(&method, &path);

        match request.headers.iter().find(|header| { header.name().to_lowercase() == "x-mock-id" }) {
            Some(header) => { mock.id = header.value_string(); },
            None => {},
        };

        for header in request.headers.iter() {
            let field = header.name().to_lowercase();
            if field.starts_with("x-mock-") && field != "x-mock-id" && field != "x-mock-method" && field != "x-mock-path" {
                let (header_field, header_value) =
                    match field.as_ref() {
                        "x-mock-header-any" => (header.value_string(), Matcher::Any),
                        "x-mock-header-missing" => (header.value_string(), Matcher::Missing),
                        _ => (field.replace("x-mock-", ""), Matcher::Exact(header.value_string())),
                    };

                mock.match_header(&header_field, header_value);
            }
        }

        let content_length: ContentLength = *try!(request.headers.get().ok_or(CreateMockError::ContentLengthMissing));

        let mut body = String::new();
        request.take(content_length.0).read_to_string(&mut body).unwrap();

        let response: MockResponse = try!(serde_json::from_str(&body).map_err(|_| CreateMockError::InvalidMockResponse));
        mock.response = response;

        Ok(mock)
    }
}

impl Handler for RequestHandler {
    fn handle(&self, request: Request, response: Response) {
        match (&request.method, &*request.uri.to_string()) {
            (&Method::Post, "/mocks") => self.handle_create_mock(request, response),
            (&Method::Delete, "/mocks") => self.handle_delete_mocks(request, response),
            _ => self.handle_default(request, response),
        };
    }
}

pub fn try_start() {
    if is_listening() { return }

    start()
}

fn start() {
    thread::spawn(move || {
        let mocks: Arc<Mutex<Vec<Mock>>> = Arc::new(Mutex::new(vec!()));

        match Server::http(SERVER_ADDRESS) {
            Ok(server) => { server.handle(RequestHandler::new(mocks)).unwrap(); },
            Err(_) => {},
        };
    });

    while !is_listening() {}
}

fn is_listening() -> bool {
    TcpStream::connect(SERVER_ADDRESS).is_ok()
}
<|endoftext|>


<commit_before>use base::world::{ChunkIndex, ChunkProvider, World};
use ghost::Ghost;
use event_manager::{CloseHandler, EventManager, EventResponse};
use glium::backend::glutin_backend::GlutinFacade;
use glium::{self, DisplayBuild, glutin};
use render::Renderer;
use super::Config;
use world::WorldView;
use base::math::*;
use base::gen::WorldGenerator;

pub struct Game {
    provider: Box<ChunkProvider>,
    renderer: Renderer,
    event_manager: EventManager,
    world_view: WorldView,
    world: World,
    player: Ghost,
}

impl Game {
    pub fn new(config: Config) -> Result<Self, ()> {
        let context = try!(create_context(&config));
        let mut world = World::empty();
        let provider = create_chunk_provider(&config);
        pregenerate_world(&mut world, &*provider);

        Ok(Game {
            provider: provider,
            renderer: Renderer::new(context.clone()),
            event_manager: EventManager::new(context.clone()),
            world_view: WorldView::from_world(&world, &context),
            world: world,
            player: Ghost::new(context.clone()),
        })
    }

    /// Main game function: contains the main render loop and owns all important
    /// components. This function should remain rather small, all heavy lifting
    /// should be done in other functions.
    pub fn run(mut self) -> Result<(), ()> {
        loop {
            try!(self.renderer.render(&self.world_view, &self.player.get_camera()));
            let event_resp = self.event_manager
                .poll_events(vec![&mut CloseHandler, &mut self.player]);
            if event_resp == EventResponse::Quit {
                break;
            }
            self.player.update();
        }

        Ok(())
    }
}

fn create_chunk_provider(config: &Config) -> Box<ChunkProvider> {
    Box::new(WorldGenerator::with_seed(config.seed))
}

fn pregenerate_world(world: &mut World, provider: &ChunkProvider) {
    // FIXME temporary worldgen invoker, replace with dynamic gen
    for i in 0..5 {
        for j in 0..5 {
            world.add_chunk(ChunkIndex(AxialPoint::new(i, j)), provider).unwrap();
        }
    }
}

/// Creates the OpenGL context and prints useful information about the
/// success or failure of said action.
fn create_context(config: &Config) -> Result<GlutinFacade, ()> {
    // Create glium context
    // TODO: handle fullscreen
    // TODO: OpenGL version/profile
    // TODO: vsync
    let context = glutin::WindowBuilder::new()
        .with_dimensions(config.resolution.width, config.resolution.height)
        .with_title(config.window_title.clone())
        .with_depth_buffer(24)
        .build_glium();

    match context {
        Err(e) => {
            // TODO: print more user friendly output
            error!("OpenGL context creation failed! Detailed error:");
            error!("{}", e);

            Err(())
        }
        Ok(context) => {
            // Print some information about the acquired OpenGL context
            info!("OpenGL context was successfully built");

            let glium::Version(api, major, minor) = *context.get_opengl_version();
            info!("Version of context: {} {}.{}",
                  if api == glium::Api::Gl { "OpenGL" } else { "OpenGL ES" },
                  major,
                  minor);

            let glium::Version(api, major, minor) = context.get_supported_glsl_version();
            info!("Supported GLSL version: {} {}.{}",
                  if api == glium::Api::Gl { "GLSL" } else { "GLSL ES" },
                  major,
                  minor);

            if let Some(mem) = context.get_free_video_memory().map(|mem| mem as u64) {
                let (mem, unit) = match () {
                    _ if mem < (1 << 12) => (mem, "B"),
                    _ if mem < (1 << 22) => (mem >> 10, "KB"),
                    _ if mem < (1 << 32) => (mem >> 20, "MB"),
                    _ => (mem >> 30, "GB"),
                };
                info!("Free GPU memory (estimated): {}{}", mem, unit);
            }

            Ok(context)
        }
    }
}
<commit_msg>allow dead code for 2 fields<commit_after>use base::world::{ChunkIndex, ChunkProvider, World};
use ghost::Ghost;
use event_manager::{CloseHandler, EventManager, EventResponse};
use glium::backend::glutin_backend::GlutinFacade;
use glium::{self, DisplayBuild, glutin};
use render::Renderer;
use super::Config;
use world::WorldView;
use base::math::*;
use base::gen::WorldGenerator;

pub struct Game {
    #[allow(dead_code)]
    provider: Box<ChunkProvider>, // Needed when we dynamically load chunks
    renderer: Renderer,
    event_manager: EventManager,
    world_view: WorldView,
    #[allow(dead_code)]
    world: World, // Needed for physics and updated as chunk updates arrive
    player: Ghost,
}

impl Game {
    pub fn new(config: Config) -> Result<Self, ()> {
        let context = try!(create_context(&config));
        let mut world = World::empty();
        let provider = create_chunk_provider(&config);
        pregenerate_world(&mut world, &*provider);

        Ok(Game {
            provider: provider,
            renderer: Renderer::new(context.clone()),
            event_manager: EventManager::new(context.clone()),
            world_view: WorldView::from_world(&world, &context),
            world: world,
            player: Ghost::new(context.clone()),
        })
    }

    /// Main game function: contains the main render loop and owns all important
    /// components. This function should remain rather small, all heavy lifting
    /// should be done in other functions.
    pub fn run(mut self) -> Result<(), ()> {
        loop {
            try!(self.renderer.render(&self.world_view, &self.player.get_camera()));
            let event_resp = self.event_manager
                .poll_events(vec![&mut CloseHandler, &mut self.player]);
            if event_resp == EventResponse::Quit {
                break;
            }
            self.player.update();
        }

        Ok(())
    }
}

fn create_chunk_provider(config: &Config) -> Box<ChunkProvider> {
    Box::new(WorldGenerator::with_seed(config.seed))
}

fn pregenerate_world(world: &mut World, provider: &ChunkProvider) {
    // FIXME temporary worldgen invoker, replace with dynamic gen
    for i in 0..5 {
        for j in 0..5 {
            world.add_chunk(ChunkIndex(AxialPoint::new(i, j)), provider).unwrap();
        }
    }
}

/// Creates the OpenGL context and prints useful information about the
/// success or failure of said action.
fn create_context(config: &Config) -> Result<GlutinFacade, ()> {
    // Create glium context
    // TODO: handle fullscreen
    // TODO: OpenGL version/profile
    // TODO: vsync
    let context = glutin::WindowBuilder::new()
        .with_dimensions(config.resolution.width, config.resolution.height)
        .with_title(config.window_title.clone())
        .with_depth_buffer(24)
        .build_glium();

    match context {
        Err(e) => {
            // TODO: print more user friendly output
            error!("OpenGL context creation failed! Detailed error:");
            error!("{}", e);

            Err(())
        }
        Ok(context) => {
            // Print some information about the acquired OpenGL context
            info!("OpenGL context was successfully built");

            let glium::Version(api, major, minor) = *context.get_opengl_version();
            info!("Version of context: {} {}.{}",
                  if api == glium::Api::Gl { "OpenGL" } else { "OpenGL ES" },
                  major,
                  minor);

            let glium::Version(api, major, minor) = context.get_supported_glsl_version();
            info!("Supported GLSL version: {} {}.{}",
                  if api == glium::Api::Gl { "GLSL" } else { "GLSL ES" },
                  major,
                  minor);

            if let Some(mem) = context.get_free_video_memory().map(|mem| mem as u64) {
                let (mem, unit) = match () {
                    _ if mem < (1 << 12) => (mem, "B"),
                    _ if mem < (1 << 22) => (mem >> 10, "KB"),
                    _ if mem < (1 << 32) => (mem >> 20, "MB"),
                    _ => (mem >> 30, "GB"),
                };
                info!("Free GPU memory (estimated): {}{}", mem, unit);
            }

            Ok(context)
        }
    }
}
<|endoftext|>