<commit_before>//! HTTP Proxy client server

use std::{
    collections::HashMap,
    convert::Infallible,
    future::Future,
    io,
    net::{IpAddr, SocketAddr},
    pin::Pin,
    sync::Arc,
    task::{self, Poll},
};

use futures::{
    future,
    future::{BoxFuture, Either},
    FutureExt,
};
use hyper::{
    client::connect::{Connected, Connection},
    server::conn::AddrStream,
    service::{make_service_fn, service_fn},
    upgrade::Upgraded,
    Body,
    Client,
    Method,
    Request,
    Response,
    Server,
    StatusCode,
    Uri,
};
use log::{debug, error, info, trace};
use pin_project::pin_project;
use tokio;
use tower;

use super::{CryptoStream, STcpStream};
use crate::{
    config::ServerConfig,
    context::SharedContext,
    relay::{
        loadbalancing::server::{ping, LoadBalancer, PingBalancer},
        socks5::Address,
    },
};

#[derive(Clone)]
struct ShadowSocksConnector {
    context: SharedContext,
    svr_cfg: Arc<ServerConfig>,
}

impl ShadowSocksConnector {
    fn new(context: SharedContext, svr_cfg: Arc<ServerConfig>) -> ShadowSocksConnector {
        ShadowSocksConnector { context, svr_cfg }
    }
}

impl tower::Service<Address> for ShadowSocksConnector {
    type Error = io::Error;
    type Future = ShadowSocksConnecting;
    type Response = CryptoStream<STcpStream>;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, addr: Address) -> Self::Future {
        let svr_cfg = self.svr_cfg.clone();
        let context = self.context.clone();

        ShadowSocksConnecting {
            fut: async move {
                let stream = super::connect_proxy_server(&*context, &*svr_cfg).await?;
                super::proxy_server_handshake(stream, svr_cfg.clone(), &addr).await
            }
            .boxed(),
        }
    }
}

impl tower::Service<Uri> for ShadowSocksConnector {
    type Error = io::Error;
    type Future = ShadowSocksConnecting;
    type Response = CryptoStream<STcpStream>;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, dst: Uri) -> Self::Future {
        let svr_cfg = self.svr_cfg.clone();
        let context = self.context.clone();

        ShadowSocksConnecting {
            fut: async move {
                match host_addr(&dst) {
                    None => {
                        use std::io::{Error, ErrorKind};

                        error!("HTTP target URI must be a valid address, but found: {}", dst);

                        let err = Error::new(ErrorKind::Other, "URI must be a valid Address");
                        Err(err)
                    }
                    Some(addr) => {
                        let stream = super::connect_proxy_server(&*context, &*svr_cfg).await?;
                        super::proxy_server_handshake(stream, svr_cfg.clone(), &addr).await
                    }
                }
            }
            .boxed(),
        }
    }
}

#[pin_project]
struct ShadowSocksConnecting {
    #[pin]
    fut: BoxFuture<'static, io::Result<CryptoStream<STcpStream>>>,
}

impl Future for ShadowSocksConnecting {
    type Output = io::Result<CryptoStream<STcpStream>>;

    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        self.project().fut.poll(cx)
    }
}

fn host_addr(uri: &Uri) -> Option<Address> {
    let port = match uri.port_u16() {
        Some(p) => p,
        None => {
            match uri.scheme_str() {
                None => 80, // Assume it is http
                Some("http") => 80,
                Some("https") => 443,
                _ => return None, // Not supported
            }
        }
    };

    match uri.host() {
        None => None,
        Some(host_str) => match host_str.parse::<IpAddr>() {
            Ok(ip) => Some(Address::from(SocketAddr::new(ip, port))),
            Err(..) => Some(Address::DomainNameAddress(host_str.to_owned(), port)),
        },
    }
}

impl Connection for CryptoStream<STcpStream> {
    fn connected(&self) -> Connected {
        Connected::new()
    }
}

async fn establish_connect_tunnel(
    upgraded: Upgraded,
    mut stream: CryptoStream<STcpStream>,
    svr_cfg: Arc<ServerConfig>,
    client_addr: SocketAddr,
    addr: Address,
) {
    use tokio::io::{copy, split};

    let (mut r, mut w) = split(upgraded);
    let (mut svr_r, mut svr_w) = stream.split();

    let rhalf = copy(&mut r, &mut svr_w);
    let whalf = copy(&mut svr_r, &mut w);

    debug!(
        "CONNECT relay established {} <-> {} ({})",
        client_addr,
        svr_cfg.addr(),
        addr
    );

    match future::select(rhalf, whalf).await {
        Either::Left((Ok(..), _)) => trace!("CONNECT relay {} -> {} ({}) closed", client_addr, svr_cfg.addr(), addr),
        Either::Left((Err(err), _)) => trace!(
            "CONNECT relay {} -> {} ({}) closed with error {:?}",
            client_addr,
            svr_cfg.addr(),
            addr,
            err,
        ),
        Either::Right((Ok(..), _)) => trace!("CONNECT relay {} <- {} ({}) closed", client_addr, svr_cfg.addr(), addr),
        Either::Right((Err(err), _)) => trace!(
            "CONNECT relay {} <- {} ({}) closed with error {:?}",
            client_addr,
            svr_cfg.addr(),
            addr,
            err,
        ),
    }

    debug!("CONNECT relay {} <-> {} ({}) closed", client_addr, svr_cfg.addr(), addr);
}

type ShadowSocksClient = Client<ShadowSocksConnector>;

async fn server_dispatch(
    context: SharedContext,
    req: Request<Body>,
    svr_cfg: Arc<ServerConfig>,
    client_addr: SocketAddr,
    client: ShadowSocksClient,
) -> Result<Response<Body>, io::Error> {
    // Parse URI
    //
    // Proxy request URI must contains a host
    let host = match host_addr(req.uri()) {
        None => {
            error!("HTTP {} URI is not a valid address. URI: {}", req.method(), req.uri());

            let mut resp = Response::new(Body::from("URI must be a valid Address"));
            *resp.status_mut() = StatusCode::BAD_REQUEST;

            return Ok(resp);
        }
        Some(h) => h,
    };

    if Method::CONNECT == req.method() {
        // Establish a TCP tunnel
        // https://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01

        debug!("HTTP CONNECT {}", host);

        // Connect to Shadowsocks' remote
        //
        // FIXME: What STATUS should I return for connection error?
        let stream = super::connect_proxy_server(&*context, &*svr_cfg).await?;
        let stream = super::proxy_server_handshake(stream, svr_cfg.clone(), &host).await?;

        debug!(
            "CONNECT relay connected {} <-> {} ({})",
            client_addr,
            svr_cfg.addr(),
            host
        );

        // Upgrade to a TCP tunnel
        //
        // Note: only after client received an empty body with STATUS_OK can the
        // connection be upgraded, so we can't return a response inside
        // `on_upgrade` future.
        tokio::spawn(async move {
            match req.into_body().on_upgrade().await {
                Ok(upgraded) => {
                    trace!(
                        "CONNECT tunnel upgrade success, {} <-> {} ({})",
                        client_addr,
                        svr_cfg.addr(),
                        host
                    );

                    establish_connect_tunnel(upgraded, stream, svr_cfg, client_addr, host).await
                }
                Err(e) => {
                    error!(
                        "Failed to upgrade TCP tunnel {} <-> {} ({}), error: {}",
                        client_addr,
                        svr_cfg.addr(),
                        host,
                        e
                    );
                }
            }
        });

        let resp = Response::builder()
            .header("Proxy-Agent", format!("ShadowSocks/{}", crate::VERSION))
            .body(Body::empty())
            .unwrap();

        Ok(resp)
    } else {
        let method = req.method().clone();

        debug!("HTTP {} {}", method, host);

        let res = match client.request(req).await {
            Ok(res) => res,
            Err(err) => {
                error!(
                    "HTTP {} {} <-> {} ({}) relay failed, error: {}",
                    method,
                    client_addr,
                    svr_cfg.addr(),
                    host,
                    err
                );

                let mut resp = Response::new(Body::from(format!("Relay failed to {}", host)));
                *resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;

                return Ok(resp);
            }
        };

        debug!(
            "HTTP {} relay {} <-> {} ({}) finished",
            method,
            client_addr,
            svr_cfg.addr(),
            host
        );

        Ok(res)
    }
}

/// Starts a TCP local server with HTTP proxy protocol
pub async fn run(context: SharedContext) -> io::Result<()> {
    let local_addr = *context.config().local.as_ref().expect("Missing local config");

    let mut servers = PingBalancer::new(context.clone(), ping::ServerType::Tcp).await;

    let mut server_clients = HashMap::new();

    // Create HTTP clients for each remote servers
    for svr_cfg in servers.servers() {
        let addr_str = svr_cfg.addr().to_string();
        let client = Client::builder().build::<_, Body>(ShadowSocksConnector::new(context.clone(), svr_cfg));
        server_clients.insert(addr_str, client);
    }

    let make_service = make_service_fn(|socket: &AddrStream| {
        let client_addr = socket.remote_addr();
        let svr_cfg = servers.pick_server();
        let context = context.clone();

        // Keep connections for clients
        let addr_str = svr_cfg.addr().to_string();
        let client = server_clients.get(&addr_str).unwrap().clone();

        async move {
            Ok::<_, Infallible>(service_fn(move |req: Request<Body>| {
                server_dispatch(context.clone(), req, svr_cfg.clone(), client_addr, client.clone())
            }))
        }
    });

    let server = Server::bind(&local_addr).serve(make_service);

    let actual_local_addr = server.local_addr();

    info!("ShadowSocks HTTP Listening on {}", actual_local_addr);

    if let Err(err) = server.await {
        use std::io::{Error, ErrorKind};

        error!("Hyper Server error: {}", err);
        return Err(Error::new(ErrorKind::Other, err));
    }

    Ok(())
}
<commit_msg>Properly handles IPv6 host URI<commit_after>//! HTTP Proxy client server

use std::{
    collections::HashMap,
    convert::Infallible,
    future::Future,
    io,
    net::{IpAddr, SocketAddr},
    pin::Pin,
    sync::Arc,
    task::{self, Poll},
};

use futures::{
    future,
    future::{BoxFuture, Either},
    FutureExt,
};
use hyper::{
    client::connect::{Connected, Connection},
    server::conn::AddrStream,
    service::{make_service_fn, service_fn},
    upgrade::Upgraded,
    Body,
    Client,
    Method,
    Request,
    Response,
    Server,
    StatusCode,
    Uri,
};
use log::{debug, error, info, trace};
use pin_project::pin_project;
use tokio;
use tower;

use super::{CryptoStream, STcpStream};
use crate::{
    config::ServerConfig,
    context::SharedContext,
    relay::{
        loadbalancing::server::{ping, LoadBalancer, PingBalancer},
        socks5::Address,
    },
};

#[derive(Clone)]
struct ShadowSocksConnector {
    context: SharedContext,
    svr_cfg: Arc<ServerConfig>,
}

impl ShadowSocksConnector {
    fn new(context: SharedContext, svr_cfg: Arc<ServerConfig>) -> ShadowSocksConnector {
        ShadowSocksConnector { context, svr_cfg }
    }
}

impl tower::Service<Address> for ShadowSocksConnector {
    type Error = io::Error;
    type Future = ShadowSocksConnecting;
    type Response = CryptoStream<STcpStream>;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, addr: Address) -> Self::Future {
        let svr_cfg = self.svr_cfg.clone();
        let context = self.context.clone();

        ShadowSocksConnecting {
            fut: async move {
                let stream = super::connect_proxy_server(&*context, &*svr_cfg).await?;
                super::proxy_server_handshake(stream, svr_cfg.clone(), &addr).await
            }
            .boxed(),
        }
    }
}

impl tower::Service<Uri> for ShadowSocksConnector {
    type Error = io::Error;
    type Future = ShadowSocksConnecting;
    type Response = CryptoStream<STcpStream>;

    fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, dst: Uri) -> Self::Future {
        let svr_cfg = self.svr_cfg.clone();
        let context = self.context.clone();

        ShadowSocksConnecting {
            fut: async move {
                match host_addr(&dst) {
                    None => {
                        use std::io::{Error, ErrorKind};

                        error!("HTTP target URI must be a valid address, but found: {}", dst);

                        let err = Error::new(ErrorKind::Other, "URI must be a valid Address");
                        Err(err)
                    }
                    Some(addr) => {
                        let stream = super::connect_proxy_server(&*context, &*svr_cfg).await?;
                        super::proxy_server_handshake(stream, svr_cfg.clone(), &addr).await
                    }
                }
            }
            .boxed(),
        }
    }
}

#[pin_project]
struct ShadowSocksConnecting {
    #[pin]
    fut: BoxFuture<'static, io::Result<CryptoStream<STcpStream>>>,
}

impl Future for ShadowSocksConnecting {
    type Output = io::Result<CryptoStream<STcpStream>>;

    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        self.project().fut.poll(cx)
    }
}

fn host_addr(uri: &Uri) -> Option<Address> {
    match uri.authority() {
        None => None,
        Some(authority) => {
            // NOTE: Authority may include authentication info (user:password)
            // Although it is already deprecated, but some very old application may still depending on it
            //
            // But ... We won't be compatible with it. :)

            // Check if URI has port
            match authority.port_u16() {
                Some(port) => {
                    // Well, it has port!
                    // 1. Maybe authority is a SocketAddr (127.0.0.1:1234, [::1]:1234)
                    // 2. Otherwise, it must be a domain name (google.com:443)

                    match authority.as_str().parse::<SocketAddr>() {
                        Ok(saddr) => Some(Address::from(saddr)),
                        Err(..) => Some(Address::DomainNameAddress(authority.host().to_owned(), port)),
                    }
                }
                None => {
                    // Ok, we don't have port
                    // 1. IPv4 Address 127.0.0.1
                    // 2. IPv6 Address: https://tools.ietf.org/html/rfc2732 , [::1]
                    // 3. Domain name

                    // Uses default port
                    let port = match uri.scheme_str() {
                        None => 80, // Assume it is http
                        Some("http") => 80,
                        Some("https") => 443,
                        _ => return None, // Not supported
                    };

                    // RFC2732 indicates that IPv6 address should be wrapped in [ and ]
                    let authority_str = authority.as_str();
                    if authority_str.starts_with('[') && authority_str.ends_with(']') {
                        // Must be a IPv6 address
                        let addr = authority_str.trim_start_matches('[').trim_end_matches(']');
                        match addr.parse::<IpAddr>() {
                            Ok(a) => Some(Address::from(SocketAddr::new(a, port))),
                            // Ignore invalid IPv6 address
                            Err(..) => None,
                        }
                    } else {
                        // Maybe it is a IPv4 address, or a non-standard IPv6
                        match authority_str.parse::<IpAddr>() {
                            Ok(a) => Some(Address::from(SocketAddr::new(a, port))),
                            // Should be a domain name, or a invalid IP address.
                            // Let DNS deal with it.
                            Err(..) => Some(Address::DomainNameAddress(authority_str.to_owned(), port)),
                        }
                    }
                }
            }
        }
    }
}

impl Connection for CryptoStream<STcpStream> {
    fn connected(&self) -> Connected {
        Connected::new()
    }
}

async fn establish_connect_tunnel(
    upgraded: Upgraded,
    mut stream: CryptoStream<STcpStream>,
    svr_cfg: Arc<ServerConfig>,
    client_addr: SocketAddr,
    addr: Address,
) {
    use tokio::io::{copy, split};

    let (mut r, mut w) = split(upgraded);
    let (mut svr_r, mut svr_w) = stream.split();

    let rhalf = copy(&mut r, &mut svr_w);
    let whalf = copy(&mut svr_r, &mut w);

    debug!(
        "CONNECT relay established {} <-> {} ({})",
        client_addr,
        svr_cfg.addr(),
        addr
    );

    match future::select(rhalf, whalf).await {
        Either::Left((Ok(..), _)) => trace!("CONNECT relay {} -> {} ({}) closed", client_addr, svr_cfg.addr(), addr),
        Either::Left((Err(err), _)) => trace!(
            "CONNECT relay {} -> {} ({}) closed with error {:?}",
            client_addr,
            svr_cfg.addr(),
            addr,
            err,
        ),
        Either::Right((Ok(..), _)) => trace!("CONNECT relay {} <- {} ({}) closed", client_addr, svr_cfg.addr(), addr),
        Either::Right((Err(err), _)) => trace!(
            "CONNECT relay {} <- {} ({}) closed with error {:?}",
            client_addr,
            svr_cfg.addr(),
            addr,
            err,
        ),
    }

    debug!("CONNECT relay {} <-> {} ({}) closed", client_addr, svr_cfg.addr(), addr);
}

type ShadowSocksClient = Client<ShadowSocksConnector>;

async fn server_dispatch(
    context: SharedContext,
    req: Request<Body>,
    svr_cfg: Arc<ServerConfig>,
    client_addr: SocketAddr,
    client: ShadowSocksClient,
) -> Result<Response<Body>, io::Error> {
    // Parse URI
    //
    // Proxy request URI must contains a host
    let host = match host_addr(req.uri()) {
        None => {
            error!("HTTP {} URI is not a valid address. URI: {}", req.method(), req.uri());

            let mut resp = Response::new(Body::from("URI must be a valid Address"));
            *resp.status_mut() = StatusCode::BAD_REQUEST;

            return Ok(resp);
        }
        Some(h) => h,
    };

    if Method::CONNECT == req.method() {
        // Establish a TCP tunnel
        // https://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01

        debug!("HTTP CONNECT {}", host);

        // Connect to Shadowsocks' remote
        //
        // FIXME: What STATUS should I return for connection error?
        let stream = super::connect_proxy_server(&*context, &*svr_cfg).await?;
        let stream = super::proxy_server_handshake(stream, svr_cfg.clone(), &host).await?;

        debug!(
            "CONNECT relay connected {} <-> {} ({})",
            client_addr,
            svr_cfg.addr(),
            host
        );

        // Upgrade to a TCP tunnel
        //
        // Note: only after client received an empty body with STATUS_OK can the
        // connection be upgraded, so we can't return a response inside
        // `on_upgrade` future.
        tokio::spawn(async move {
            match req.into_body().on_upgrade().await {
                Ok(upgraded) => {
                    trace!(
                        "CONNECT tunnel upgrade success, {} <-> {} ({})",
                        client_addr,
                        svr_cfg.addr(),
                        host
                    );

                    establish_connect_tunnel(upgraded, stream, svr_cfg, client_addr, host).await
                }
                Err(e) => {
                    error!(
                        "Failed to upgrade TCP tunnel {} <-> {} ({}), error: {}",
                        client_addr,
                        svr_cfg.addr(),
                        host,
                        e
                    );
                }
            }
        });

        let resp = Response::builder()
            .header("Proxy-Agent", format!("ShadowSocks/{}", crate::VERSION))
            .body(Body::empty())
            .unwrap();

        Ok(resp)
    } else {
        let method = req.method().clone();

        debug!("HTTP {} {}", method, host);

        let res = match client.request(req).await {
            Ok(res) => res,
            Err(err) => {
                error!(
                    "HTTP {} {} <-> {} ({}) relay failed, error: {}",
                    method,
                    client_addr,
                    svr_cfg.addr(),
                    host,
                    err
                );

                let mut resp = Response::new(Body::from(format!("Relay failed to {}", host)));
                *resp.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;

                return Ok(resp);
            }
        };

        debug!(
            "HTTP {} relay {} <-> {} ({}) finished",
            method,
            client_addr,
            svr_cfg.addr(),
            host
        );

        Ok(res)
    }
}

/// Starts a TCP local server with HTTP proxy protocol
pub async fn run(context: SharedContext) -> io::Result<()> {
    let local_addr = *context.config().local.as_ref().expect("Missing local config");

    let mut servers = PingBalancer::new(context.clone(), ping::ServerType::Tcp).await;

    let mut server_clients = HashMap::new();

    // Create HTTP clients for each remote servers
    for svr_cfg in servers.servers() {
        let addr_str = svr_cfg.addr().to_string();
        let client = Client::builder().build::<_, Body>(ShadowSocksConnector::new(context.clone(), svr_cfg));
        server_clients.insert(addr_str, client);
    }

    let make_service = make_service_fn(|socket: &AddrStream| {
        let client_addr = socket.remote_addr();
        let svr_cfg = servers.pick_server();
        let context = context.clone();

        // Keep connections for clients
        let addr_str = svr_cfg.addr().to_string();
        let client = server_clients.get(&addr_str).unwrap().clone();

        async move {
            Ok::<_, Infallible>(service_fn(move |req: Request<Body>| {
                server_dispatch(context.clone(), req, svr_cfg.clone(), client_addr, client.clone())
            }))
        }
    });

    let server = Server::bind(&local_addr).serve(make_service);

    let actual_local_addr = server.local_addr();

    info!("ShadowSocks HTTP Listening on {}", actual_local_addr);

    if let Err(err) = server.await {
        use std::io::{Error, ErrorKind};

        error!("Hyper Server error: {}", err);
        return Err(Error::new(ErrorKind::Other, err));
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::collections::hash_map;

use render::Renderer;
use routing::{DagHandle, Edge, GraphWatcher, NodeData, NodeHandle};

type NodeMap = HashMap<NodeHandle, Node>;

#[derive(Default)]
pub struct RefRenderer {
    nodes: NodeMap,
}

struct Node {
    data: MyNodeData,
    inbound: HashSet<Edge>
}

enum MyNodeData {
    /// This node is a non-primitive effect.
    UserNode(NodeMap),
    /// This node is an instance of another DAG.
    Graph(DagHandle),
    /// Primitive Delay(samples) effect
    Delay(u64),
    /// Primitive Constant(value) effect.
    /// Also serves as a unit step;
    /// Returns the f32 value for t >= 0, else 0.
    Constant(f32),
    /// Primitive effect to multiply TWO input streams sample-wise.
    Multiply,
    /// This node is a DAG definition. i.e. it holds the output edges of a DAG.
    DagIO,
}

impl Renderer for RefRenderer {
    fn get_sample(&mut self, time: u64, ch: u8) -> f32 {
        // Try to find the edge that goes to -> (Null, slot=0, ch=ch)
        let root_handle = NodeHandle::toplevel();
        self.nodes.get(&root_handle).map(|node| {
            // find all edges to ([Null], slot=0, ch=ch)
            self.sum_input_to_slot(&self.nodes, node, time, 0, ch, &Vec::new())
        }).unwrap_or(0f32)
    }
}
impl RefRenderer {
    /// Get the value on an edge at a particular time
    /// When backtracking from the output, we push each Node onto the context if we enter inside of
    ///   it (i.e. if it's a nested DAG) & pop when exiting.
    fn get_value(&self, nodes: &NodeMap, edge: &Edge, time: u64, context: &Vec<(&NodeMap, NodeHandle)>) -> f32 {
        let from = edge.from_full();
        if *from.node_handle() == None {
            // Reading from one of the inputs to the top of `context`
            // TODO: we can avoid cloning by reversing the pop after recursing.
            let mut new_context = context.clone();
            let (new_nodes, head) = new_context.pop().unwrap();
            // Sum the inputs to the matching slot/ch
            self.sum_input_to_slot(new_nodes, &new_nodes[&head], time, edge.from_slot(), edge.from_ch(), &new_context)
        } else {
            // Reading from another node within the DAG
            let node = &nodes[&from];
            match node.data {
                MyNodeData::UserNode(ref new_nodes) => {
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    // Now find the *output* of the sub dag.
                    self.sum_input_to_slot(&new_nodes, new_nodes.get(&NodeHandle::toplevel()).unwrap(), time, edge.from_slot(), edge.from_ch(), &new_context)
                },
                // Output = sum of all edges to Null of the same slot & ch, within the given DAG.
                MyNodeData::Graph(ref dag_handle) => {
                    // TODO: we can avoid cloning by reversing the push after recursing.
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    let subdag = &nodes[&NodeHandle::new_dag(dag_handle.clone())];
                    self.sum_input_to_slot(nodes, &subdag, time, edge.from_slot(), edge.from_ch(), &new_context)
                }
                // Output = sum of all inputs to slot 0 of the same ch.
                MyNodeData::Delay(ref frames) => {
                    // The only nonzero output is slot=1.
                    if edge.from_slot() != 1 {
                        println!("Warning: attempt to read from Delay slot != 1");
                        0f32
                    } else {
                        // t<0 -> value is 0f32.
                        time.checked_sub(*frames).map(|origin_time| {
                            self.sum_input_to_slot(nodes, node, origin_time, 0, edge.from_ch(), context)
                        }).unwrap_or(0f32)
                    }
                },
                MyNodeData::Constant(ref value) => {
                    // The only nonzero output is slot=1.
                    if edge.from_slot() != 1 {
                        println!("Warning: attempt to read from Constant slot != 1");
                        0f32
                    } else {
                        *value
                    }
                },
                MyNodeData::Multiply => {
                    // The only nonzero output is slot=1.
                    if edge.from_slot() != 1 {
                        println!("Warning: attempt to read from Multiply slot != 1");
                        0f32
                    } else {
                        // Sum all inputs from slot=0 and slot=2 into two separate
                        // variables, then multiply them.
                        let val_a = self.sum_input_to_slot(nodes, node, time, 0, edge.from_ch(), context);
                        let val_b = self.sum_input_to_slot(nodes, node, time, 2, edge.from_ch(), context);
                        val_a * val_b
                    }
                },
                _ => panic!("Internal RefRenderer error: illegal node type"),
            }
        }
    }
    /// Return the sum of all inputs into a specific slot/channel of the given
    /// node at the given time.
    fn sum_input_to_slot(&self, nodes: &NodeMap, node: &Node, time: u64, slot: u32, ch: u8, context: &Vec<(&NodeMap, NodeHandle)>) -> f32 {
        let edges_in = node.inbound.iter().filter(|in_edge| {
            in_edge.to_slot() == slot && in_edge.to_ch() == ch
        });
        edges_in.map(|edge| self.get_value(nodes, edge, time, context)).sum()
    }

    fn make_node(&self, data: &NodeData) -> MyNodeData {
        match *data {
            NodeData::Graph(ref handle) => MyNodeData::Graph(handle.clone()),
            NodeData::Effect(ref effect) => {
                match effect.meta().get_primitive_url() {
                    Some(ref url) => {
                        let mut params: HashMap<_, _> = url.query_pairs().collect();
                        match url.path() {
                            "/Delay" => {
                                let frames: u64 = match params.entry(Cow::from("frames")) {
                                    hash_map::Entry::Occupied(e) => e.remove().parse().unwrap(),
                                    hash_map::Entry::Vacant(_) => 0u64,
                                };
                                // Make sure we consumed all arguments.
                                assert!(params.is_empty());
                                MyNodeData::Delay(frames)
                            },
                            "/Constant" => {
                                let value: f32 = match params.entry(Cow::from("value")) {
                                    hash_map::Entry::Occupied(e) => e.remove().parse().unwrap(),
                                    hash_map::Entry::Vacant(_) => 0f32,
                                };
                                // Make sure we consumed all arguments.
                                assert!(params.is_empty());
                                MyNodeData::Constant(value)
                            },
                            "/Multiply" => MyNodeData::Multiply,
                            _ => panic!("Unrecognized primitive effect: {} (full url: {})", url.path(), url),
                        }
                    }
                    None => {
                        let graph = effect.routegraph().as_ref().unwrap();
                        let mut nodes = HashMap::new();
                        for (node, data) in graph.iter_nodes() {
                            nodes.insert(node.clone(), Node::new(self.make_node(data)));
                        }
                        for edge in graph.iter_edges() {
                            nodes.entry(edge.to_full()).or_insert_with(|| {
                                Node::new(MyNodeData::DagIO)
                            }).inbound.insert(edge.clone());
                        }
                        MyNodeData::UserNode(nodes)
                    }
                }
            }
        }
    }
}

impl GraphWatcher for RefRenderer {
    fn on_add_node(&mut self, handle: &NodeHandle, data: &NodeData) {
        let my_node_data = self.make_node(data);
        self.nodes.insert(handle.clone(), Node::new(my_node_data));
        // If the node is part of a new DAG, allocate data so that future edges
        // to null within the DAG can be held.
        self.nodes.entry(NodeHandle::new_dag(handle.dag_handle().clone())).or_insert_with(|| {
            Node::new(MyNodeData::DagIO)
        });
    }
    fn on_del_node(&mut self, handle: &NodeHandle) {
        self.nodes.remove(handle);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.remove(edge);
    }
}

impl Node {
    fn new(data: MyNodeData) -> Self {
        Node {
            data: data,
            inbound: HashSet::new(),
        }
    }
}
<commit_msg>Handle the case where a user node has no outputs<commit_after>use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::collections::hash_map;

use render::Renderer;
use routing::{DagHandle, Edge, GraphWatcher, NodeData, NodeHandle};

type NodeMap = HashMap<NodeHandle, Node>;

#[derive(Default)]
pub struct RefRenderer {
    nodes: NodeMap,
}

struct Node {
    data: MyNodeData,
    inbound: HashSet<Edge>
}

enum MyNodeData {
    /// This node is a non-primitive effect.
    UserNode(NodeMap),
    /// This node is an instance of another DAG.
    Graph(DagHandle),
    /// Primitive Delay(samples) effect
    Delay(u64),
    /// Primitive Constant(value) effect.
    /// Also serves as a unit step;
    /// Returns the f32 value for t >= 0, else 0.
    Constant(f32),
    /// Primitive effect to multiply TWO input streams sample-wise.
    Multiply,
    /// This node is a DAG definition. i.e. it holds the output edges of a DAG.
    DagIO,
}

impl Renderer for RefRenderer {
    fn get_sample(&mut self, time: u64, ch: u8) -> f32 {
        // Try to find the edge that goes to -> (Null, slot=0, ch=ch)
        let root_handle = NodeHandle::toplevel();
        // empty graph is 0f32 = silence
        self.nodes.get(&root_handle).map(|node| {
            // find all edges to ([Null], slot=0, ch=ch)
            self.sum_input_to_slot(&self.nodes, node, time, 0, ch, &Vec::new())
        }).unwrap_or(0f32)
    }
}
impl RefRenderer {
    /// Get the value on an edge at a particular time
    /// When backtracking from the output, we push each Node onto the context if we enter inside of
    ///   it (i.e. if it's a nested DAG) & pop when exiting.
    fn get_value(&self, nodes: &NodeMap, edge: &Edge, time: u64, context: &Vec<(&NodeMap, NodeHandle)>) -> f32 {
        let from = edge.from_full();
        if *from.node_handle() == None {
            // Reading from one of the inputs to the top of `context`
            // TODO: we can avoid cloning by reversing the pop after recursing.
            let mut new_context = context.clone();
            let (new_nodes, head) = new_context.pop().unwrap();
            // Sum the inputs to the matching slot/ch
            self.sum_input_to_slot(new_nodes, &new_nodes[&head], time, edge.from_slot(), edge.from_ch(), &new_context)
        } else {
            // Reading from another node within the DAG
            let node = &nodes[&from];
            match node.data {
                MyNodeData::UserNode(ref new_nodes) => {
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    // Now find the *output* of the sub dag (or 0 if the sub dag has no outputs)
                    new_nodes.get(&NodeHandle::toplevel()).map(|root_node| {
                        self.sum_input_to_slot(&new_nodes, root_node, time, edge.from_slot(), edge.from_ch(), &new_context)
                    }).unwrap_or(0f32)
                },
                // Output = sum of all edges to Null of the same slot & ch, within the given DAG.
                MyNodeData::Graph(ref dag_handle) => {
                    // TODO: we can avoid cloning by reversing the push after recursing.
                    let mut new_context = context.clone();
                    new_context.push((nodes, from));
                    let subdag = &nodes[&NodeHandle::new_dag(dag_handle.clone())];
                    self.sum_input_to_slot(nodes, &subdag, time, edge.from_slot(), edge.from_ch(), &new_context)
                }
                // Output = sum of all inputs to slot 0 of the same ch.
                MyNodeData::Delay(ref frames) => {
                    // The only nonzero output is slot=1.
                    if edge.from_slot() != 1 {
                        println!("Warning: attempt to read from Delay slot != 1");
                        0f32
                    } else {
                        // t<0 -> value is 0f32.
                        time.checked_sub(*frames).map(|origin_time| {
                            self.sum_input_to_slot(nodes, node, origin_time, 0, edge.from_ch(), context)
                        }).unwrap_or(0f32)
                    }
                },
                MyNodeData::Constant(ref value) => {
                    // The only nonzero output is slot=1.
                    if edge.from_slot() != 1 {
                        println!("Warning: attempt to read from Constant slot != 1");
                        0f32
                    } else {
                        *value
                    }
                },
                MyNodeData::Multiply => {
                    // The only nonzero output is slot=1.
                    if edge.from_slot() != 1 {
                        println!("Warning: attempt to read from Multiply slot != 1");
                        0f32
                    } else {
                        // Sum all inputs from slot=0 and slot=2 into two separate
                        // variables, then multiply them.
                        let val_a = self.sum_input_to_slot(nodes, node, time, 0, edge.from_ch(), context);
                        let val_b = self.sum_input_to_slot(nodes, node, time, 2, edge.from_ch(), context);
                        val_a * val_b
                    }
                },
                _ => panic!("Internal RefRenderer error: illegal node type"),
            }
        }
    }
    /// Return the sum of all inputs into a specific slot/channel of the given
    /// node at the given time.
    fn sum_input_to_slot(&self, nodes: &NodeMap, node: &Node, time: u64, slot: u32, ch: u8, context: &Vec<(&NodeMap, NodeHandle)>) -> f32 {
        let edges_in = node.inbound.iter().filter(|in_edge| {
            in_edge.to_slot() == slot && in_edge.to_ch() == ch
        });
        edges_in.map(|edge| self.get_value(nodes, edge, time, context)).sum()
    }

    fn make_node(&self, data: &NodeData) -> MyNodeData {
        match *data {
            NodeData::Graph(ref handle) => MyNodeData::Graph(handle.clone()),
            NodeData::Effect(ref effect) => {
                match effect.meta().get_primitive_url() {
                    Some(ref url) => {
                        let mut params: HashMap<_, _> = url.query_pairs().collect();
                        match url.path() {
                            "/Delay" => {
                                let frames: u64 = match params.entry(Cow::from("frames")) {
                                    hash_map::Entry::Occupied(e) => e.remove().parse().unwrap(),
                                    hash_map::Entry::Vacant(_) => 0u64,
                                };
                                // Make sure we consumed all arguments.
                                assert!(params.is_empty());
                                MyNodeData::Delay(frames)
                            },
                            "/Constant" => {
                                let value: f32 = match params.entry(Cow::from("value")) {
                                    hash_map::Entry::Occupied(e) => e.remove().parse().unwrap(),
                                    hash_map::Entry::Vacant(_) => 0f32,
                                };
                                // Make sure we consumed all arguments.
                                assert!(params.is_empty());
                                MyNodeData::Constant(value)
                            },
                            "/Multiply" => MyNodeData::Multiply,
                            _ => panic!("Unrecognized primitive effect: {} (full url: {})", url.path(), url),
                        }
                    }
                    None => {
                        let graph = effect.routegraph().as_ref().unwrap();
                        let mut nodes = HashMap::new();
                        for (node, data) in graph.iter_nodes() {
                            nodes.insert(node.clone(), Node::new(self.make_node(data)));
                        }
                        for edge in graph.iter_edges() {
                            nodes.entry(edge.to_full()).or_insert_with(|| {
                                Node::new(MyNodeData::DagIO)
                            }).inbound.insert(edge.clone());
                        }
                        MyNodeData::UserNode(nodes)
                    }
                }
            }
        }
    }
}

impl GraphWatcher for RefRenderer {
    fn on_add_node(&mut self, handle: &NodeHandle, data: &NodeData) {
        let my_node_data = self.make_node(data);
        self.nodes.insert(handle.clone(), Node::new(my_node_data));
        // If the node is part of a new DAG, allocate data so that future edges
        // to null within the DAG can be held.
        self.nodes.entry(NodeHandle::new_dag(handle.dag_handle().clone())).or_insert_with(|| {
            Node::new(MyNodeData::DagIO)
        });
    }
    fn on_del_node(&mut self, handle: &NodeHandle) {
        self.nodes.remove(handle);
    }
    fn on_add_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.insert(edge.clone());
    }
    fn on_del_edge(&mut self, edge: &Edge) {
        self.nodes.get_mut(&edge.to_full()).unwrap().inbound.remove(edge);
    }
}

impl Node {
    fn new(data: MyNodeData) -> Self {
        Node {
            data: data,
            inbound: HashSet::new(),
        }
    }
}
<|endoftext|>


<commit_before>//! Wrapper types for the values returned from `File`s.
//!
//! The methods of `File` that return information about the entry on the
//! filesystem -- size, modification date, block count, or Git status -- used
//! to just return these as formatted strings, but this became inflexible once
//! customisable output styles landed.
//!
//! Instead, they will return a wrapper type from this module, which tags the
//! type with what field it is while containing the actual raw value.
//!
//! The `output::details` module, among others, uses these types to render and
//! display the information as formatted strings.

// C-style `blkcnt_t` types don’t follow Rust’s rules!
#![allow(non_camel_case_types)]
#![allow(clippy::struct_excessive_bools)]

/// The type of a file’s block count.
pub type blkcnt_t = u64;

/// The type of a file’s group ID.
pub type gid_t = u32;

/// The type of a file’s inode.
pub type ino_t = u64;

/// The type of a file’s number of links.
pub type nlink_t = u64;

/// The type of a file’s timestamp (creation, modification, access, etc).
pub type time_t = i64;

/// The type of a file’s user ID.
pub type uid_t = u32;

/// The file’s base type, which gets displayed in the very first column of the
/// details output.
///
/// This type is set entirely by the filesystem, rather than relying on a
/// file’s contents. So “link” is a type, but “image” is just a type of
/// regular file. (See the `filetype` module for those checks.)
///
/// Its ordering is used when sorting by type.
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub enum Type {
    Directory,
    File,
    Link,
    Pipe,
    Socket,
    CharDevice,
    BlockDevice,
    Special,
}

impl Type {
    pub fn is_regular_file(self) -> bool {
        matches!(self, Self::File)
    }
}

/// The file’s Unix permission bitfield, with one entry per bit.
#[derive(Copy, Clone)]
pub struct Permissions {
    pub user_read:      bool,
    pub user_write:     bool,
    pub user_execute:   bool,

    pub group_read:     bool,
    pub group_write:    bool,
    pub group_execute:  bool,

    pub other_read:     bool,
    pub other_write:    bool,
    pub other_execute:  bool,

    pub sticky:         bool,
    pub setgid:         bool,
    pub setuid:         bool,
}

/// The three pieces of information that are displayed as a single column in
/// the details view. These values are fused together to make the output a
/// little more compressed.
#[derive(Copy, Clone)]
pub struct PermissionsPlus {
    pub file_type:   Type,
    pub permissions: Permissions,
    pub xattrs:      bool,
}

/// The permissions encoded as octal values
#[derive(Copy, Clone)]
pub struct OctalPermissions {
    pub permissions: Permissions,
}

/// A file’s number of hard links on the filesystem.
///
/// Under Unix, a file can exist on the filesystem only once but appear in
/// multiple directories. However, it’s rare (but occasionally useful!) for a
/// regular file to have a link count greater than 1, so we highlight the
/// block count specifically for this case.
#[derive(Copy, Clone)]
pub struct Links {

    /// The actual link count.
    pub count: nlink_t,

    /// Whether this file is a regular file with more than one hard link.
    pub multiple: bool,
}

/// A file’s inode. Every directory entry on a Unix filesystem has an inode,
/// including directories and links, so this is applicable to everything exa
/// can deal with.
#[derive(Copy, Clone)]
pub struct Inode(pub ino_t);

/// The number of blocks that a file takes up on the filesystem, if any.
#[derive(Copy, Clone)]
pub enum Blocks {

    /// This file has the given number of blocks.
    Some(blkcnt_t),

    /// This file isn’t of a type that can take up blocks.
    None,
}

/// The ID of the user that owns a file. This will only ever be a number;
/// looking up the username is done in the `display` module.
#[derive(Copy, Clone)]
pub struct User(pub uid_t);

/// The ID of the group that a file belongs to.
#[derive(Copy, Clone)]
pub struct Group(pub gid_t);

/// A file’s size, in bytes. This is usually formatted by the `number_prefix`
/// crate into something human-readable.
#[derive(Copy, Clone)]
pub enum Size {

    /// This file has a defined size.
    Some(u64),

    /// This file has no size, or has a size but we aren’t interested in it.
    ///
    /// Under Unix, directory entries that aren’t regular files will still
    /// have a file size. For example, a directory will just contain a list of
    /// its files as its “contents” and will be specially flagged as being a
    /// directory, rather than a file. However, seeing the “file size” of this
    /// data is rarely useful — I can’t think of a time when I’ve seen it and
    /// learnt something. So we discard it and just output “-” instead.
    ///
    /// See this answer for more: <http://unix.stackexchange.com/a/68266>
    None,

    /// This file is a block or character device, so instead of a size, print
    /// out the file’s major and minor device IDs.
    ///
    /// This is what ls does as well. Without it, the devices will just have
    /// file sizes of zero.
    DeviceIDs(DeviceIDs),
}

/// The major and minor device IDs that gets displayed for device files.
///
/// You can see what these device numbers mean:
/// - <http://www.lanana.org/docs/device-list/>
/// - <http://www.lanana.org/docs/device-list/devices-2.6+.txt>
#[derive(Copy, Clone)]
pub struct DeviceIDs {
    pub major: u8,
    pub minor: u8,
}

/// One of a file’s timestamps (created, accessed, or modified).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time {
    pub seconds: time_t,
    pub nanoseconds: time_t,
}

/// A file’s status in a Git repository. Whether a file is in a repository or
/// not is handled by the Git module, rather than having a “null” variant in
/// this enum.
#[derive(PartialEq, Copy, Clone)]
pub enum GitStatus {

    /// This file hasn’t changed since the last commit.
    NotModified,

    /// This file didn’t exist for the last commit, and is not specified in
    /// the ignored files list.
    New,

    /// A file that’s been modified since the last commit.
    Modified,

    /// A deleted file. This can’t ever be shown, but it’s here anyway!
    Deleted,

    /// A file that Git has tracked a rename for.
    Renamed,

    /// A file that’s had its type (such as the file permissions) changed.
    TypeChange,

    /// A file that’s ignored (that matches a line in .gitignore)
    Ignored,

    /// A file that’s updated but unmerged.
    Conflicted,
}

/// A file’s complete Git status. It’s possible to make changes to a file, add
/// it to the staging area, then make *more* changes, so we need to list each
/// file’s status for both of these.
#[derive(Copy, Clone)]
pub struct Git {
    pub staged:   GitStatus,
    pub unstaged: GitStatus,
}

impl Default for Git {

    /// Create a Git status for a file with nothing done to it.
    fn default() -> Self {
        Self {
            staged: GitStatus::NotModified,
            unstaged: GitStatus::NotModified,
        }
    }
}
<commit_msg>Update fields.rs<commit_after>//! Wrapper types for the values returned from `File`s.
//!
//! The methods of `File` that return information about the entry on the
//! filesystem -- size, modification date, block count, or Git status -- used
//! to just return these as formatted strings, but this became inflexible once
//! customisable output styles landed.
//!
//! Instead, they will return a wrapper type from this module, which tags the
//! type with what field it is while containing the actual raw value.
//!
//! The `output::details` module, among others, uses these types to render and
//! display the information as formatted strings.

// C-style `blkcnt_t` types don’t follow Rust’s rules!
#![allow(non_camel_case_types)]
#![allow(clippy::struct_excessive_bools)]

/// The type of a file’s block count.
pub type blkcnt_t = u64;

/// The type of a file’s group ID.
pub type gid_t = u32;

/// The type of a file’s inode.
pub type ino_t = u64;

/// The type of a file’s number of links.
pub type nlink_t = u64;

/// The type of a file’s timestamp (creation, modification, access, etc).
pub type time_t = i64;

/// The type of a file’s user ID.
pub type uid_t = u32;

/// The file’s base type, which gets displayed in the very first column of the
/// details output.
///
/// This type is set entirely by the filesystem, rather than relying on a
/// file’s contents. So “link” is a type, but “image” is just a type of
/// regular file. (See the `filetype` module for those checks.)
///
/// Its ordering is used when sorting by type.
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub enum Type {
    Directory,
    File,
    Link,
    Pipe,
    Socket,
    CharDevice,
    BlockDevice,
    Special,
}

impl Type {
    pub fn is_regular_file(self) -> bool {
        matches!(self, Self::File)
    }
}

/// The file’s Unix permission bitfield, with one entry per bit.
#[derive(Copy, Clone)]
pub struct Permissions {
    pub user_read:      bool,
    pub user_write:     bool,
    pub user_execute:   bool,

    pub group_read:     bool,
    pub group_write:    bool,
    pub group_execute:  bool,

    pub other_read:     bool,
    pub other_write:    bool,
    pub other_execute:  bool,

    pub sticky:         bool,
    pub setgid:         bool,
    pub setuid:         bool,
}

/// The three pieces of information that are displayed as a single column in
/// the details view. These values are fused together to make the output a
/// little more compressed.
#[derive(Copy, Clone)]
pub struct PermissionsPlus {
    pub file_type:   Type,
    pub permissions: Permissions,
    pub xattrs:      bool,
}

/// The permissions encoded as octal values
#[derive(Copy, Clone)]
pub struct OctalPermissions {
    pub permissions: Permissions,
}

/// A file’s number of hard links on the filesystem.
///
/// Under Unix, a file can exist on the filesystem only once but appear in
/// multiple directories. However, it’s rare (but occasionally useful!) for a
/// regular file to have a link count greater than 1, so we highlight the
/// block count specifically for this case.
#[derive(Copy, Clone)]
pub struct Links {

    /// The actual link count.
    pub count: nlink_t,

    /// Whether this file is a regular file with more than one hard link.
    pub multiple: bool,
}

/// A file’s inode. Every directory entry on a Unix filesystem has an inode,
/// including directories and links, so this is applicable to everything exa
/// can deal with.
#[derive(Copy, Clone)]
pub struct Inode(pub ino_t);

/// The number of blocks that a file takes up on the filesystem, if any.
#[derive(Copy, Clone)]
pub enum Blocks {

    /// This file has the given number of blocks.
    Some(blkcnt_t),

    /// This file isn’t of a type that can take up blocks.
    None,
}

/// The ID of the user that owns a file. This will only ever be a number;
/// looking up the username is done in the `display` module.
#[derive(Copy, Clone)]
pub struct User(pub uid_t);

/// The ID of the group that a file belongs to.
#[derive(Copy, Clone)]
pub struct Group(pub gid_t);

/// A file’s size, in bytes. This is usually formatted by the `number_prefix`
/// crate into something human-readable.
#[derive(Copy, Clone)]
pub enum Size {

    /// This file has a defined size.
    Some(u64),

    /// This file has no size, or has a size but we aren’t interested in it.
    ///
    /// Under Unix, directory entries that aren’t regular files will still
    /// have a file size. For example, a directory will just contain a list of
    /// its files as its “contents” and will be specially flagged as being a
    /// directory, rather than a file. However, seeing the “file size” of this
    /// data is rarely useful — I can’t think of a time when I’ve seen it and
    /// learnt something. So we discard it and just output “-” instead.
    ///
    /// See this answer for more: <https://unix.stackexchange.com/a/68266>
    None,

    /// This file is a block or character device, so instead of a size, print
    /// out the file’s major and minor device IDs.
    ///
    /// This is what ls does as well. Without it, the devices will just have
    /// file sizes of zero.
    DeviceIDs(DeviceIDs),
}

/// The major and minor device IDs that gets displayed for device files.
///
/// You can see what these device numbers mean:
/// - <http://www.lanana.org/docs/device-list/>
/// - <http://www.lanana.org/docs/device-list/devices-2.6+.txt>
#[derive(Copy, Clone)]
pub struct DeviceIDs {
    pub major: u8,
    pub minor: u8,
}

/// One of a file’s timestamps (created, accessed, or modified).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time {
    pub seconds: time_t,
    pub nanoseconds: time_t,
}

/// A file’s status in a Git repository. Whether a file is in a repository or
/// not is handled by the Git module, rather than having a “null” variant in
/// this enum.
#[derive(PartialEq, Copy, Clone)]
pub enum GitStatus {

    /// This file hasn’t changed since the last commit.
    NotModified,

    /// This file didn’t exist for the last commit, and is not specified in
    /// the ignored files list.
    New,

    /// A file that’s been modified since the last commit.
    Modified,

    /// A deleted file. This can’t ever be shown, but it’s here anyway!
    Deleted,

    /// A file that Git has tracked a rename for.
    Renamed,

    /// A file that’s had its type (such as the file permissions) changed.
    TypeChange,

    /// A file that’s ignored (that matches a line in .gitignore)
    Ignored,

    /// A file that’s updated but unmerged.
    Conflicted,
}

/// A file’s complete Git status. It’s possible to make changes to a file, add
/// it to the staging area, then make *more* changes, so we need to list each
/// file’s status for both of these.
#[derive(Copy, Clone)]
pub struct Git {
    pub staged:   GitStatus,
    pub unstaged: GitStatus,
}

impl Default for Git {

    /// Create a Git status for a file with nothing done to it.
    fn default() -> Self {
        Self {
            staged: GitStatus::NotModified,
            unstaged: GitStatus::NotModified,
        }
    }
}
<|endoftext|>


<commit_before>//! HTTP Server
//!
//! A `Server` is created to listen on a port, parse HTTP requests, and hand
//! them off to a `Service`.
//!
//! There are two levels of APIs provide for constructing HTTP servers:
//!
//! - The higher-level [`Server`](Server) type.
//! - The lower-level [conn](conn) module.
//!
//! # Server
//!
//! The [`Server`](Server) is main way to start listening for HTTP requests.
//! It wraps a listener with a [`MakeService`](::service), and then should
//! be executed to start serving requests.
//!
//! [`Server`](Server) accepts connections in both HTTP1 and HTTP2 by default.
//!
//! ## Example
//!
//! ```no_run
//! extern crate hyper;
//!
//! use hyper::{Body, Response, Server};
//! use hyper::service::service_fn_ok;
//!
//! # #[cfg(feature = "runtime")]
//! fn main() {
//! # use hyper::rt::Future;
//!     // Construct our SocketAddr to listen on...
//!     let addr = ([127, 0, 0, 1], 3000).into();
//!
//!     // And a MakeService to handle each connection...
//!     let make_service = || {
//!         service_fn_ok(|_req| {
//!             Response::new(Body::from("Hello World"))
//!         })
//!     };
//!
//!     // Then bind and serve...
//!     let server = Server::bind(&addr)
//!         .serve(make_service);
//!
//!     // Finally, spawn `server` onto an Executor...
//!     hyper::rt::run(server.map_err(|e| {
//!         eprintln!("server error: {}", e);
//!     }));
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```

pub mod conn;
mod shutdown;
#[cfg(feature = "runtime")] mod tcp;

use std::fmt;
#[cfg(feature = "runtime")] use std::net::{SocketAddr, TcpListener as StdTcpListener};

#[cfg(feature = "runtime")] use std::time::Duration;

use futures::{Future, Stream, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
#[cfg(feature = "runtime")] use tokio_reactor;

use body::{Body, Payload};
use common::exec::{Exec, H2Exec, NewSvcExec};
use service::Service;
// Renamed `Http` as `Http_` for now so that people upgrading don't see an
// error that `hyper::server::Http` is private...
use self::conn::{Http as Http_, MakeServiceRef, NoopWatcher, SpawnAll};
use self::shutdown::{Graceful, GracefulWatcher};
#[cfg(feature = "runtime")] use self::tcp::AddrIncoming;

/// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default.
///
/// `Server` is a `Future` mapping a bound listener with a set of service
/// handlers. It is built using the [`Builder`](Builder), and the future
/// completes when the server has been shutdown. It should be run by an
/// `Executor`.
pub struct Server<I, S, E = Exec> {
    spawn_all: SpawnAll<I, S, E>,
}

/// A builder for a [`Server`](Server).
#[derive(Debug)]
pub struct Builder<I, E = Exec> {
    incoming: I,
    protocol: Http_<E>,
}

// ===== impl Server =====

impl<I> Server<I, ()> {
    /// Starts a [`Builder`](Builder) with the provided incoming stream.
    pub fn builder(incoming: I) -> Builder<I> {
        Builder {
            incoming,
            protocol: Http_::new(),
        }
    }
}

#[cfg(feature = "runtime")]
impl Server<AddrIncoming, ()> {
    /// Binds to the provided address, and returns a [`Builder`](Builder).
    ///
    /// # Panics
    ///
    /// This method will panic if binding to the address fails. For a method
    /// to bind to an address and return a `Result`, see `Server::try_bind`.
    pub fn bind(addr: &SocketAddr) -> Builder<AddrIncoming> {
        let incoming = AddrIncoming::new(addr, None)
            .unwrap_or_else(|e| {
                panic!("error binding to {}: {}", addr, e);
            });
        Server::builder(incoming)
    }

    /// Tries to bind to the provided address, and returns a [`Builder`](Builder).
    pub fn try_bind(addr: &SocketAddr) -> ::Result<Builder<AddrIncoming>> {
        AddrIncoming::new(addr, None)
            .map(Server::builder)
    }

    /// Create a new instance from a `std::net::TcpListener` instance.
    pub fn from_tcp(listener: StdTcpListener) -> Result<Builder<AddrIncoming>, ::Error> {
        let handle = tokio_reactor::Handle::current();
        AddrIncoming::from_std(listener, &handle)
            .map(Server::builder)
    }
}

#[cfg(feature = "runtime")]
impl<S> Server<AddrIncoming, S> {
    /// Returns the local address that this server is bound to.
    pub fn local_addr(&self) -> SocketAddr {
        self.spawn_all.local_addr()
    }
}

impl<I, S, E, B> Server<I, S, E>
where
    I: Stream,
    I::Error: Into<Box<::std::error::Error + Send + Sync>>,
    I::Item: AsyncRead + AsyncWrite + Send + 'static,
    S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    S::Service: 'static,
    B: Payload,
    E: H2Exec<<S::Service as Service>::Future, B>,
    E: NewSvcExec<I::Item, S::Future, S::Service, E, GracefulWatcher>,
{
    /// Prepares a server to handle graceful shutdown when the provided future
    /// completes.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate hyper;
    /// # extern crate futures;
    /// # use futures::Future;
    /// # fn main() {}
    /// # #[cfg(feature = "runtime")]
    /// # fn run() {
    /// # use hyper::{Body, Response, Server};
    /// # use hyper::service::service_fn_ok;
    /// # let new_service = || {
    /// #     service_fn_ok(|_req| {
    /// #         Response::new(Body::from("Hello World"))
    /// #     })
    /// # };
    ///
    /// // Make a server from the previous examples...
    /// let server = Server::bind(&([127, 0, 0, 1], 3000).into())
    ///     .serve(new_service);
    ///
    /// // Prepare some signal for when the server should start
    /// // shutting down...
    /// let (tx, rx) = futures::sync::oneshot::channel::<()>();
    ///
    /// let graceful = server
    ///     .with_graceful_shutdown(rx)
    ///     .map_err(|err| eprintln!("server error: {}", err));
    ///
    /// // Spawn `server` onto an Executor...
    /// hyper::rt::spawn(graceful);
    ///
    /// // And later, trigger the signal by calling `tx.send(())`.
    /// let _ = tx.send(());
    /// # }
    /// ```
    pub fn with_graceful_shutdown<F>(self, signal: F) -> Graceful<I, S, F, E>
    where
        F: Future<Item=()>
    {
        Graceful::new(self.spawn_all, signal)
    }
}

impl<I, S, B, E> Future for Server<I, S, E>
where
    I: Stream,
    I::Error: Into<Box<::std::error::Error + Send + Sync>>,
    I::Item: AsyncRead + AsyncWrite + Send + 'static,
    S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    S::Service: 'static,
    B: Payload,
    E: H2Exec<<S::Service as Service>::Future, B>,
    E: NewSvcExec<I::Item, S::Future, S::Service, E, NoopWatcher>,
{
    type Item = ();
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.spawn_all.poll_watch(&NoopWatcher)
    }
}

impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Server")
            .field("listener", &self.spawn_all.incoming_ref())
            .finish()
    }
}

// ===== impl Builder =====

impl<I, E> Builder<I, E> {
    /// Start a new builder, wrapping an incoming stream and low-level options.
    ///
    /// For a more convenient constructor, see [`Server::bind`](Server::bind).
    pub fn new(incoming: I, protocol: Http_<E>) -> Self {
        Builder {
            incoming,
            protocol,
        }
    }

    /// Sets whether to use keep-alive for HTTP/1 connections.
    ///
    /// Default is `true`.
    pub fn http1_keepalive(mut self, val: bool) -> Self {
        self.protocol.keep_alive(val);
        self
    }

    /// Set whether HTTP/1 connections should support half-closures.
    ///
    /// Clients can chose to shutdown their write-side while waiting
    /// for the server to respond. Setting this to `false` will
    /// automatically close any connection immediately if `read`
    /// detects an EOF.
    ///
    /// Default is `true`.
    pub fn http1_half_close(mut self, val: bool) -> Self {
        self.protocol.http1_half_close(val);
        self
    }

    /// Sets whether HTTP/1 is required.
    ///
    /// Default is `false`.
    pub fn http1_only(mut self, val: bool) -> Self {
        self.protocol.http1_only(val);
        self
    }

    // Sets whether to bunch up HTTP/1 writes until the read buffer is empty.
    //
    // This isn't really desirable in most cases, only really being useful in
    // silly pipeline benchmarks.
    #[doc(hidden)]
    pub fn http1_pipeline_flush(mut self, val: bool) -> Self {
        self.protocol.pipeline_flush(val);
        self
    }

    /// Set whether HTTP/1 connections should try to use vectored writes,
    /// or always flatten into a single buffer.
    ///
    /// # Note
    ///
    /// Setting this to `false` may mean more copies of body data,
    /// but may also improve performance when an IO transport doesn't
    /// support vectored writes well, such as most TLS implementations.
    ///
    /// Default is `true`.
    pub fn http1_writev(mut self, val: bool) -> Self {
        self.protocol.http1_writev(val);
        self
    }

    /// Sets whether HTTP/2 is required.
    ///
    /// Default is `false`.
    pub fn http2_only(mut self, val: bool) -> Self {
        self.protocol.http2_only(val);
        self
    }

    /// Sets the `Executor` to deal with connection tasks.
    ///
    /// Default is `tokio::spawn`.
    pub fn executor<E2>(self, executor: E2) -> Builder<I, E2> {
        Builder {
            incoming: self.incoming,
            protocol: self.protocol.with_executor(executor),
        }
    }

    /// Consume this `Builder`, creating a [`Server`](Server).
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate hyper;
    /// # fn main() {}
    /// # #[cfg(feature = "runtime")]
    /// # fn run() {
    /// use hyper::{Body, Response, Server};
    /// use hyper::service::service_fn_ok;
    ///
    /// // Construct our SocketAddr to listen on...
    /// let addr = ([127, 0, 0, 1], 3000).into();
    ///
    /// // And a NewService to handle each connection...
    /// let new_service = || {
    ///     service_fn_ok(|_req| {
    ///         Response::new(Body::from("Hello World"))
    ///     })
    /// };
    ///
    /// // Then bind and serve...
    /// let server = Server::bind(&addr)
    ///     .serve(new_service);
    ///
    /// // Finally, spawn `server` onto an Executor...
    /// # }
    /// ```
    pub fn serve<S, B>(self, new_service: S) -> Server<I, S, E>
    where
        I: Stream,
        I::Error: Into<Box<::std::error::Error + Send + Sync>>,
        I::Item: AsyncRead + AsyncWrite + Send + 'static,
        S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>,
        S::Error: Into<Box<::std::error::Error + Send + Sync>>,
        S::Service: 'static,
        B: Payload,
        E: NewSvcExec<I::Item, S::Future, S::Service, E, NoopWatcher>,
        E: H2Exec<<S::Service as Service>::Future, B>,
    {
        let serve = self.protocol.serve_incoming(self.incoming, new_service);
        let spawn_all = serve.spawn_all();
        Server {
            spawn_all,
        }
    }
}

#[cfg(feature = "runtime")]
impl<E> Builder<AddrIncoming, E> {
    /// Set whether TCP keepalive messages are enabled on accepted connections.
    ///
    /// If `None` is specified, keepalive is disabled, otherwise the duration
    /// specified will be the time to remain idle before sending TCP keepalive
    /// probes.
    pub fn tcp_keepalive(mut self, keepalive: Option<Duration>) -> Self {
        self.incoming.set_keepalive(keepalive);
        self
    }

    /// Set the value of `TCP_NODELAY` option for accepted connections.
    pub fn tcp_nodelay(mut self, enabled: bool) -> Self {
        self.incoming.set_nodelay(enabled);
        self
    }
}

<commit_msg>feat(server): add `tcp_sleep_on_accept_errors` builder method<commit_after>//! HTTP Server
//!
//! A `Server` is created to listen on a port, parse HTTP requests, and hand
//! them off to a `Service`.
//!
//! There are two levels of APIs provide for constructing HTTP servers:
//!
//! - The higher-level [`Server`](Server) type.
//! - The lower-level [conn](conn) module.
//!
//! # Server
//!
//! The [`Server`](Server) is main way to start listening for HTTP requests.
//! It wraps a listener with a [`MakeService`](::service), and then should
//! be executed to start serving requests.
//!
//! [`Server`](Server) accepts connections in both HTTP1 and HTTP2 by default.
//!
//! ## Example
//!
//! ```no_run
//! extern crate hyper;
//!
//! use hyper::{Body, Response, Server};
//! use hyper::service::service_fn_ok;
//!
//! # #[cfg(feature = "runtime")]
//! fn main() {
//! # use hyper::rt::Future;
//!     // Construct our SocketAddr to listen on...
//!     let addr = ([127, 0, 0, 1], 3000).into();
//!
//!     // And a MakeService to handle each connection...
//!     let make_service = || {
//!         service_fn_ok(|_req| {
//!             Response::new(Body::from("Hello World"))
//!         })
//!     };
//!
//!     // Then bind and serve...
//!     let server = Server::bind(&addr)
//!         .serve(make_service);
//!
//!     // Finally, spawn `server` onto an Executor...
//!     hyper::rt::run(server.map_err(|e| {
//!         eprintln!("server error: {}", e);
//!     }));
//! }
//! # #[cfg(not(feature = "runtime"))]
//! # fn main() {}
//! ```

pub mod conn;
mod shutdown;
#[cfg(feature = "runtime")] mod tcp;

use std::fmt;
#[cfg(feature = "runtime")] use std::net::{SocketAddr, TcpListener as StdTcpListener};

#[cfg(feature = "runtime")] use std::time::Duration;

use futures::{Future, Stream, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
#[cfg(feature = "runtime")] use tokio_reactor;

use body::{Body, Payload};
use common::exec::{Exec, H2Exec, NewSvcExec};
use service::Service;
// Renamed `Http` as `Http_` for now so that people upgrading don't see an
// error that `hyper::server::Http` is private...
use self::conn::{Http as Http_, MakeServiceRef, NoopWatcher, SpawnAll};
use self::shutdown::{Graceful, GracefulWatcher};
#[cfg(feature = "runtime")] use self::tcp::AddrIncoming;

/// A listening HTTP server that accepts connections in both HTTP1 and HTTP2 by default.
///
/// `Server` is a `Future` mapping a bound listener with a set of service
/// handlers. It is built using the [`Builder`](Builder), and the future
/// completes when the server has been shutdown. It should be run by an
/// `Executor`.
pub struct Server<I, S, E = Exec> {
    spawn_all: SpawnAll<I, S, E>,
}

/// A builder for a [`Server`](Server).
#[derive(Debug)]
pub struct Builder<I, E = Exec> {
    incoming: I,
    protocol: Http_<E>,
}

// ===== impl Server =====

impl<I> Server<I, ()> {
    /// Starts a [`Builder`](Builder) with the provided incoming stream.
    pub fn builder(incoming: I) -> Builder<I> {
        Builder {
            incoming,
            protocol: Http_::new(),
        }
    }
}

#[cfg(feature = "runtime")]
impl Server<AddrIncoming, ()> {
    /// Binds to the provided address, and returns a [`Builder`](Builder).
    ///
    /// # Panics
    ///
    /// This method will panic if binding to the address fails. For a method
    /// to bind to an address and return a `Result`, see `Server::try_bind`.
    pub fn bind(addr: &SocketAddr) -> Builder<AddrIncoming> {
        let incoming = AddrIncoming::new(addr, None)
            .unwrap_or_else(|e| {
                panic!("error binding to {}: {}", addr, e);
            });
        Server::builder(incoming)
    }

    /// Tries to bind to the provided address, and returns a [`Builder`](Builder).
    pub fn try_bind(addr: &SocketAddr) -> ::Result<Builder<AddrIncoming>> {
        AddrIncoming::new(addr, None)
            .map(Server::builder)
    }

    /// Create a new instance from a `std::net::TcpListener` instance.
    pub fn from_tcp(listener: StdTcpListener) -> Result<Builder<AddrIncoming>, ::Error> {
        let handle = tokio_reactor::Handle::current();
        AddrIncoming::from_std(listener, &handle)
            .map(Server::builder)
    }
}

#[cfg(feature = "runtime")]
impl<S> Server<AddrIncoming, S> {
    /// Returns the local address that this server is bound to.
    pub fn local_addr(&self) -> SocketAddr {
        self.spawn_all.local_addr()
    }
}

impl<I, S, E, B> Server<I, S, E>
where
    I: Stream,
    I::Error: Into<Box<::std::error::Error + Send + Sync>>,
    I::Item: AsyncRead + AsyncWrite + Send + 'static,
    S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    S::Service: 'static,
    B: Payload,
    E: H2Exec<<S::Service as Service>::Future, B>,
    E: NewSvcExec<I::Item, S::Future, S::Service, E, GracefulWatcher>,
{
    /// Prepares a server to handle graceful shutdown when the provided future
    /// completes.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate hyper;
    /// # extern crate futures;
    /// # use futures::Future;
    /// # fn main() {}
    /// # #[cfg(feature = "runtime")]
    /// # fn run() {
    /// # use hyper::{Body, Response, Server};
    /// # use hyper::service::service_fn_ok;
    /// # let new_service = || {
    /// #     service_fn_ok(|_req| {
    /// #         Response::new(Body::from("Hello World"))
    /// #     })
    /// # };
    ///
    /// // Make a server from the previous examples...
    /// let server = Server::bind(&([127, 0, 0, 1], 3000).into())
    ///     .serve(new_service);
    ///
    /// // Prepare some signal for when the server should start
    /// // shutting down...
    /// let (tx, rx) = futures::sync::oneshot::channel::<()>();
    ///
    /// let graceful = server
    ///     .with_graceful_shutdown(rx)
    ///     .map_err(|err| eprintln!("server error: {}", err));
    ///
    /// // Spawn `server` onto an Executor...
    /// hyper::rt::spawn(graceful);
    ///
    /// // And later, trigger the signal by calling `tx.send(())`.
    /// let _ = tx.send(());
    /// # }
    /// ```
    pub fn with_graceful_shutdown<F>(self, signal: F) -> Graceful<I, S, F, E>
    where
        F: Future<Item=()>
    {
        Graceful::new(self.spawn_all, signal)
    }
}

impl<I, S, B, E> Future for Server<I, S, E>
where
    I: Stream,
    I::Error: Into<Box<::std::error::Error + Send + Sync>>,
    I::Item: AsyncRead + AsyncWrite + Send + 'static,
    S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>,
    S::Error: Into<Box<::std::error::Error + Send + Sync>>,
    S::Service: 'static,
    B: Payload,
    E: H2Exec<<S::Service as Service>::Future, B>,
    E: NewSvcExec<I::Item, S::Future, S::Service, E, NoopWatcher>,
{
    type Item = ();
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.spawn_all.poll_watch(&NoopWatcher)
    }
}

impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Server")
            .field("listener", &self.spawn_all.incoming_ref())
            .finish()
    }
}

// ===== impl Builder =====

impl<I, E> Builder<I, E> {
    /// Start a new builder, wrapping an incoming stream and low-level options.
    ///
    /// For a more convenient constructor, see [`Server::bind`](Server::bind).
    pub fn new(incoming: I, protocol: Http_<E>) -> Self {
        Builder {
            incoming,
            protocol,
        }
    }

    /// Sets whether to use keep-alive for HTTP/1 connections.
    ///
    /// Default is `true`.
    pub fn http1_keepalive(mut self, val: bool) -> Self {
        self.protocol.keep_alive(val);
        self
    }

    /// Set whether HTTP/1 connections should support half-closures.
    ///
    /// Clients can chose to shutdown their write-side while waiting
    /// for the server to respond. Setting this to `false` will
    /// automatically close any connection immediately if `read`
    /// detects an EOF.
    ///
    /// Default is `true`.
    pub fn http1_half_close(mut self, val: bool) -> Self {
        self.protocol.http1_half_close(val);
        self
    }

    /// Sets whether HTTP/1 is required.
    ///
    /// Default is `false`.
    pub fn http1_only(mut self, val: bool) -> Self {
        self.protocol.http1_only(val);
        self
    }

    // Sets whether to bunch up HTTP/1 writes until the read buffer is empty.
    //
    // This isn't really desirable in most cases, only really being useful in
    // silly pipeline benchmarks.
    #[doc(hidden)]
    pub fn http1_pipeline_flush(mut self, val: bool) -> Self {
        self.protocol.pipeline_flush(val);
        self
    }

    /// Set whether HTTP/1 connections should try to use vectored writes,
    /// or always flatten into a single buffer.
    ///
    /// # Note
    ///
    /// Setting this to `false` may mean more copies of body data,
    /// but may also improve performance when an IO transport doesn't
    /// support vectored writes well, such as most TLS implementations.
    ///
    /// Default is `true`.
    pub fn http1_writev(mut self, val: bool) -> Self {
        self.protocol.http1_writev(val);
        self
    }

    /// Sets whether HTTP/2 is required.
    ///
    /// Default is `false`.
    pub fn http2_only(mut self, val: bool) -> Self {
        self.protocol.http2_only(val);
        self
    }

    /// Sets the `Executor` to deal with connection tasks.
    ///
    /// Default is `tokio::spawn`.
    pub fn executor<E2>(self, executor: E2) -> Builder<I, E2> {
        Builder {
            incoming: self.incoming,
            protocol: self.protocol.with_executor(executor),
        }
    }

    /// Consume this `Builder`, creating a [`Server`](Server).
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate hyper;
    /// # fn main() {}
    /// # #[cfg(feature = "runtime")]
    /// # fn run() {
    /// use hyper::{Body, Response, Server};
    /// use hyper::service::service_fn_ok;
    ///
    /// // Construct our SocketAddr to listen on...
    /// let addr = ([127, 0, 0, 1], 3000).into();
    ///
    /// // And a NewService to handle each connection...
    /// let new_service = || {
    ///     service_fn_ok(|_req| {
    ///         Response::new(Body::from("Hello World"))
    ///     })
    /// };
    ///
    /// // Then bind and serve...
    /// let server = Server::bind(&addr)
    ///     .serve(new_service);
    ///
    /// // Finally, spawn `server` onto an Executor...
    /// # }
    /// ```
    pub fn serve<S, B>(self, new_service: S) -> Server<I, S, E>
    where
        I: Stream,
        I::Error: Into<Box<::std::error::Error + Send + Sync>>,
        I::Item: AsyncRead + AsyncWrite + Send + 'static,
        S: MakeServiceRef<I::Item, ReqBody=Body, ResBody=B>,
        S::Error: Into<Box<::std::error::Error + Send + Sync>>,
        S::Service: 'static,
        B: Payload,
        E: NewSvcExec<I::Item, S::Future, S::Service, E, NoopWatcher>,
        E: H2Exec<<S::Service as Service>::Future, B>,
    {
        let serve = self.protocol.serve_incoming(self.incoming, new_service);
        let spawn_all = serve.spawn_all();
        Server {
            spawn_all,
        }
    }
}

#[cfg(feature = "runtime")]
impl<E> Builder<AddrIncoming, E> {
    /// Set whether TCP keepalive messages are enabled on accepted connections.
    ///
    /// If `None` is specified, keepalive is disabled, otherwise the duration
    /// specified will be the time to remain idle before sending TCP keepalive
    /// probes.
    pub fn tcp_keepalive(mut self, keepalive: Option<Duration>) -> Self {
        self.incoming.set_keepalive(keepalive);
        self
    }

    /// Set the value of `TCP_NODELAY` option for accepted connections.
    pub fn tcp_nodelay(mut self, enabled: bool) -> Self {
        self.incoming.set_nodelay(enabled);
        self
    }

    /// Set whether to sleep on accept errors.
    ///
    /// A possible scenario is that the process has hit the max open files
    /// allowed, and so trying to accept a new connection will fail with
    /// EMFILE. In some cases, it's preferable to just wait for some time, if
    /// the application will likely close some files (or connections), and try
    /// to accept the connection again. If this option is true, the error will
    /// be logged at the error level, since it is still a big deal, and then
    /// the listener will sleep for 1 second.
    ///
    /// In other cases, hitting the max open files should be treat similarly
    /// to being out-of-memory, and simply error (and shutdown). Setting this
    /// option to false will allow that.
    ///
    /// For more details see [`AddrIncoming::set_sleep_on_errors`]
    pub fn tcp_sleep_on_accept_errors(mut self, val: bool) -> Self {
        self.incoming.set_sleep_on_errors(val);
        self
    }
}

<|endoftext|>


<commit_before>use std::cell::Cell;
use std::rc::Rc;

use piston_window::*;

use game::config::{Config, ConfigBuilder};
use game::factory::TetrominoFactory;
use game::grid::Grid;
use game::tetromino::{Direction, MoveResult, Rotation, RotationResult, Tetromino};
use game::timer::{Timer, TimerTickResult};
use game::window::GameWindow;

pub struct Game {
    time: Rc<Cell<f64>>,
    config: Config,
    grid: Grid,
    block_drop_timer: Timer,
    tetromino: Tetromino,
    tetromino_factory: TetrominoFactory,
}

impl Game {
    pub fn new() -> Game {
        let time = RcCell!(0.0);
        let factory = TetrominoFactory::new();
        let config = ConfigBuilder::new()
            .grid_size((10, 22))
            .grid_offset(10.0)
            .tile_size(29.0)
            .build();

        let tetromino = factory.create(&config);

        Game {
            time: time.clone(),
            config: config,
            grid: Grid::new(),
            block_drop_timer: Timer::new(0.5, time.clone()),
            tetromino: tetromino,
            tetromino_factory: factory,
        }
    }

    pub fn process(&mut self, e: &Event) -> bool {
        match *e {
            Event::Update(update) => {
                // Update the globa game time
                self.update_time(update.dt);

                // Drop the current block if it needs dropping
                self.drop_current_block(None);

                // Apply the currently active tetromino into the grid
                self.grid.apply_tetromino(&self.tetromino);
            }
            Event::Input(ref input_event) => {
                self.handle_input(input_event);
            }
            _ => (),
        }

        true
    }

    /// Increments the global time
    fn update_time(&mut self, delta: f64) {
        self.time.set(self.time.get() + delta);
    }

    fn drop_current_block<O>(&mut self, force_drop: O)
        where O: Into<Option<bool>>
    {
        // If we can drop, check if we are ready and drop the active tetromino
        match self.tetromino.can_move(Direction::South, &self.grid.boxes) {
            MoveResult::Allow => {
                if self.block_drop_timer.elapsed() || force_drop.into().is_some() {
                    self.tetromino.drop_down();
                    self.block_drop_timer.reset();
                }
            }
            MoveResult::Blocked => {
                // Otherwise, store the tetromino in the grid and create a new tetromino
                self.new_tetromino();
            }
            _ => (),
        }
    }

    fn new_tetromino(&mut self) {
        self.grid.store_tetromino(&self.tetromino);
        self.tetromino = self.tetromino_factory.create(&self.config);
        self.block_drop_timer.reset();
    }

    fn handle_input(&mut self, input: &Input) {
        if let Input::Press(ref button) = *input {
            match *button {
                Button::Keyboard(Key::Z) => {
                    match self.tetromino.can_rotate(Rotation::CounterClockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::CounterClockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::X) => {
                    match self.tetromino.can_rotate(Rotation::Clockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::Clockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Left) => {
                    match self.tetromino.can_move(Direction::West, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_left(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Right) => {
                    match self.tetromino.can_move(Direction::East, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_right(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Down) => {
                    self.drop_current_block(true);
                }
                _ => (),
            }
        }
    }

    pub fn render(&self, window: &mut GameWindow, e: &Event) {
        window.draw_2d(e, |c, g| {
            clear([1.0, 1.0, 1.0, 1.0], g);

            self.grid.render(&self.config, c, g, &e);
        });
    }
}
<commit_msg>Renamed block_drop_timer to drop_timer<commit_after>use std::cell::Cell;
use std::rc::Rc;

use piston_window::*;

use game::config::{Config, ConfigBuilder};
use game::factory::TetrominoFactory;
use game::grid::Grid;
use game::tetromino::{Direction, MoveResult, Rotation, RotationResult, Tetromino};
use game::timer::{Timer, TimerTickResult};
use game::window::GameWindow;

pub struct Game {
    time: Rc<Cell<f64>>,
    config: Config,
    grid: Grid,
    drop_timer: Timer,
    tetromino: Tetromino,
    tetromino_factory: TetrominoFactory,
}

impl Game {
    pub fn new() -> Game {
        let time = RcCell!(0.0);
        let factory = TetrominoFactory::new();
        let config = ConfigBuilder::new()
            .grid_size((10, 22))
            .grid_offset(10.0)
            .tile_size(29.0)
            .build();

        let tetromino = factory.create(&config);

        Game {
            time: time.clone(),
            config: config,
            grid: Grid::new(),
            drop_timer: Timer::new(0.5, time.clone()),
            tetromino: tetromino,
            tetromino_factory: factory,
        }
    }

    pub fn process(&mut self, e: &Event) -> bool {
        match *e {
            Event::Update(update) => {
                // Update the globa game time
                self.update_time(update.dt);

                // Drop the current block if it needs dropping
                self.drop_current_block(None);

                // Apply the currently active tetromino into the grid
                self.grid.apply_tetromino(&self.tetromino);
            }
            Event::Input(ref input_event) => {
                self.handle_input(input_event);
            }
            _ => (),
        }

        true
    }

    /// Increments the global time
    fn update_time(&mut self, delta: f64) {
        self.time.set(self.time.get() + delta);
    }

    fn drop_current_block<O>(&mut self, force_drop: O)
        where O: Into<Option<bool>>
    {
        // If we can drop, check if we are ready and drop the active tetromino
        match self.tetromino.can_move(Direction::South, &self.grid.boxes) {
            MoveResult::Allow => {
                if self.drop_timer.elapsed() || force_drop.into().is_some() {
                    self.tetromino.drop_down();
                    self.drop_timer.reset();
                }
            }
            MoveResult::Blocked => {
                // Otherwise, store the tetromino in the grid and create a new tetromino
                self.new_tetromino();
            }
            _ => (),
        }
    }

    fn new_tetromino(&mut self) {
        self.grid.store_tetromino(&self.tetromino);
        self.tetromino = self.tetromino_factory.create(&self.config);
        self.drop_timer.reset();
    }

    fn handle_input(&mut self, input: &Input) {
        if let Input::Press(ref button) = *input {
            match *button {
                Button::Keyboard(Key::Z) => {
                    match self.tetromino.can_rotate(Rotation::CounterClockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::CounterClockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::X) => {
                    match self.tetromino.can_rotate(Rotation::Clockwise, &self.grid.boxes) {
                        RotationResult::Allow => self.tetromino.rotate(Rotation::Clockwise),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Left) => {
                    match self.tetromino.can_move(Direction::West, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_left(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Right) => {
                    match self.tetromino.can_move(Direction::East, &self.grid.boxes) {
                        MoveResult::Allow => self.tetromino.move_right(),
                        MoveResult::Blocked => self.new_tetromino(),
                        _ => (),
                    }
                }
                Button::Keyboard(Key::Down) => {
                    self.drop_current_block(true);
                }
                _ => (),
            }
        }
    }

    pub fn render(&self, window: &mut GameWindow, e: &Event) {
        window.draw_2d(e, |c, g| {
            clear([1.0, 1.0, 1.0, 1.0], g);

            self.grid.render(&self.config, c, g, &e);
        });
    }
}
<|endoftext|>