<commit_before>use bytes::{Bytes, IntoBuf};
use futures::{try_ready, Async, Future, Poll, Stream};
use std::error;
use tokio_io::{AsyncRead, AsyncWrite};

use crate::proto;
use crate::{Client, Connection, Error, Portal, Row, Statement, TlsConnect};
#[cfg(feature = "runtime")]
use crate::{MakeTlsConnect, Socket};

#[must_use = "futures do nothing unless polled"]
pub struct CancelQueryRaw<S, T>(pub(crate) proto::CancelQueryRawFuture<S, T>)
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>;

impl<S, T> Future for CancelQueryRaw<S, T>
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>,
{
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<(), Error> {
        self.0.poll()
    }
}

#[cfg(feature = "runtime")]
#[must_use = "futures do nothing unless polled"]
pub struct CancelQuery<T>(pub(crate) proto::CancelQueryFuture<T>)
where
    T: MakeTlsConnect<Socket>;

#[cfg(feature = "runtime")]
impl<T> Future for CancelQuery<T>
where
    T: MakeTlsConnect<Socket>,
{
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<(), Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct ConnectRaw<S, T>(pub(crate) proto::ConnectRawFuture<S, T>)
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>;

impl<S, T> Future for ConnectRaw<S, T>
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>,
{
    type Item = (Client, Connection<S, T::Stream>);
    type Error = Error;

    fn poll(&mut self) -> Poll<(Client, Connection<S, T::Stream>), Error> {
        let (client, connection) = try_ready!(self.0.poll());

        Ok(Async::Ready((Client(client), Connection(connection))))
    }
}

#[cfg(feature = "runtime")]
#[must_use = "futures do nothing unless polled"]
pub struct Connect<T>(pub(crate) proto::ConnectFuture<T>)
where
    T: MakeTlsConnect<Socket>;

#[cfg(feature = "runtime")]
impl<T> Future for Connect<T>
where
    T: MakeTlsConnect<Socket>,
{
    type Item = (Client, Connection<Socket, T::Stream>);
    type Error = Error;

    fn poll(&mut self) -> Poll<(Client, Connection<Socket, T::Stream>), Error> {
        let (client, connection) = try_ready!(self.0.poll());

        Ok(Async::Ready((Client(client), Connection(connection))))
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Prepare(pub(crate) proto::PrepareFuture);

impl Future for Prepare {
    type Item = Statement;
    type Error = Error;

    fn poll(&mut self) -> Poll<Statement, Error> {
        let statement = try_ready!(self.0.poll());

        Ok(Async::Ready(Statement(statement)))
    }
}

#[must_use = "streams do nothing unless polled"]
pub struct Query(pub(crate) proto::QueryStream<proto::Statement>);

impl Stream for Query {
    type Item = Row;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Row>, Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Bind(pub(crate) proto::BindFuture);

impl Future for Bind {
    type Item = Portal;
    type Error = Error;

    fn poll(&mut self) -> Poll<Portal, Error> {
        match self.0.poll() {
            Ok(Async::Ready(portal)) => Ok(Async::Ready(Portal(portal))),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

#[must_use = "streams do nothing unless polled"]
pub struct QueryPortal(pub(crate) proto::QueryStream<proto::Portal>);

impl Stream for QueryPortal {
    type Item = Row;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Row>, Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct CopyIn<S>(pub(crate) proto::CopyInFuture<S>)
where
    S: Stream,
    S::Item: IntoBuf,
    <S::Item as IntoBuf>::Buf: Send,
    S::Error: Into<Box<dyn error::Error + Sync + Send>>;

impl<S> Future for CopyIn<S>
where
    S: Stream,
    S::Item: IntoBuf,
    <S::Item as IntoBuf>::Buf: Send,
    S::Error: Into<Box<dyn error::Error + Sync + Send>>,
{
    type Item = u64;
    type Error = Error;

    fn poll(&mut self) -> Poll<u64, Error> {
        self.0.poll()
    }
}

#[must_use = "streams do nothing unless polled"]
pub struct CopyOut(pub(crate) proto::CopyOutStream);

impl Stream for CopyOut {
    type Item = Bytes;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Bytes>, Error> {
        self.0.poll()
    }
}
<commit_msg>Document impls module<commit_after>//! Futures and stream types used in the crate.
use bytes::{Bytes, IntoBuf};
use futures::{try_ready, Async, Future, Poll, Stream};
use std::error;
use tokio_io::{AsyncRead, AsyncWrite};

use crate::proto;
use crate::{Client, Connection, Error, Portal, Row, Statement, TlsConnect};
#[cfg(feature = "runtime")]
use crate::{MakeTlsConnect, Socket};

/// The future returned by `Client::cancel_query_raw`.
#[must_use = "futures do nothing unless polled"]
pub struct CancelQueryRaw<S, T>(pub(crate) proto::CancelQueryRawFuture<S, T>)
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>;

impl<S, T> Future for CancelQueryRaw<S, T>
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>,
{
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<(), Error> {
        self.0.poll()
    }
}

/// The future returned by `Client::cancel_query`.
#[cfg(feature = "runtime")]
#[must_use = "futures do nothing unless polled"]
pub struct CancelQuery<T>(pub(crate) proto::CancelQueryFuture<T>)
where
    T: MakeTlsConnect<Socket>;

#[cfg(feature = "runtime")]
impl<T> Future for CancelQuery<T>
where
    T: MakeTlsConnect<Socket>,
{
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<(), Error> {
        self.0.poll()
    }
}

/// The future returned by `Config::connect_raw`.
#[must_use = "futures do nothing unless polled"]
pub struct ConnectRaw<S, T>(pub(crate) proto::ConnectRawFuture<S, T>)
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>;

impl<S, T> Future for ConnectRaw<S, T>
where
    S: AsyncRead + AsyncWrite,
    T: TlsConnect<S>,
{
    type Item = (Client, Connection<S, T::Stream>);
    type Error = Error;

    fn poll(&mut self) -> Poll<(Client, Connection<S, T::Stream>), Error> {
        let (client, connection) = try_ready!(self.0.poll());

        Ok(Async::Ready((Client(client), Connection(connection))))
    }
}

/// The future returned by `Config::connect`.
#[cfg(feature = "runtime")]
#[must_use = "futures do nothing unless polled"]
pub struct Connect<T>(pub(crate) proto::ConnectFuture<T>)
where
    T: MakeTlsConnect<Socket>;

#[cfg(feature = "runtime")]
impl<T> Future for Connect<T>
where
    T: MakeTlsConnect<Socket>,
{
    type Item = (Client, Connection<Socket, T::Stream>);
    type Error = Error;

    fn poll(&mut self) -> Poll<(Client, Connection<Socket, T::Stream>), Error> {
        let (client, connection) = try_ready!(self.0.poll());

        Ok(Async::Ready((Client(client), Connection(connection))))
    }
}

/// The future returned by `Client::prepare`.
#[must_use = "futures do nothing unless polled"]
pub struct Prepare(pub(crate) proto::PrepareFuture);

impl Future for Prepare {
    type Item = Statement;
    type Error = Error;

    fn poll(&mut self) -> Poll<Statement, Error> {
        let statement = try_ready!(self.0.poll());

        Ok(Async::Ready(Statement(statement)))
    }
}

/// The future returned by `Client::query`.
#[must_use = "streams do nothing unless polled"]
pub struct Query(pub(crate) proto::QueryStream<proto::Statement>);

impl Stream for Query {
    type Item = Row;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Row>, Error> {
        self.0.poll()
    }
}

/// The future returned by `Client::bind`.
#[must_use = "futures do nothing unless polled"]
pub struct Bind(pub(crate) proto::BindFuture);

impl Future for Bind {
    type Item = Portal;
    type Error = Error;

    fn poll(&mut self) -> Poll<Portal, Error> {
        match self.0.poll() {
            Ok(Async::Ready(portal)) => Ok(Async::Ready(Portal(portal))),
            Ok(Async::NotReady) => Ok(Async::NotReady),
            Err(e) => Err(e),
        }
    }
}

/// The future returned by `Client::query_portal`.
#[must_use = "streams do nothing unless polled"]
pub struct QueryPortal(pub(crate) proto::QueryStream<proto::Portal>);

impl Stream for QueryPortal {
    type Item = Row;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Row>, Error> {
        self.0.poll()
    }
}

/// The future returned by `Client::copy_in`.
#[must_use = "futures do nothing unless polled"]
pub struct CopyIn<S>(pub(crate) proto::CopyInFuture<S>)
where
    S: Stream,
    S::Item: IntoBuf,
    <S::Item as IntoBuf>::Buf: Send,
    S::Error: Into<Box<dyn error::Error + Sync + Send>>;

impl<S> Future for CopyIn<S>
where
    S: Stream,
    S::Item: IntoBuf,
    <S::Item as IntoBuf>::Buf: Send,
    S::Error: Into<Box<dyn error::Error + Sync + Send>>,
{
    type Item = u64;
    type Error = Error;

    fn poll(&mut self) -> Poll<u64, Error> {
        self.0.poll()
    }
}

/// The future returned by `Client::copy_out`.
#[must_use = "streams do nothing unless polled"]
pub struct CopyOut(pub(crate) proto::CopyOutStream);

impl Stream for CopyOut {
    type Item = Bytes;
    type Error = Error;

    fn poll(&mut self) -> Poll<Option<Bytes>, Error> {
        self.0.poll()
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
extern crate libc;

use xlib::{XOpenDisplay, XDisplayName, XQueryExtension, XInitExtension, XSynchronize};
use libc::{c_int};
use std::ptr;
use xtst::{XRecordCreateContext, XRecordAllClients, XRecordAllocRange, XRecordRange, XRecordQueryVersion, XRecordEnableContext, XRecordEnableContextAsync,XRecordInterceptData, XRecordProcessReplies, XRecordFreeData};
use std::mem;
mod xtst;
mod xlib;

fn main() {
	let mut a:  i8 = 0;
	let display_control = unsafe { XOpenDisplay( &a)};
	let display_data = unsafe { XOpenDisplay(&a)};
	if display_data.is_null() || display_control.is_null() {
		fail!("XOpenDisplay() failed!");
	}

	unsafe {
		XSynchronize(display_control, 1);
	}

	let display_name = unsafe {XDisplayName(&a)};
	let ext_name = "RECORD";

	unsafe {
		// Check presence of Record extension
		let arg2:*mut c_int = &mut 1;
		let arg3:*mut c_int = &mut 1;
		let arg4:*mut c_int = &mut 1;
		let has_record = XQueryExtension(display_control, ext_name.to_c_str().as_ptr() as *const i8,arg2,arg3,arg4);
		let extension = XInitExtension(display_control, ext_name.to_c_str().as_ptr() as *const i8);
		if extension.is_null() {
			fail!("XInitExtension() failed!");
		}

		// Get version
		let mut versionMajor: c_int = 0;
		let mut versionMinor: c_int = 0;
		XRecordQueryVersion(display_control, &mut versionMajor, &mut versionMinor);
		println!("RECORD extension version {}.{}", versionMajor, versionMinor);

		// Prepare record range
		let mut recordRange: XRecordRange = *XRecordAllocRange();
		let mut recordRangePtr: *mut *mut XRecordRange = std::mem::transmute(&mut &mut recordRange);
		recordRange.device_events.first = 2; // KeyPress
		recordRange.device_events.last = 6; // MotionNotify

		// Create context
		let context = XRecordCreateContext(
			display_control,
			0,
			&mut XRecordAllClients,
			1,
			recordRangePtr,
			1
		);
		if context == 0 {
			fail!("Fail create Record context\n");
		}

		// Run
		let res = XRecordEnableContextAsync(display_data, context, Some(recordCallback), &mut 0);
		if res == 0 {
			fail!("Cound not enable the Record context!\n");
		}
		loop {
			XRecordProcessReplies(display_data);
		}
	}
}

extern "C" fn recordCallback(pointer:*mut i8, raw_data: *mut XRecordInterceptData) {
	println!("Receive event\n");

	unsafe {
		let data = &*raw_data;
		println!("Category {}", data.category);
		println!("Time {}", data.server_time);
		println!("Datalen {}", data.data_len);
		XRecordFreeData(raw_data);
	}
}<commit_msg>Refactoring<commit_after>#![feature(globs)]
extern crate libc;

use xlib::{XOpenDisplay, XDisplayName, XQueryExtension, XInitExtension, XSynchronize};
use libc::{c_int};
use std::ptr;
use xtst::{XRecordCreateContext, XRecordAllClients, XRecordAllocRange, XRecordRange, XRecordQueryVersion, XRecordEnableContext, XRecordEnableContextAsync,XRecordInterceptData, XRecordProcessReplies, XRecordFreeData};
use std::mem;
mod xtst;
mod xlib;

fn main() {
	unsafe {
		let mut a:  i8 = 0;
		let display_control = XOpenDisplay( &a);
		let display_data = XOpenDisplay(&a);

		if display_data.is_null() || display_control.is_null() {
			fail!("XOpenDisplay() failed!");
		}

		XSynchronize(display_control, 1);

		let display_name = unsafe {XDisplayName(&a)};
		let ext_name = "RECORD";
		// Check presence of Record extension
		let arg2:*mut c_int = &mut 1;
		let arg3:*mut c_int = &mut 1;
		let arg4:*mut c_int = &mut 1;
		let has_record = XQueryExtension(display_control, ext_name.to_c_str().as_ptr() as *const i8,arg2,arg3,arg4);
		let extension = XInitExtension(display_control, ext_name.to_c_str().as_ptr() as *const i8);
		if extension.is_null() {
			fail!("XInitExtension() failed!");
		}

		// Get version
		let mut versionMajor: c_int = 0;
		let mut versionMinor: c_int = 0;
		XRecordQueryVersion(display_control, &mut versionMajor, &mut versionMinor);
		println!("RECORD extension version {}.{}", versionMajor, versionMinor);

		// Prepare record range
		let mut recordRange: XRecordRange = *XRecordAllocRange();
		let mut recordRangePtr: *mut *mut XRecordRange = std::mem::transmute(&mut &mut recordRange);
		recordRange.device_events.first = 2; // KeyPress
		recordRange.device_events.last = 6; // MotionNotify

		// Create context
		let context = XRecordCreateContext(
			display_control,
			0,
			&mut XRecordAllClients,
			1,
			recordRangePtr,
			1
		);
		if context == 0 {
			fail!("Fail create Record context\n");
		}

		// Run
		let res = XRecordEnableContextAsync(display_data, context, Some(recordCallback), &mut 0);
		if res == 0 {
			fail!("Cound not enable the Record context!\n");
		}
		loop {
			XRecordProcessReplies(display_data);
		}
	}
}

extern "C" fn recordCallback(pointer:*mut i8, raw_data: *mut XRecordInterceptData) {
	println!("Receive event\n");

	unsafe {
		let data = &*raw_data;
		println!("Category {}", data.category);
		println!("Time {}", data.server_time);
		println!("Datalen {}", data.data_len);
		XRecordFreeData(raw_data);
	}
}<|endoftext|>


<commit_before>extern crate base64;
extern crate clap;
extern crate hyper;
extern crate hyper_rustls;
extern crate pem;
#[macro_use]
extern crate prettytable;
extern crate ring;
extern crate rustls;
extern crate serde_json;
extern crate tempfile;
#[macro_use]
extern crate tera;

extern crate ct_tools;

use ct_tools::{censys, crtsh, letsencrypt};
use ct_tools::common::{Log, sha256_hex};
use ct_tools::ct::submit_cert_to_logs;
use ct_tools::google::fetch_trusted_ct_logs;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::process::Command;
use std::sync::Arc;
use std::time::Duration;

fn pems_to_chain(data: &str) -> Vec<Vec<u8>> {
    pem::parse_many(data)
        .into_iter()
        .filter(|p| p.tag == "CERTIFICATE")
        .map(|p| p.contents)
        .collect()
}

fn submit(paths: clap::Values) {
    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
    );
    // TODO: timeout on the http_client, but for submit_cert_to_logs only, not build_chain
    let logs = fetch_trusted_ct_logs(&http_client);

    for path in paths {
        println!("Submitting {} ...", path);

        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let mut chain = pems_to_chain(&contents);
        if chain.len() == 1 {
            // TODO: There's got to be some way to do this ourselves, instead of using crt.sh as a
            // glorified AIA chaser.
            println!("Only one certificate in chain, using crt.sh to build a full chain ...");
            chain = crtsh::build_chain_for_cert(&http_client, &chain[0]);
        }
        let scts = submit_cert_to_logs(&http_client, &logs, &chain);

        println!("Find the cert on crt.sh: {}",
                 crtsh::url_for_cert(&chain[0]));
        let mut table = prettytable::Table::new();
        table.add_row(row!["Log", "SCT"]);
        for (log, sct) in scts {
            table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
        }
        table.printstd();
        println!();
        println!();
    }
}

fn check(paths: clap::Values) {
    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
    );

    for path in paths {
        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let chain = pems_to_chain(&contents);

        let is_logged = censys::is_cert_logged(&http_client, &chain[0]);
        if is_logged {
            println!("{} was already logged", path);
        } else {
            println!("{} has not been logged", path);
        }
    }
}

struct HttpHandler {
    templates: tera::Tera,
    http_client: hyper::Client,
    logs: Vec<Log>,
}

impl hyper::server::Handler for HttpHandler {
    fn handle(&self, request: hyper::server::Request, response: hyper::server::Response) {
        let peer_certs = request
            .ssl::<hyper_rustls::WrappedStream>()
            .unwrap()
            .to_tls_stream()
            .get_session()
            .get_peer_certificates();

        let mut crtsh_url = None;
        if peer_certs.is_some() && request.method == hyper::method::Method::Post {
            let chain = crtsh::build_chain_for_cert(&self.http_client,
                                                    &peer_certs.as_ref().unwrap()[0].0);
            let scts = submit_cert_to_logs(&self.http_client, &self.logs, &chain);
            if !scts.is_empty() {
                crtsh_url = Some(crtsh::url_for_cert(&chain[0]));
                println!("Successfully submitted: {}", sha256_hex(&chain[0]));
            }
        }

        let rendered_cert = peer_certs.map(|chain| {
            let mut tmp = tempfile::NamedTempFile::new().unwrap();
            tmp.write_all(&chain[0].0).unwrap();
            tmp.flush().unwrap();
            let stdout = Command::new("openssl")
                .arg("x509")
                .arg("-text")
                .arg("-noout")
                .arg("-inform")
                .arg("der")
                .arg("-in")
                .arg(tmp.path().as_os_str())
                .output()
                .unwrap()
                .stdout;
            String::from_utf8_lossy(&stdout).into_owned()
        });

        let mut context = tera::Context::new();
        context.add("cert", &rendered_cert);
        context.add("crtsh_url", &crtsh_url);
        response
            .send(self.templates
                      .render("home.html", &context)
                      .unwrap()
                      .as_bytes())
            .unwrap();
    }
}

struct NoVerificationCertificateVerifier;
impl rustls::ClientCertVerifier for NoVerificationCertificateVerifier {
    fn verify_client_cert(&self,
                          _: &rustls::RootCertStore,
                          _: &[rustls::Certificate])
                          -> Result<(), rustls::TLSError> {
        Ok(())
    }
}

fn server(local_dev: bool, domain: Option<&str>, letsencrypt_env: Option<&str>) {
    match (local_dev, domain, letsencrypt_env) {
        (true, Some(_), _) |
        (true, _, Some(_)) => {
            panic!("Can't use both --local-dev and --letsencrypt-env or --domain")
        }
        (_, Some(_), None) |
        (_, None, Some(_)) => {
            panic!("When using Let's Encrypt, must set both --letsencrypt-env and --domain")
        }
        (false, _, None) => panic!("Must set at least one of --local-dev or --letsencrypt-env"),
        _ => {}
    };

    let mut tls_config = rustls::ServerConfig::new();
    tls_config.client_auth_offer = true;
    if local_dev {
        // TODO: not all the details on the cert are perfect, but it's fine.
        let (cert, pkey) = letsencrypt::generate_temporary_cert("localhost");
        tls_config.set_single_cert(vec![letsencrypt::openssl_cert_to_rustls(&cert)],
                                   letsencrypt::openssl_pkey_to_rustls(&pkey));
    } else {
        let letsencrypt_url = match letsencrypt_env.unwrap() {
            "prod" => "https://acme-v01.api.letsencrypt.org/directory",
            "dev" => "https://acme-staging.api.letsencrypt.org/directory",
            _ => unreachable!(),
        };
        let cert_cache = letsencrypt::DiskCache::new(env::home_dir()
                                                         .unwrap()
                                                         .join(".ct-tools")
                                                         .join("certificates"));
        tls_config.cert_resolver =
            Box::new(letsencrypt::AutomaticCertResolver::new(letsencrypt_url,
                                                             vec![domain.unwrap().to_string()],
                                                             cert_cache));
    }
    tls_config.set_persistence(rustls::ServerSessionMemoryCache::new(1024));
    tls_config.ticketer = rustls::Ticketer::new();
    // Disable certificate verification. In any normal context, this would be horribly insecure!
    // However, all we're doing is taking the certs and then turning around and submitting them to
    // CT logs, so it doesn't matter if they're verified.
    tls_config
        .dangerous()
        .set_certificate_verifier(Box::new(NoVerificationCertificateVerifier));
    let tls_server = hyper_rustls::TlsServer { cfg: Arc::new(tls_config) };

    let mut http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
    );
    let logs = fetch_trusted_ct_logs(&http_client);
    http_client.set_write_timeout(Some(Duration::from_secs(5)));
    http_client.set_read_timeout(Some(Duration::from_secs(5)));
    let handler = HttpHandler {
        templates: compile_templates!("templates/*"),
        http_client: http_client,
        logs: logs,
    };

    let addr = if local_dev {
        "127.0.0.1:1337"
    } else {
        "0.0.0.0:443"
    };
    println!("Listening on https://{} ...", addr);
    hyper::Server::https(addr, tls_server)
        .unwrap()
        // If there aren't at least two threads, the Let's Encrypt integration will deadlock.
        .handle_threads(handler, 16)
        .unwrap();
}

fn main() {
    let matches = clap::App::new("ct-tools")
        .subcommand(clap::SubCommand::with_name("submit")
                        .about("Directly submits certificates to CT logs")
                        .arg(clap::Arg::with_name("path")
                                 .multiple(true)
                                 .required(true)
                                 .help("Path to certificate or chain")))
        .subcommand(clap::SubCommand::with_name("check")
                        .about("Checks whether a certificate exists in CT logs")
                        .arg(clap::Arg::with_name("path")
                                 .multiple(true)
                                 .required(true)
                                 .help("Path to certificate or chain")))
        .subcommand(clap::SubCommand::with_name("server")
                        .about("Run an HTTPS server that submits client to CT logs")
                        .arg(clap::Arg::with_name("local-dev")
                                 .long("--local-dev")
                                 .help("Local development, do not obtain a certificate"))
                        .arg(clap::Arg::with_name("domain")
                                 .takes_value(true)
                                 .long("--domain")
                                 .help("Domain this is running as"))
                        .arg(clap::Arg::with_name("letsencrypt-env")
                                 .takes_value(true)
                                 .long("--letsencrypt-env")
                                 .possible_values(&["dev", "prod"])
                                 .help("Let's Encrypt environment to use")))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("submit") {
        submit(matches.values_of("path").unwrap());
    } else if let Some(matches) = matches.subcommand_matches("check") {
        check(matches.values_of("path").unwrap());
    } else if let Some(matches) = matches.subcommand_matches("server") {
        server(matches.is_present("local-dev"),
               matches.value_of("domain"),
               matches.value_of("letsencrypt-env"));
    }
}
<commit_msg>I don't have patience for things longer than 15 seconds<commit_after>extern crate base64;
extern crate clap;
extern crate hyper;
extern crate hyper_rustls;
extern crate pem;
#[macro_use]
extern crate prettytable;
extern crate ring;
extern crate rustls;
extern crate serde_json;
extern crate tempfile;
#[macro_use]
extern crate tera;

extern crate ct_tools;

use ct_tools::{censys, crtsh, letsencrypt};
use ct_tools::common::{Log, sha256_hex};
use ct_tools::ct::submit_cert_to_logs;
use ct_tools::google::fetch_trusted_ct_logs;
use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::process::Command;
use std::sync::Arc;
use std::time::Duration;

fn pems_to_chain(data: &str) -> Vec<Vec<u8>> {
    pem::parse_many(data)
        .into_iter()
        .filter(|p| p.tag == "CERTIFICATE")
        .map(|p| p.contents)
        .collect()
}

fn submit(paths: clap::Values) {
    let mut http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
    );
    http_client.set_read_timeout(Some(Duration::from_secs(15)));
    let logs = fetch_trusted_ct_logs(&http_client);

    for path in paths {
        println!("Submitting {} ...", path);

        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let mut chain = pems_to_chain(&contents);
        if chain.len() == 1 {
            // TODO: There's got to be some way to do this ourselves, instead of using crt.sh as a
            // glorified AIA chaser.
            println!("Only one certificate in chain, using crt.sh to build a full chain ...");
            chain = crtsh::build_chain_for_cert(&http_client, &chain[0]);
        }
        let scts = submit_cert_to_logs(&http_client, &logs, &chain);

        println!("Find the cert on crt.sh: {}",
                 crtsh::url_for_cert(&chain[0]));
        let mut table = prettytable::Table::new();
        table.add_row(row!["Log", "SCT"]);
        for (log, sct) in scts {
            table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
        }
        table.printstd();
        println!();
        println!();
    }
}

fn check(paths: clap::Values) {
    let http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
    );

    for path in paths {
        let mut contents = String::new();
        File::open(path)
            .unwrap()
            .read_to_string(&mut contents)
            .unwrap();

        let chain = pems_to_chain(&contents);

        let is_logged = censys::is_cert_logged(&http_client, &chain[0]);
        if is_logged {
            println!("{} was already logged", path);
        } else {
            println!("{} has not been logged", path);
        }
    }
}

struct HttpHandler {
    templates: tera::Tera,
    http_client: hyper::Client,
    logs: Vec<Log>,
}

impl hyper::server::Handler for HttpHandler {
    fn handle(&self, request: hyper::server::Request, response: hyper::server::Response) {
        let peer_certs = request
            .ssl::<hyper_rustls::WrappedStream>()
            .unwrap()
            .to_tls_stream()
            .get_session()
            .get_peer_certificates();

        let mut crtsh_url = None;
        if peer_certs.is_some() && request.method == hyper::method::Method::Post {
            let chain = crtsh::build_chain_for_cert(&self.http_client,
                                                    &peer_certs.as_ref().unwrap()[0].0);
            let scts = submit_cert_to_logs(&self.http_client, &self.logs, &chain);
            if !scts.is_empty() {
                crtsh_url = Some(crtsh::url_for_cert(&chain[0]));
                println!("Successfully submitted: {}", sha256_hex(&chain[0]));
            }
        }

        let rendered_cert = peer_certs.map(|chain| {
            let mut tmp = tempfile::NamedTempFile::new().unwrap();
            tmp.write_all(&chain[0].0).unwrap();
            tmp.flush().unwrap();
            let stdout = Command::new("openssl")
                .arg("x509")
                .arg("-text")
                .arg("-noout")
                .arg("-inform")
                .arg("der")
                .arg("-in")
                .arg(tmp.path().as_os_str())
                .output()
                .unwrap()
                .stdout;
            String::from_utf8_lossy(&stdout).into_owned()
        });

        let mut context = tera::Context::new();
        context.add("cert", &rendered_cert);
        context.add("crtsh_url", &crtsh_url);
        response
            .send(self.templates
                      .render("home.html", &context)
                      .unwrap()
                      .as_bytes())
            .unwrap();
    }
}

struct NoVerificationCertificateVerifier;
impl rustls::ClientCertVerifier for NoVerificationCertificateVerifier {
    fn verify_client_cert(&self,
                          _: &rustls::RootCertStore,
                          _: &[rustls::Certificate])
                          -> Result<(), rustls::TLSError> {
        Ok(())
    }
}

fn server(local_dev: bool, domain: Option<&str>, letsencrypt_env: Option<&str>) {
    match (local_dev, domain, letsencrypt_env) {
        (true, Some(_), _) |
        (true, _, Some(_)) => {
            panic!("Can't use both --local-dev and --letsencrypt-env or --domain")
        }
        (_, Some(_), None) |
        (_, None, Some(_)) => {
            panic!("When using Let's Encrypt, must set both --letsencrypt-env and --domain")
        }
        (false, _, None) => panic!("Must set at least one of --local-dev or --letsencrypt-env"),
        _ => {}
    };

    let mut tls_config = rustls::ServerConfig::new();
    tls_config.client_auth_offer = true;
    if local_dev {
        // TODO: not all the details on the cert are perfect, but it's fine.
        let (cert, pkey) = letsencrypt::generate_temporary_cert("localhost");
        tls_config.set_single_cert(vec![letsencrypt::openssl_cert_to_rustls(&cert)],
                                   letsencrypt::openssl_pkey_to_rustls(&pkey));
    } else {
        let letsencrypt_url = match letsencrypt_env.unwrap() {
            "prod" => "https://acme-v01.api.letsencrypt.org/directory",
            "dev" => "https://acme-staging.api.letsencrypt.org/directory",
            _ => unreachable!(),
        };
        let cert_cache = letsencrypt::DiskCache::new(env::home_dir()
                                                         .unwrap()
                                                         .join(".ct-tools")
                                                         .join("certificates"));
        tls_config.cert_resolver =
            Box::new(letsencrypt::AutomaticCertResolver::new(letsencrypt_url,
                                                             vec![domain.unwrap().to_string()],
                                                             cert_cache));
    }
    tls_config.set_persistence(rustls::ServerSessionMemoryCache::new(1024));
    tls_config.ticketer = rustls::Ticketer::new();
    // Disable certificate verification. In any normal context, this would be horribly insecure!
    // However, all we're doing is taking the certs and then turning around and submitting them to
    // CT logs, so it doesn't matter if they're verified.
    tls_config
        .dangerous()
        .set_certificate_verifier(Box::new(NoVerificationCertificateVerifier));
    let tls_server = hyper_rustls::TlsServer { cfg: Arc::new(tls_config) };

    let mut http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_rustls::TlsClient::new())
    );
    let logs = fetch_trusted_ct_logs(&http_client);
    http_client.set_write_timeout(Some(Duration::from_secs(5)));
    http_client.set_read_timeout(Some(Duration::from_secs(5)));
    let handler = HttpHandler {
        templates: compile_templates!("templates/*"),
        http_client: http_client,
        logs: logs,
    };

    let addr = if local_dev {
        "127.0.0.1:1337"
    } else {
        "0.0.0.0:443"
    };
    println!("Listening on https://{} ...", addr);
    hyper::Server::https(addr, tls_server)
        .unwrap()
        // If there aren't at least two threads, the Let's Encrypt integration will deadlock.
        .handle_threads(handler, 16)
        .unwrap();
}

fn main() {
    let matches = clap::App::new("ct-tools")
        .subcommand(clap::SubCommand::with_name("submit")
                        .about("Directly submits certificates to CT logs")
                        .arg(clap::Arg::with_name("path")
                                 .multiple(true)
                                 .required(true)
                                 .help("Path to certificate or chain")))
        .subcommand(clap::SubCommand::with_name("check")
                        .about("Checks whether a certificate exists in CT logs")
                        .arg(clap::Arg::with_name("path")
                                 .multiple(true)
                                 .required(true)
                                 .help("Path to certificate or chain")))
        .subcommand(clap::SubCommand::with_name("server")
                        .about("Run an HTTPS server that submits client to CT logs")
                        .arg(clap::Arg::with_name("local-dev")
                                 .long("--local-dev")
                                 .help("Local development, do not obtain a certificate"))
                        .arg(clap::Arg::with_name("domain")
                                 .takes_value(true)
                                 .long("--domain")
                                 .help("Domain this is running as"))
                        .arg(clap::Arg::with_name("letsencrypt-env")
                                 .takes_value(true)
                                 .long("--letsencrypt-env")
                                 .possible_values(&["dev", "prod"])
                                 .help("Let's Encrypt environment to use")))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("submit") {
        submit(matches.values_of("path").unwrap());
    } else if let Some(matches) = matches.subcommand_matches("check") {
        check(matches.values_of("path").unwrap());
    } else if let Some(matches) = matches.subcommand_matches("server") {
        server(matches.is_present("local-dev"),
               matches.value_of("domain"),
               matches.value_of("letsencrypt-env"));
    }
}
<|endoftext|>


<commit_before>extern crate base64;
extern crate docopt;
extern crate rustc_serialize;

use std::error::Error;
use std::fs::File;
use std::io::{self, Write};
use std::path::Path;
use std::str;

use docopt::Docopt;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

const BUF_SIZE: usize = 4 * 1024;

const USAGE: &'static str = "
Base64 encode or decode FILE, or standard input, to standard output.

Usage: base64 [options] [<file>]
       base64 (--help | --version)

Options:
  -d --decode   decode data
  -h --help     display this help and exit
  --version     output version information and exit
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_decode: bool,
    flag_help: bool,
    flag_version: bool,
}

fn encode(file: &mut io::Read) {
    let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
    let mut stdout = io::stdout();

    loop {
        match file.read(&mut buf[..]) {
            Ok(count) => {
                if count == 0 {
                    print!("\n");
                    break;
                }
                let res = base64::encode(&buf[..count]);
                stdout.write(&res).unwrap();
            },
            Err(err) => panic!(err),
        }
    }
}

fn decode(file: &mut io::Read) {
    let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
    let mut stdout = io::stdout();
    let mut stderr = io::stderr();

    loop {
        match file.read(&mut buf[..]) {
            Ok(count) => {
                if count == 0 {
                     break;
                }
                match base64::decode(&buf[..count]) {
                    Ok(res) => {
                        stdout.write(&res).unwrap();
                    },
                    Err(msg) => {
                        stderr.write(msg.as_bytes()).unwrap();

                    },
                }
            },
            Err(err) => panic!(err),
        }
    }
}

fn process(file: &mut io::Read, is_decode: bool) {
    if is_decode {
        decode(file);
    } else {
        encode(file);
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    if args.flag_version {
        println!("base64 v{}", VERSION);
        return;
    }

    if args.arg_file != "" {
        let path = Path::new(&args.arg_file);
        let mut file = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}",
                               path.display(), why.description()),
            Ok(file) => file,
        };
        process(&mut file, args.flag_decode);
    } else {
        process(&mut io::stdin(), args.flag_decode);
    }
}
<commit_msg>fix buffer size<commit_after>extern crate base64;
extern crate docopt;
extern crate rustc_serialize;

use std::error::Error;
use std::fs::File;
use std::io::{self, Write};
use std::path::Path;
use std::str;

use docopt::Docopt;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

const BUF_SIZE: usize = 4 * 1024 - 1;

const USAGE: &'static str = "
Base64 encode or decode FILE, or standard input, to standard output.

Usage: base64 [options] [<file>]
       base64 (--help | --version)

Options:
  -d --decode   decode data
  -h --help     display this help and exit
  --version     output version information and exit
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_file: String,
    flag_decode: bool,
    flag_help: bool,
    flag_version: bool,
}

fn encode(file: &mut io::Read) {
    let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
    let mut stdout = io::stdout();

    loop {
        match file.read(&mut buf[..]) {
            Ok(count) => {
                if count == 0 {
                    print!("\n");
                    break;
                }
                let res = base64::encode(&buf[..count]);
                stdout.write(&res).unwrap();
            },
            Err(err) => panic!(err),
        }
    }
}

fn decode(file: &mut io::Read) {
    let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
    let mut stdout = io::stdout();
    let mut stderr = io::stderr();

    loop {
        match file.read(&mut buf[..]) {
            Ok(count) => {
                if count == 0 {
                     break;
                }
                match base64::decode(&buf[..count]) {
                    Ok(res) => {
                        stdout.write(&res).unwrap();
                    },
                    Err(msg) => {
                        stderr.write(msg.as_bytes()).unwrap();

                    },
                }
            },
            Err(err) => panic!(err),
        }
    }
}

fn process(file: &mut io::Read, is_decode: bool) {
    if is_decode {
        decode(file);
    } else {
        encode(file);
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    if args.flag_version {
        println!("base64 v{}", VERSION);
        return;
    }

    if args.arg_file != "" {
        let path = Path::new(&args.arg_file);
        let mut file = match File::open(&path) {
            Err(why) => panic!("couldn't open {}: {}",
                               path.display(), why.description()),
            Ok(file) => file,
        };
        process(&mut file, args.flag_decode);
    } else {
        process(&mut io::stdin(), args.flag_decode);
    }
}
<|endoftext|>


<commit_before>extern crate automata;

use std::process;
use automata::automata::dfa::*;

fn main() {
    // (toto)*
    let dfa = DFABuilder::new()
        .add_start(0)
        .add_final(4)
        .add_final(0)
        .add_transition('t', 0, 1)
        .add_transition('o', 1, 2)
        .add_transition('t', 2, 3)
        .add_transition('o', 3, 4)
        .add_transition('t', 4, 1)
        .finalize();
    match dfa {
        Ok(dfa) => {
            println!("{}", dfa);
            println!("{:?}", dfa.run("toto"));
            println!("{:?}", dfa.run(""));
            println!("{:?}", dfa.run("t"));
            println!("{:?}", dfa.run("to"));
            println!("{:?}", dfa.run("tot"));
            println!("{:?}", dfa.run("totot"));
            println!("{:?}", dfa.run("totototo"));
        },
        _ => process::exit(1),
    }
}

/*
fn main() {
    // (ab)*c
    let file = "data/dfa1.txt";
    match DFA::new_from_file(file) {
        Ok(d) => {
            let dfa = d;
            println!("{}", dfa);
            println!("{:?}", dfa.run("ababac"));
            println!("{:?}", dfa.run("ababc"));
            println!("{:?}", dfa.run(""));
            println!("{:?}", dfa.run("abc"));
            println!("{:?}", dfa.run("ac"));
            println!("{:?}", dfa.run("c"));
            println!("{:?}", dfa.run("ababababababababababababababababababababc"));
        },
        Err(e) => {
            println!("{}", e);
            //process::exit(0)
        },
    }
}
*/
<commit_msg>main.rs<commit_after>extern crate automata;

use std::process;
use automata::automata::dfa::*;

fn main() {
    // (toto)*
    let dfa = DFABuilder::new()
        .add_start(0)
        .add_final(4)
        .add_final(0)
        .add_transition('t', 0, 1)
        .add_transition('o', 1, 2)
        .add_transition('t', 2, 3)
        .add_transition('o', 3, 4)
        .add_transition('t', 4, 1)
        .finalize();
    match dfa {
        Ok(dfa) => {
            println!("{}", dfa);
            println!("{:?}", dfa.run("toto"));
            println!("{:?}", dfa.run(""));
            println!("{:?}", dfa.run("t"));
            println!("{:?}", dfa.run("to"));
            println!("{:?}", dfa.run("tot"));
            println!("{:?}", dfa.run("totot"));
            println!("{:?}", dfa.run("totototo"));
        },
        _ => process::exit(1),
    }
}
<|endoftext|>


<commit_before>
#[derive(Copy, Clone)]
enum InstructionSet {
	PSH,
	ADD,
	POP,
	SET,
	HLT,
	VAL{value: i32},
}

struct VM {
	ip: usize,
	program: Vec<InstructionSet>,
	running: bool,
	sp: isize,
	stack: [InstructionSet; 256],
}

impl VM {
	pub fn new(prog: Vec<InstructionSet>) -> VM {
		VM {
			ip : 0,
			program: prog,
			running: true,
			sp: -1,
			stack:[InstructionSet::VAL{value:0}; 256],
		}
	}

	fn fetch(&mut self) -> InstructionSet {
		let instr = self.program[self.ip];
		instr
	}

	fn eval(&mut self, instr: InstructionSet) {
		use InstructionSet::*;
		match instr {
			HLT => self.running = false,
			PSH => {
				self.sp += 1;
				self.ip += 1; // move to operand location
				self.stack[self.sp as usize] = self.program[self.ip];
				//[DEBUG]
				println!("PSH {0}", match self.program[self.ip] {InstructionSet::VAL{value} => value, _=> 0,});
			},
			POP => {
				let val_popped = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;
				println!("POP {0}", val_popped);
			},
			ADD => {
				// first we pop the stack and store it as a
				let a = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				// we then pop the top of the stack and store it as b
				let b = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				//[DEBUG]
				println!("ADD {0}; {1}", a, b);

				// we then add the result and push it to the stack
				let result = b + a;
				self.sp += 1; // increment stack pointer **before**
				self.stack[self.sp as usize] = InstructionSet::VAL{value: result}; // set the value to the top of the stack

			},
			_ => println!("Instruction does not exist in instruction set."),
		}
	}
}

fn main() {
	let program = vec![
		InstructionSet::PSH, InstructionSet::VAL{value: 5},
		InstructionSet::PSH, InstructionSet::VAL{value: 6},
		InstructionSet::ADD,
		InstructionSet::POP,
		InstructionSet::HLT,
	];

	let mut vm = VM::new(program);
	loop {
		let instr = vm.fetch();
		vm.eval(instr);
		vm.ip += 1;
		if !vm.running {
			break;
		}
	}
}
<commit_msg>All isntructions are supported and function as described<commit_after>
use InstructionSet;

#[derive(Copy, Clone)]
enum InstructionSet {
	PSH,
	ADD,
	POP,
	SET,
	HLT,
	VAL{value: i32},
}

struct VM {
	ip: usize,
	program: Vec<InstructionSet>,
	running: bool,
	sp: isize,
	stack: [InstructionSet; 256],
}

impl VM {
	pub fn new(prog: Vec<InstructionSet>) -> VM {
		VM {
			ip : 0,
			program: prog,
			running: true,
			sp: -1,
			stack:[InstructionSet::VAL{value:0}; 256],
		}
	}

	fn fetch(&mut self) -> InstructionSet {
		let instr = self.program[self.ip];
		instr
	}

	fn eval(&mut self, instr: InstructionSet) {
		use InstructionSet::*;
		match instr {
			HLT => self.running = false,
			PSH => {
				self.sp += 1;
				self.ip += 1; // move to operand location
				self.stack[self.sp as usize] = self.program[self.ip];
				//[DEBUG]
				println!("PSH {0}", match self.program[self.ip] {InstructionSet::VAL{value} => value, _=> 0,});
			},
			POP => {
				let val_popped = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;
				println!("POP {0}", val_popped);
			},
			ADD => {
				// first we pop the stack and store it as a
				let a = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				// we then pop the top of the stack and store it as b
				let b = match self.stack[self.sp as usize] {
					InstructionSet::VAL{value} => value,
					_ => 0,
				};
				self.sp -= 1;

				//[DEBUG]
				println!("ADD {0}; {1}", a, b);

				// we then add the result and push it to the stack
				let result = b + a;
				self.sp += 1; // increment stack pointer **before**
				self.stack[self.sp as usize] = InstructionSet::VAL{value: result}; // set the value to the top of the stack

			},
			_ => println!("Instruction does not exist in instruction set."),
		}
	}
}

fn main() {
	let program = vec![
		InstructionSet::PSH, InstructionSet::VAL{value: 5},
		InstructionSet::PSH, InstructionSet::VAL{value: 6},
		InstructionSet::ADD,
		InstructionSet::POP,
		InstructionSet::HLT,
	];

	let mut vm = VM::new(program);
	loop {
		let instr = vm.fetch();
		vm.eval(instr);
		vm.ip += 1;
		if !vm.running {
			break;
		}
	}
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate rustc_serialize;

#[macro_use]
extern crate rouille;

mod alsa_input;
mod async_input;
mod base;
mod control;
mod file_input;
mod filters;
mod input_device;
mod input;
mod light;
mod output;
mod pipe_input;
mod resampler;
mod state_script;
mod ui;
mod web_ui;

use base::*;
use input::Input;
use getopts::Options;
use std::env;
use std::time::{Instant, Duration};
use filters::*;

impl From<getopts::Fail> for Error {
    fn from(e: getopts::Fail) -> Error {
        Error::new(&e.to_string())
    }
}

struct InputMixer {
    input: Box<Input>,
    current_frame: Option<Frame>,
    current_frame_pos: usize,
    volume: ui::Gain,
    gain: ui::Gain,
    multiplier: f32,
}

impl InputMixer {
    fn new(input: Box<Input>) -> InputMixer {
        let mut r = InputMixer {
            input: input,
            current_frame: None,
            current_frame_pos: 0,
            volume: ui::Gain { db: -20.0 },
            gain: ui::Gain { db: 0.0 },
            multiplier: 1.0,
        };
        r.update_multiplier();
        r
    }

    fn set_input_gain(&mut self, input_gain: ui::Gain) {
        self.gain = input_gain;
        self.update_multiplier();
    }

    fn set_master_volume(&mut self, volume: ui::Gain) {
        self.volume = volume;
        self.update_multiplier();
    }

    fn update_multiplier(&mut self) {
        self.multiplier = 10f32.powf((self.volume.db + self.gain.db) / 20.0);
    }

    fn mix_into(&mut self, mixed_frame: &mut Frame) -> Result<bool> {
        for i in 0..mixed_frame.len() {
            if self.current_frame.is_none() {
                self.current_frame = try!(self.input.read());
                self.current_frame_pos = 0;
            }

            let reset: bool;
            match self.current_frame {
                None => return Ok(i > 0),
                Some(ref frame) => {
                    mixed_frame.left[i] += self.multiplier * frame.left[self.current_frame_pos];
                    mixed_frame.right[i] += self.multiplier * frame.right[self.current_frame_pos];
                    self.current_frame_pos += 1;
                    reset = self.current_frame_pos >= frame.len();
                }
            }
            if reset {
                self.current_frame = None;
            }
        }

        if self.input.is_synchronized() {
            while try!(self.input.samples_buffered()) > MAX_QUEUED_FRAMES * mixed_frame.len() {
                try!(self.input.read());
            }
        }

        Ok(true)
    }
}

const OUTPUT_SHUTDOWN_SECONDS: u64 = 5;
const STANDBY_SECONDS: u64 = 3600;

fn run_loop(mut inputs: Vec<Box<Input>>,
            mut outputs: Vec<Box<output::Output>>,
            sample_rate: usize,
            shared_state: ui::SharedState,
            mut drc_filter: Option<StereoFilter<FirFilter>>)
            -> Result<()> {
    let ui_channel = shared_state.lock().add_observer();

    let mut mixers: Vec<Box<InputMixer>> = inputs
        .drain(..)
        .map(|i| Box::new(InputMixer::new(i)))
        .collect();

    let mut state = ui::StreamState::Active;
    let mut last_data_time = Instant::now();
    let mut selected_output = 0;

    let mut loudness_filter =
        StereoFilter::<LoudnessFilter>::new(SimpleFilterParams::new(sample_rate, 10.0));
    let mut voice_boost_filter: Option<StereoFilter<VoiceBoostFilter>> = None;
    let mut crossfeed_filter = CrossfeedFilter::new();

    let mut exclusive_mux_mode = true;
    let mut enable_drc = true;

    loop {
        let mut frame = Frame::new(sample_rate, outputs[selected_output].period_size());

        let mut have_data = false;
        for m in mixers.iter_mut() {
            have_data |= try!(m.mix_into(&mut frame));
            if have_data && exclusive_mux_mode {
                break;
            }
        }

        let now = Instant::now();
        if have_data {
            last_data_time = now;
        }

        let new_state = match (have_data, (now - last_data_time).as_secs()) {
            (true, _) => ui::StreamState::Active,
            (false, t) if t < OUTPUT_SHUTDOWN_SECONDS => ui::StreamState::Active,
            (false, t) if t < STANDBY_SECONDS => ui::StreamState::Inactive,
            (false, _) => ui::StreamState::Standby,
        };

        if state != new_state {
            state = new_state;
            println!("INFO: state: {}", state.as_str());
            shared_state.lock().on_stream_state(state);
            if state != ui::StreamState::Active {
                for ref mut out in &mut outputs {
                    out.deactivate();
                }
            }
        }

        if state == ui::StreamState::Active {
            loudness_filter.apply(&mut frame);
            match voice_boost_filter.as_mut() {
                Some(ref mut f) => {
                    f.apply(&mut frame);
                }
                None => (),
            }
            frame = crossfeed_filter.apply(frame);

            match (enable_drc, drc_filter.as_mut()) {
                (true, Some(ref mut f)) => {
                    f.apply(&mut frame);
                }
                _ => (),
            }

            try!(outputs[selected_output].write(frame));
        } else {
            std::thread::sleep(Duration::from_millis(500));
        }

        for msg in ui_channel.try_iter() {
            match msg {
                ui::UiMessage::SelectOutput { output } => {
                    outputs[output].deactivate();
                    selected_output = output;
                }
                ui::UiMessage::SetMasterVolume { volume, loudness } => {
                    for i in mixers.iter_mut() {
                        i.set_master_volume(volume)
                    }
                    loudness_filter.set_params(SimpleFilterParams::new(sample_rate, loudness.db));
                }
                ui::UiMessage::SetInputGain { device, gain } => {
                    mixers[device as usize].set_input_gain(gain);
                }
                ui::UiMessage::SetEnableDrc { enable } => enable_drc = enable,
                ui::UiMessage::SetVoiceBoost { boost } => {
                    if boost.db > 0.0 {
                        let p = SimpleFilterParams::new(sample_rate, boost.db);
                        if voice_boost_filter.is_some() {
                            voice_boost_filter.as_mut().unwrap().set_params(p);
                        } else {
                            voice_boost_filter = Some(StereoFilter::<VoiceBoostFilter>::new(
                            SimpleFilterParams::new(sample_rate, boost.db)))
                        }
                    } else {
                        voice_boost_filter = None
                    }
                }
                ui::UiMessage::SetCrossfeed { level, delay_ms } => {
                    crossfeed_filter.set_params(level, delay_ms);
                }
                ui::UiMessage::SetMuxMode { mux_mode: ui::MuxMode::Exclusive } => {
                    exclusive_mux_mode = true;
                }
                ui::UiMessage::SetMuxMode { mux_mode: ui::MuxMode::Mixer } => {
                    exclusive_mux_mode = false;
                }
            }
        }
    }
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn get_impulse_response(output: &mut Box<output::Output>, input: &mut Input) -> Result<Vec<f32>> {
    // Silence for 100 ms.
    for _ in 0..10 {
        let zero = Frame::new(output.sample_rate(), output.sample_rate() / 100);
        try!(output.write(zero));
    }

    // Impulse at -6db.
    let mut impulse = Frame::new(output.sample_rate(), 1);
    impulse.left[0] = 0.5;
    impulse.right[0] = 0.5;
    try!(output.write(impulse));

    // Silence for 500 ms.
    for _ in 0..50 {
        let zero = Frame::new(output.sample_rate(), output.sample_rate() / 100);
        try!(output.write(zero));
    }

    let mut result = Vec::<f32>::new();
    loop {
        match try!(input.read()) {
            None => return Ok(result),
            Some(s) => result.extend_from_slice(&s.left),
        };
    }
}

fn run() -> Result<()> {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optmulti("i", "input", "Audio input device name", "INPUT");
    opts.optmulti("f", "input-file", "Input file name", "FILE");
    opts.optmulti("p", "input-pipe", "Input pipe name", "PIPE");
    opts.optmulti("o", "output", "Output device name", "OUTPUT");
    opts.optopt("r", "sample-rate", "Output sample rate", "RATE");
    opts.optopt("w", "web-address", "Address:port for web UI", "ADDRESS");
    opts.optopt("s",
                "state-script",
                "Script to run on state change",
                "SCRIPT");
    opts.optmulti("c", "control-device", "Control input device", "INPUT_DEV");
    opts.optmulti("l", "light-device", "Light device", "LIGHT_DEV");
    opts.optmulti("F", "filter", "FIR filter file", "FIR_FILTER");
    opts.optopt("L",
                "filter-length",
                "Length for FIR filter (1000 by default)",
                "FILTER_LENGTH");
    opts.optflag("g", "loudness-graph", "Print out loudness graph");
    opts.optflag("m", "impulse-response", "Measure impulse response");
    opts.optflag("h", "help", "Print this help menu");

    let matches = try!(opts.parse(&args[1..]));

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return Ok(());
    }

    let mut inputs = Vec::<Box<Input>>::new();
    let mut input_states = Vec::<ui::InputState>::new();

    let sample_rate = match matches.opt_str("r").map(|x| x.parse::<usize>()) {
        None => 48000,
        Some(Ok(rate)) => rate,
        Some(Err(_)) => return Err(Error::new("Cannot parse sample-rate parameter.")),
    };

    let filter_length = match matches.opt_str("L").map(|x| x.parse::<usize>()) {
        None => 1000,
        Some(Ok(length)) => length,
        Some(Err(_)) => return Err(Error::new("Cannot parse filter length.")),
    };

    let mut fir_filters = Vec::new();
    for filename in matches.opt_strs("F") {
        let params = try!(FirFilterParams::new(&filename));
        fir_filters.push(params);
    }

    if matches.opt_present("g") {
        print!("Loudness filter");
        filters::draw_filter_graph::<LoudnessFilter>(sample_rate,
                                                     SimpleFilterParams::new(sample_rate, 10.0));

        print!("Voice Boost filter");
        filters::draw_filter_graph::<VoiceBoostFilter>(sample_rate,
                                                       SimpleFilterParams::new(sample_rate, 10.0));

        for i in 0..fir_filters.len() {
            print!("FIR filter {}", i);
            filters::draw_filter_graph::<FirFilter>(sample_rate,
                                                    filters::reduce_fir(fir_filters[i].clone(),
                                                                        filter_length));
        }

        return Ok(());
    }

    let mut outputs = Vec::<Box<output::Output>>::new();
    let mut output_states = Vec::<ui::OutputState>::new();

    for o in matches.opt_strs("o") {
        outputs.push(Box::new(output::ResamplingOutput::open(&o, sample_rate)));
        output_states.push(ui::OutputState::new(&o));
    }

    if matches.opt_present("m") {
        let mut input = async_input::AsyncInput::new(Box::new(
            try!(alsa_input::AlsaInput::open(&matches.opt_strs("i")[0], 192000, false))));
        let r = try!(get_impulse_response(&mut outputs[0], &mut input));
        let mut s = 0;
        println!(" {}", r.len());
        for i in 100..r.len() {
            if r[i].abs() > 0.02 {
                s = i - 100;
                break;
            }
        }

        for i in s..r.len() {
            println!("{} {}", i, r[i]);
        }
        return Ok(());
    }

    let drc_filter = if fir_filters.len() == 0 {
        None
    } else if fir_filters.len() == 2 {
        let (left, right) = reduce_fir_pair(fir_filters[0].clone(),
                                            fir_filters[1].clone(),
                                            filter_length);
        Some(StereoFilter::<FirFilter>::new_pair(left, right))
    } else {
        return Err(Error::new("Expected 0 or 2 FIR filters"));
    };

    for f in matches.opt_strs("f") {
        inputs.push(Box::new(try!(file_input::FileInput::open(&f))));
        input_states.push(ui::InputState::new(&f));
    }

    for p in matches.opt_strs("p") {
        inputs.push(Box::new(pipe_input::PipeInput::open(&p)));
        input_states.push(ui::InputState::new(&p));
    }

    for i in matches.opt_strs("i") {
        inputs.push(Box::new(alsa_input::ResilientAlsaInput::new(&i)));
        input_states.push(ui::InputState::new(&i));
    }

    if inputs.is_empty() {
        return Err(Error::new("No inputs specified."));
    }

    let shared_state = ui::SharedState::new(input_states, output_states);

    let web_addr = match matches.opt_str("w") {
        Some(addr) => addr,
        None => String::from("127.0.0.1:8000"),
    };
    web_ui::start_web(&web_addr, shared_state.clone());

    for c in matches.opt_strs("c") {
        control::start_input_handler(&c, shared_state.clone());
    }

    for l in matches.opt_strs("l") {
        light::start_light_controller(&l, shared_state.clone());
    }

    for s in matches.opt_strs("s") {
        state_script::start_state_script_contoller(&s, shared_state.clone());
    }

    let wrapped_inputs = inputs
        .drain(..)
        .map(|input| {
                 Box::<async_input::AsyncInput>::new(async_input::AsyncInput::new(
                Box::new(input::InputResampler::new(input, sample_rate))))
              as Box<Input>
             })
        .collect();

    run_loop(wrapped_inputs,
             outputs,
             sample_rate,
             shared_state,
             drc_filter)
}

fn main() {
    match run() {
        Err(e) => {
            println!("{}", e);
            std::process::exit(-1);
        }
        Ok(_) => (),
    }
}
<commit_msg>cleanup<commit_after>extern crate getopts;
extern crate rustc_serialize;

#[macro_use]
extern crate rouille;

mod alsa_input;
mod async_input;
mod base;
mod control;
mod file_input;
mod filters;
mod input_device;
mod input;
mod light;
mod output;
mod pipe_input;
mod resampler;
mod state_script;
mod ui;
mod web_ui;

use base::*;
use input::Input;
use getopts::Options;
use std::env;
use std::time::{Instant, Duration};
use filters::*;

impl From<getopts::Fail> for Error {
    fn from(e: getopts::Fail) -> Error {
        Error::new(&e.to_string())
    }
}

struct InputMixer {
    input: Box<Input>,
    current_frame: Option<Frame>,
    current_frame_pos: usize,
    volume: ui::Gain,
    gain: ui::Gain,
    multiplier: f32,
}

impl InputMixer {
    fn new(input: Box<Input>) -> InputMixer {
        let mut r = InputMixer {
            input: input,
            current_frame: None,
            current_frame_pos: 0,
            volume: ui::Gain { db: -20.0 },
            gain: ui::Gain { db: 0.0 },
            multiplier: 1.0,
        };
        r.update_multiplier();
        r
    }

    fn set_input_gain(&mut self, input_gain: ui::Gain) {
        self.gain = input_gain;
        self.update_multiplier();
    }

    fn set_master_volume(&mut self, volume: ui::Gain) {
        self.volume = volume;
        self.update_multiplier();
    }

    fn update_multiplier(&mut self) {
        self.multiplier = 10f32.powf((self.volume.db + self.gain.db) / 20.0);
    }

    fn mix_into(&mut self, mixed_frame: &mut Frame) -> Result<bool> {
        for i in 0..mixed_frame.len() {
            if self.current_frame.is_none() {
                self.current_frame = try!(self.input.read());
                self.current_frame_pos = 0;
            }

            let reset: bool;
            match self.current_frame {
                None => return Ok(i > 0),
                Some(ref frame) => {
                    mixed_frame.left[i] += self.multiplier * frame.left[self.current_frame_pos];
                    mixed_frame.right[i] += self.multiplier * frame.right[self.current_frame_pos];
                    self.current_frame_pos += 1;
                    reset = self.current_frame_pos >= frame.len();
                }
            }
            if reset {
                self.current_frame = None;
            }
        }

        if self.input.is_synchronized() {
            while try!(self.input.samples_buffered()) > MAX_QUEUED_FRAMES * mixed_frame.len() {
                try!(self.input.read());
            }
        }

        Ok(true)
    }
}

const OUTPUT_SHUTDOWN_SECONDS: u64 = 5;
const STANDBY_SECONDS: u64 = 3600;

fn run_loop(mut inputs: Vec<Box<Input>>,
            mut outputs: Vec<Box<output::Output>>,
            sample_rate: usize,
            shared_state: ui::SharedState,
            mut drc_filter: Option<StereoFilter<FirFilter>>)
            -> Result<()> {
    let ui_channel = shared_state.lock().add_observer();

    let mut mixers: Vec<Box<InputMixer>> = inputs
        .drain(..)
        .map(|i| Box::new(InputMixer::new(i)))
        .collect();

    let mut state = ui::StreamState::Active;
    let mut last_data_time = Instant::now();
    let mut selected_output = 0;

    let mut loudness_filter =
        StereoFilter::<LoudnessFilter>::new(SimpleFilterParams::new(sample_rate, 10.0));
    let mut voice_boost_filter: Option<StereoFilter<VoiceBoostFilter>> = None;
    let mut crossfeed_filter = CrossfeedFilter::new();

    let mut exclusive_mux_mode = true;
    let mut enable_drc = true;

    loop {
        let mut frame = Frame::new(sample_rate, outputs[selected_output].period_size());

        let mut have_data = false;
        for m in mixers.iter_mut() {
            have_data |= try!(m.mix_into(&mut frame));
            if have_data && exclusive_mux_mode {
                break;
            }
        }

        let now = Instant::now();
        if have_data {
            last_data_time = now;
        }

        let new_state = match (have_data, (now - last_data_time).as_secs()) {
            (true, _) => ui::StreamState::Active,
            (false, t) if t < OUTPUT_SHUTDOWN_SECONDS => ui::StreamState::Active,
            (false, t) if t < STANDBY_SECONDS => ui::StreamState::Inactive,
            (false, _) => ui::StreamState::Standby,
        };

        if state != new_state {
            state = new_state;
            println!("INFO: state: {}", state.as_str());
            shared_state.lock().on_stream_state(state);
            if state != ui::StreamState::Active {
                for ref mut out in &mut outputs {
                    out.deactivate();
                }
            }
        }

        if state == ui::StreamState::Active {
            loudness_filter.apply(&mut frame);
            match voice_boost_filter.as_mut() {
                Some(ref mut f) => {
                    f.apply(&mut frame);
                }
                None => (),
            }
            frame = crossfeed_filter.apply(frame);

            match (enable_drc, drc_filter.as_mut()) {
                (true, Some(ref mut f)) => {
                    f.apply(&mut frame);
                }
                _ => (),
            }

            try!(outputs[selected_output].write(frame));
        } else {
            std::thread::sleep(Duration::from_millis(500));
        }

        for msg in ui_channel.try_iter() {
            match msg {
                ui::UiMessage::SelectOutput { output } => {
                    outputs[output].deactivate();
                    selected_output = output;
                }
                ui::UiMessage::SetMasterVolume { volume, loudness } => {
                    for i in mixers.iter_mut() {
                        i.set_master_volume(volume)
                    }
                    loudness_filter.set_params(SimpleFilterParams::new(sample_rate, loudness.db));
                }
                ui::UiMessage::SetInputGain { device, gain } => {
                    mixers[device as usize].set_input_gain(gain);
                }
                ui::UiMessage::SetEnableDrc { enable } => enable_drc = enable,
                ui::UiMessage::SetVoiceBoost { boost } => {
                    if boost.db > 0.0 {
                        let p = SimpleFilterParams::new(sample_rate, boost.db);
                        if voice_boost_filter.is_some() {
                            voice_boost_filter.as_mut().unwrap().set_params(p);
                        } else {
                            voice_boost_filter = Some(StereoFilter::<VoiceBoostFilter>::new(
                            SimpleFilterParams::new(sample_rate, boost.db)))
                        }
                    } else {
                        voice_boost_filter = None
                    }
                }
                ui::UiMessage::SetCrossfeed { level, delay_ms } => {
                    crossfeed_filter.set_params(level, delay_ms);
                }
                ui::UiMessage::SetMuxMode { mux_mode: ui::MuxMode::Exclusive } => {
                    exclusive_mux_mode = true;
                }
                ui::UiMessage::SetMuxMode { mux_mode: ui::MuxMode::Mixer } => {
                    exclusive_mux_mode = false;
                }
            }
        }
    }
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

fn get_impulse_response(output: &mut Box<output::Output>, input: &mut Input) -> Result<Vec<f32>> {
    // Silence for 100 ms.
    for _ in 0..10 {
        let zero = Frame::new(output.sample_rate(), output.sample_rate() / 100);
        try!(output.write(zero));
    }

    // Impulse at -6db.
    let mut impulse = Frame::new(output.sample_rate(), 1);
    impulse.left[0] = 0.5;
    impulse.right[0] = 0.5;
    try!(output.write(impulse));

    // Silence for 500 ms.
    for _ in 0..50 {
        let zero = Frame::new(output.sample_rate(), output.sample_rate() / 100);
        try!(output.write(zero));
    }

    let mut result = Vec::<f32>::new();
    loop {
        match try!(input.read()) {
            None => return Ok(result),
            Some(s) => result.extend_from_slice(&s.left),
        };
    }
}

fn run() -> Result<()> {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optmulti("i", "input", "Audio input device name", "INPUT");
    opts.optmulti("f", "input-file", "Input file name", "FILE");
    opts.optmulti("p", "input-pipe", "Input pipe name", "PIPE");
    opts.optmulti("o", "output", "Output device name", "OUTPUT");
    opts.optopt("r", "sample-rate", "Output sample rate", "RATE");
    opts.optopt("w", "web-address", "Address:port for web UI", "ADDRESS");
    opts.optopt("s",
                "state-script",
                "Script to run on state change",
                "SCRIPT");
    opts.optmulti("c", "control-device", "Control input device", "INPUT_DEV");
    opts.optmulti("l", "light-device", "Light device", "LIGHT_DEV");
    opts.optmulti("F", "filter", "FIR filter file", "FIR_FILTER");
    opts.optopt("L",
                "filter-length",
                "Length for FIR filter (1000 by default)",
                "FILTER_LENGTH");
    opts.optflag("g", "loudness-graph", "Print out loudness graph");
    opts.optflag("m", "impulse-response", "Measure impulse response");
    opts.optflag("h", "help", "Print this help menu");

    let matches = try!(opts.parse(&args[1..]));

    if matches.opt_present("h") {
        print_usage(&program, opts);
        return Ok(());
    }

    let mut inputs = Vec::<Box<Input>>::new();
    let mut input_states = Vec::<ui::InputState>::new();

    let sample_rate = match matches.opt_str("r").map(|x| x.parse::<usize>()) {
        None => 48000,
        Some(Ok(rate)) => rate,
        Some(Err(_)) => return Err(Error::new("Cannot parse sample-rate parameter.")),
    };

    let filter_length = match matches.opt_str("L").map(|x| x.parse::<usize>()) {
        None => 1000,
        Some(Ok(length)) => length,
        Some(Err(_)) => return Err(Error::new("Cannot parse filter length.")),
    };

    let mut fir_filters = Vec::new();
    for filename in matches.opt_strs("F") {
        let params = try!(FirFilterParams::new(&filename));
        fir_filters.push(params);
    }

    if matches.opt_present("g") {
        print!("Loudness filter");
        filters::draw_filter_graph::<LoudnessFilter>(sample_rate,
                                                     SimpleFilterParams::new(sample_rate, 10.0));

        print!("Voice Boost filter");
        filters::draw_filter_graph::<VoiceBoostFilter>(sample_rate,
                                                       SimpleFilterParams::new(sample_rate, 10.0));

        for i in 0..fir_filters.len() {
            print!("FIR filter {}", i);
            filters::draw_filter_graph::<FirFilter>(sample_rate,
                                                    filters::reduce_fir(fir_filters[i].clone(),
                                                                        filter_length));
        }

        return Ok(());
    }

    let mut outputs = Vec::<Box<output::Output>>::new();
    let mut output_states = Vec::<ui::OutputState>::new();

    for o in matches.opt_strs("o") {
        outputs.push(Box::new(output::ResamplingOutput::open(&o, sample_rate)));
        output_states.push(ui::OutputState::new(&o));
    }

    if matches.opt_present("m") {
        let mut input = async_input::AsyncInput::new(Box::new(
            try!(alsa_input::AlsaInput::open(&matches.opt_strs("i")[0], 192000, false))));
        let r = try!(get_impulse_response(&mut outputs[0], &mut input));
        let mut s = 0;
        for i in 100..r.len() {
            if r[i].abs() > 0.02 {
                s = i - 100;
                break;
            }
        }

        for i in s..r.len() {
            println!("{} {}", i, r[i]);
        }
        return Ok(());
    }

    let drc_filter = if fir_filters.len() == 0 {
        None
    } else if fir_filters.len() == 2 {
        let (left, right) = reduce_fir_pair(fir_filters[0].clone(),
                                            fir_filters[1].clone(),
                                            filter_length);
        Some(StereoFilter::<FirFilter>::new_pair(left, right))
    } else {
        return Err(Error::new("Expected 0 or 2 FIR filters"));
    };

    for f in matches.opt_strs("f") {
        inputs.push(Box::new(try!(file_input::FileInput::open(&f))));
        input_states.push(ui::InputState::new(&f));
    }

    for p in matches.opt_strs("p") {
        inputs.push(Box::new(pipe_input::PipeInput::open(&p)));
        input_states.push(ui::InputState::new(&p));
    }

    for i in matches.opt_strs("i") {
        inputs.push(Box::new(alsa_input::ResilientAlsaInput::new(&i)));
        input_states.push(ui::InputState::new(&i));
    }

    if inputs.is_empty() {
        return Err(Error::new("No inputs specified."));
    }

    let shared_state = ui::SharedState::new(input_states, output_states);

    let web_addr = match matches.opt_str("w") {
        Some(addr) => addr,
        None => String::from("127.0.0.1:8000"),
    };
    web_ui::start_web(&web_addr, shared_state.clone());

    for c in matches.opt_strs("c") {
        control::start_input_handler(&c, shared_state.clone());
    }

    for l in matches.opt_strs("l") {
        light::start_light_controller(&l, shared_state.clone());
    }

    for s in matches.opt_strs("s") {
        state_script::start_state_script_contoller(&s, shared_state.clone());
    }

    let wrapped_inputs = inputs
        .drain(..)
        .map(|input| {
                 Box::<async_input::AsyncInput>::new(async_input::AsyncInput::new(
                Box::new(input::InputResampler::new(input, sample_rate))))
              as Box<Input>
             })
        .collect();

    run_loop(wrapped_inputs,
             outputs,
             sample_rate,
             shared_state,
             drc_filter)
}

fn main() {
    match run() {
        Err(e) => {
            println!("{}", e);
            std::process::exit(-1);
        }
        Ok(_) => (),
    }
}
<|endoftext|>


<commit_before>//! Alacritty - The GPU Enhanced Terminal
#![feature(question_mark)]
#![feature(range_contains)]
#![feature(inclusive_range_syntax)]
#![feature(io)]
#![feature(unicode)]

extern crate fontconfig;
extern crate freetype;
extern crate libc;
extern crate glutin;
extern crate cgmath;
extern crate euclid;
extern crate notify;
extern crate arrayvec;

#[macro_use]
extern crate bitflags;

#[macro_use]
mod macros;

mod list_fonts;
mod text;
mod renderer;
mod grid;
mod meter;
mod tty;
mod ansi;
mod term;
mod util;

use std::sync::mpsc;
use std::collections::HashMap;
use std::io::{BufReader, Read, BufRead, Write, BufWriter};
use std::sync::Arc;
use std::fs::File;

use std::os::unix::io::{FromRawFd, AsRawFd};

use renderer::{QuadRenderer, GlyphCache, LoadGlyph};
use text::FontDesc;
use grid::Grid;
use term::Term;
use meter::Meter;
use util::thread;
use tty::process_should_exit;

/// Things that the render/update thread needs to respond to
#[derive(Debug)]
enum Event {
    PtyChar(char),
    Glutin(glutin::Event),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum ShouldExit {
    Yes,
    No
}

fn handle_event<W>(event: Event,
                   writer: &mut W,
                   terminal: &mut Term,
                   pty_parser: &mut ansi::Parser) -> ShouldExit
    where W: Write
{
    match event {
        // Handle char from pty
        Event::PtyChar(c) => pty_parser.advance(terminal, c),
        // Handle keyboard/mouse input and other window events
        Event::Glutin(gevent) => match gevent {
            glutin::Event::Closed => return ShouldExit::Yes,
            glutin::Event::ReceivedCharacter(c) => {
                let encoded = c.encode_utf8();
                writer.write(encoded.as_slice()).unwrap();
            },
            glutin::Event::KeyboardInput(state, _code, key) => {
                match state {
                    glutin::ElementState::Pressed => {
                        match key {
                            Some(glutin::VirtualKeyCode::Up) => {
                                writer.write("\x1b[A".as_bytes()).unwrap();
                            },
                            Some(glutin::VirtualKeyCode::Down) => {
                                writer.write("\x1b[B".as_bytes()).unwrap();
                            },
                            Some(glutin::VirtualKeyCode::Left) => {
                                writer.write("\x1b[D".as_bytes()).unwrap();
                            },
                            Some(glutin::VirtualKeyCode::Right) => {
                                writer.write("\x1b[C".as_bytes()).unwrap();
                            },
                            _ => (),
                        }
                    },
                    _ => (),
                }
            },
            _ => ()
        }
    }

    ShouldExit::No
}

#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
pub struct Rgb {
    r: u8,
    g: u8,
    b: u8,
}

mod gl {
    include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}

#[derive(Debug)]
struct TermProps {
    width: f32,
    height: f32,
    cell_width: f32,
    cell_height: f32,
    sep_x: f32,
    sep_y: f32,
}

fn main() {
    let window = glutin::WindowBuilder::new()
                     .with_title("alacritty".into())
                     .build()
                     .unwrap();

    let (width, height) = window.get_inner_size_pixels().unwrap();
    unsafe {
        window.make_current().unwrap();
    }

    unsafe {
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
        gl::Viewport(0, 0, width as i32, height as i32);
    }

    let (dpi_x, dpi_y) = window.get_dpi().unwrap();
    let dpr = window.hidpi_factor();

    let font_size = 11.;

    let sep_x = 2;
    let sep_y = 5;

    let desc = FontDesc::new("DejaVu Sans Mono", "Book");
    let mut rasterizer = text::Rasterizer::new(dpi_x, dpi_y, dpr);

    let (cell_width, cell_height) = rasterizer.box_size_for_font(&desc, font_size);

    let num_cols = grid::num_cells_axis(cell_width, sep_x, width);
    let num_rows = grid::num_cells_axis(cell_height, sep_y, height);

    let tty = tty::new(num_rows as u8, num_cols as u8);
    tty.resize(num_rows as usize, num_cols as usize, width as usize, height as usize);
    let mut reader = tty.reader();
    let mut writer = tty.writer();

    println!("num_cols, num_rows = {}, {}", num_cols, num_rows);

    let mut grid = Grid::new(num_rows as usize, num_cols as usize);

    let props = TermProps {
        cell_width: cell_width as f32,
        sep_x: sep_x as f32,
        cell_height: cell_height as f32,
        sep_y: sep_y as f32,
        height: height as f32,
        width: width as f32,
    };

    let mut renderer = QuadRenderer::new(width, height);

    let mut glyph_cache = GlyphCache::new(rasterizer, desc, font_size);
    renderer.with_api(&props, |mut api| {
        glyph_cache.init(&mut api);
    });

    unsafe {
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
        gl::Enable(gl::MULTISAMPLE);
    }

    let (tx, rx) = mpsc::channel();
    let reader_tx = tx.clone();
    let reader_thread = thread::spawn_named("TTY Reader", move || {
        for c in reader.chars() {
            let c = c.unwrap();
            reader_tx.send(Event::PtyChar(c)).unwrap();
        }
    });

    let mut terminal = Term::new(tty, grid);
    let mut meter = Meter::new();

    let mut pty_parser = ansi::Parser::new();

    let window = Arc::new(window);
    let window_ref = window.clone();
    let input_thread = thread::spawn_named("Input Thread", move || {
        for event in window_ref.wait_events() {
            tx.send(Event::Glutin(event));
            if process_should_exit() {
                break;
            }
        }

    });

    'main_loop: loop {
        // Block waiting for next event
        match rx.recv() {
            Ok(e) => {
                let res = handle_event(e, &mut writer, &mut terminal, &mut pty_parser);
                if res == ShouldExit::Yes {
                    break;
                }
            },
            Err(mpsc::RecvError) => break,
        }

        // Handle Any events that have been queued
        loop {
            match rx.try_recv() {
                Ok(e) => {
                    let res = handle_event(e, &mut writer, &mut terminal, &mut pty_parser);

                    if res == ShouldExit::Yes {
                        break;
                    }
                },
                Err(mpsc::TryRecvError::Disconnected) => break 'main_loop,
                Err(mpsc::TryRecvError::Empty) => break,
            }

            // TODO make sure this doesn't block renders
        }

        unsafe {
            gl::ClearColor(0.0, 0.0, 0.00, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        {
            let _sampler = meter.sampler();

            renderer.with_api(&props, |mut api| {
                // Draw the grid
                api.render_grid(terminal.grid(), &mut glyph_cache);

                // Also draw the cursor
                if !terminal.mode().contains(term::mode::TEXT_CURSOR) {
                    api.render_cursor(terminal.cursor(), &mut glyph_cache);
                }
            })
        }

        // Draw render timer
        let timing = format!("{:.3} usec", meter.average());
        let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
        renderer.with_api(&props, |mut api| {
            api.render_string(&timing[..], &mut glyph_cache, &color);
        });

        window.swap_buffers().unwrap();

        if process_should_exit() {
            break;
        }
    }

    reader_thread.join().ok();
    input_thread.join().ok();
    println!("Goodbye");
}

<commit_msg>Sort some imports<commit_after>//! Alacritty - The GPU Enhanced Terminal
#![feature(question_mark)]
#![feature(range_contains)]
#![feature(inclusive_range_syntax)]
#![feature(io)]
#![feature(unicode)]

extern crate fontconfig;
extern crate freetype;
extern crate libc;
extern crate glutin;
extern crate cgmath;
extern crate euclid;
extern crate notify;
extern crate arrayvec;

#[macro_use]
extern crate bitflags;

#[macro_use]
mod macros;

mod list_fonts;
mod text;
mod renderer;
mod grid;
mod meter;
mod tty;
mod ansi;
mod term;
mod util;

use std::collections::HashMap;
use std::fs::File;
use std::io::{BufReader, Read, BufRead, Write, BufWriter};
use std::sync::Arc;
use std::sync::mpsc;

use std::os::unix::io::{FromRawFd, AsRawFd};

use grid::Grid;
use meter::Meter;
use renderer::{QuadRenderer, GlyphCache, LoadGlyph};
use term::Term;
use text::FontDesc;
use tty::process_should_exit;
use util::thread;

/// Things that the render/update thread needs to respond to
#[derive(Debug)]
enum Event {
    PtyChar(char),
    Glutin(glutin::Event),
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum ShouldExit {
    Yes,
    No
}

fn handle_event<W>(event: Event,
                   writer: &mut W,
                   terminal: &mut Term,
                   pty_parser: &mut ansi::Parser) -> ShouldExit
    where W: Write
{
    match event {
        // Handle char from pty
        Event::PtyChar(c) => pty_parser.advance(terminal, c),
        // Handle keyboard/mouse input and other window events
        Event::Glutin(gevent) => match gevent {
            glutin::Event::Closed => return ShouldExit::Yes,
            glutin::Event::ReceivedCharacter(c) => {
                let encoded = c.encode_utf8();
                writer.write(encoded.as_slice()).unwrap();
            },
            glutin::Event::KeyboardInput(state, _code, key) => {
                match state {
                    glutin::ElementState::Pressed => {
                        match key {
                            Some(glutin::VirtualKeyCode::Up) => {
                                writer.write("\x1b[A".as_bytes()).unwrap();
                            },
                            Some(glutin::VirtualKeyCode::Down) => {
                                writer.write("\x1b[B".as_bytes()).unwrap();
                            },
                            Some(glutin::VirtualKeyCode::Left) => {
                                writer.write("\x1b[D".as_bytes()).unwrap();
                            },
                            Some(glutin::VirtualKeyCode::Right) => {
                                writer.write("\x1b[C".as_bytes()).unwrap();
                            },
                            _ => (),
                        }
                    },
                    _ => (),
                }
            },
            _ => ()
        }
    }

    ShouldExit::No
}

#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
pub struct Rgb {
    r: u8,
    g: u8,
    b: u8,
}

mod gl {
    include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
}

#[derive(Debug)]
struct TermProps {
    width: f32,
    height: f32,
    cell_width: f32,
    cell_height: f32,
    sep_x: f32,
    sep_y: f32,
}

fn main() {
    let window = glutin::WindowBuilder::new()
                     .with_title("alacritty".into())
                     .build()
                     .unwrap();

    let (width, height) = window.get_inner_size_pixels().unwrap();
    unsafe {
        window.make_current().unwrap();
    }

    unsafe {
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
        gl::Viewport(0, 0, width as i32, height as i32);
    }

    let (dpi_x, dpi_y) = window.get_dpi().unwrap();
    let dpr = window.hidpi_factor();

    let font_size = 11.;

    let sep_x = 2;
    let sep_y = 5;

    let desc = FontDesc::new("DejaVu Sans Mono", "Book");
    let mut rasterizer = text::Rasterizer::new(dpi_x, dpi_y, dpr);

    let (cell_width, cell_height) = rasterizer.box_size_for_font(&desc, font_size);

    let num_cols = grid::num_cells_axis(cell_width, sep_x, width);
    let num_rows = grid::num_cells_axis(cell_height, sep_y, height);

    let tty = tty::new(num_rows as u8, num_cols as u8);
    tty.resize(num_rows as usize, num_cols as usize, width as usize, height as usize);
    let mut reader = tty.reader();
    let mut writer = tty.writer();

    println!("num_cols, num_rows = {}, {}", num_cols, num_rows);

    let mut grid = Grid::new(num_rows as usize, num_cols as usize);

    let props = TermProps {
        cell_width: cell_width as f32,
        sep_x: sep_x as f32,
        cell_height: cell_height as f32,
        sep_y: sep_y as f32,
        height: height as f32,
        width: width as f32,
    };

    let mut renderer = QuadRenderer::new(width, height);

    let mut glyph_cache = GlyphCache::new(rasterizer, desc, font_size);
    renderer.with_api(&props, |mut api| {
        glyph_cache.init(&mut api);
    });

    unsafe {
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
        gl::Enable(gl::MULTISAMPLE);
    }

    let (tx, rx) = mpsc::channel();
    let reader_tx = tx.clone();
    let reader_thread = thread::spawn_named("TTY Reader", move || {
        for c in reader.chars() {
            let c = c.unwrap();
            reader_tx.send(Event::PtyChar(c)).unwrap();
        }
    });

    let mut terminal = Term::new(tty, grid);
    let mut meter = Meter::new();

    let mut pty_parser = ansi::Parser::new();

    let window = Arc::new(window);
    let window_ref = window.clone();
    let input_thread = thread::spawn_named("Input Thread", move || {
        for event in window_ref.wait_events() {
            tx.send(Event::Glutin(event));
            if process_should_exit() {
                break;
            }
        }

    });

    'main_loop: loop {
        // Block waiting for next event
        match rx.recv() {
            Ok(e) => {
                let res = handle_event(e, &mut writer, &mut terminal, &mut pty_parser);
                if res == ShouldExit::Yes {
                    break;
                }
            },
            Err(mpsc::RecvError) => break,
        }

        // Handle Any events that have been queued
        loop {
            match rx.try_recv() {
                Ok(e) => {
                    let res = handle_event(e, &mut writer, &mut terminal, &mut pty_parser);

                    if res == ShouldExit::Yes {
                        break;
                    }
                },
                Err(mpsc::TryRecvError::Disconnected) => break 'main_loop,
                Err(mpsc::TryRecvError::Empty) => break,
            }

            // TODO make sure this doesn't block renders
        }

        unsafe {
            gl::ClearColor(0.0, 0.0, 0.00, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        {
            let _sampler = meter.sampler();

            renderer.with_api(&props, |mut api| {
                // Draw the grid
                api.render_grid(terminal.grid(), &mut glyph_cache);

                // Also draw the cursor
                if !terminal.mode().contains(term::mode::TEXT_CURSOR) {
                    api.render_cursor(terminal.cursor(), &mut glyph_cache);
                }
            })
        }

        // Draw render timer
        let timing = format!("{:.3} usec", meter.average());
        let color = Rgb { r: 0xd5, g: 0x4e, b: 0x53 };
        renderer.with_api(&props, |mut api| {
            api.render_string(&timing[..], &mut glyph_cache, &color);
        });

        window.swap_buffers().unwrap();

        if process_should_exit() {
            break;
        }
    }

    reader_thread.join().ok();
    input_thread.join().ok();
    println!("Goodbye");
}

<|endoftext|>


<commit_before>#![feature(core)]

extern crate rand;

use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};
use std::iter::FromIterator;
use rand::distributions::{IndependentSample, Range};

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

struct Individual {
    solution: Vec<f64>,
    fitness: f64,
}

impl Individual {
    fn new() -> Individual {
        let n = 50;
        let mut rng = rand::thread_rng();
        let range = Range::new(-512.03_f64, 511.97);

        let solution = Vec::from_iter((0..n).map(|_| range.ind_sample(&mut rng)));
        let fitness = schwefel(&solution);

        Individual { solution: solution, fitness: fitness }
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl PartialEq<Individual> for Individual {
    /// This delegates to `eq` on `fitness: f64`
    fn eq(&self, other: &Individual) -> bool {
        self.fitness.eq(&other.fitness)
    }
}

impl PartialOrd for Individual {
    /// This delegates to `partial_cmp` on `fitness: f64`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}

fn main() {
    let pop_size = 128;

    // initialize population
    let population = Vec::from_iter((0..pop_size).map(|_| Individual::new()));

    let best = population.iter().min_by(|x| schwefel(&x.solution) as i64).unwrap();
    println!("The best solution was {:?}", best.solution);
    println!("Its fitness was {}", best.fitness);
}
<commit_msg>Replace min_by with min<commit_after>extern crate rand;

use std::cmp::{Eq, PartialEq, Ordering, PartialOrd};
use std::iter::FromIterator;
use rand::distributions::{IndependentSample, Range};

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

struct Individual {
    solution: Vec<f64>,
    fitness: f64,
}

impl Individual {
    fn new() -> Individual {
        let n = 50;
        let mut rng = rand::thread_rng();
        let range = Range::new(-512.03_f64, 511.97);

        let solution = Vec::from_iter((0..n).map(|_| range.ind_sample(&mut rng)));
        let fitness = schwefel(&solution);

        Individual { solution: solution, fitness: fitness }
    }
}

impl Eq for Individual {}

impl Ord for Individual {
    /// This dangerously delegates to `partial_cmp`
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl PartialEq<Individual> for Individual {
    /// This delegates to `eq` on `fitness: f64`
    fn eq(&self, other: &Individual) -> bool {
        self.fitness.eq(&other.fitness)
    }
}

impl PartialOrd for Individual {
    /// This delegates to `partial_cmp` on `fitness: f64`
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.fitness.partial_cmp(&other.fitness)
    }
}

fn main() {
    let pop_size = 128;

    // initialize population
    let population = Vec::from_iter((0..pop_size).map(|_| Individual::new()));

    let best = population.iter().min().unwrap();
    println!("The best solution was {:?}", best.solution);
    println!("Its fitness was {}", best.fitness);
}
<|endoftext|>