<commit_before>// Copyright (c) 2016 The Rouille developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Apply content encodings (such as gzip compression) to the response.
//!
//! This module provides access to the content encodings supported by a request as well as
//! a function to automatically apply common content encodings to a response.
//! # Basic example
//!
//! Here is a basic example showing how to use content encodings:
//!
//! ```
//! use rouille::Request;
//! use rouille::Response;
//! use rouille::content_encoding;
//!
//! fn handle_request(request: &Request) -> Response {
//!     let text = String::new();
//!     for encoding in content_encoding::accepted_content_encodings(request) {
//!         text.push_str(encoding);
//!         text.push('\n');
//!     }
//!     let response = Response::text(&text);
//!     content_encoding::apply(response)
//! }
//! ```
use std::str;
use Request;
use Response;

/// Applies content encoding to the response.
///
/// Analyzes the `Accept-Encoding` header of the request. If one of the encodings is recognized and
/// supported by rouille, it adds a `Content-Encoding` header to the `Response` and encodes its
/// body.
///
/// If the response already has a `Content-Encoding` header, this function is a no-op.
/// If the response has a `Content-Type` header that isn't textual content, this function is a
/// no-op.
///
/// The gzip encoding is supported only if you enable the `gzip` feature of rouille (which is
/// enabled by default).
///
/// # Example
///
/// ```rust
/// use rouille::content_encoding;
/// use rouille::Request;
/// use rouille::Response;
///
/// fn handle(request: &Request) -> Response {
///     content_encoding::apply(request, Response::text("hello world"))
/// }
/// ```
pub fn apply(request: &Request, response: Response) -> Response {
    // Only text should be encoded. Otherwise just return.
    if !response_is_text(&response) {
        return response;
    }

    // If any of the response's headers is equal to `Content-Encoding`, ignore the function
    // call and return immediately.
    if response
        .headers
        .iter()
        .any(|&(ref key, _)| key.eq_ignore_ascii_case("Content-Encoding"))
    {
        return response;
    }

    // Put the response in an Option for later.
    let mut response = Some(response);

    // Now let's get the list of content encodings accepted by the request.
    // The list should be ordered from the most desired to the list desired.
    // TODO: use input::priority_header_preferred instead
    for encoding in accepted_content_encodings(request) {
        // Try the brotli encoding.
        if brotli(encoding, &mut response) {
            return response.take().unwrap();
        }

        // Try the gzip encoding.
        if gzip(encoding, &mut response) {
            return response.take().unwrap();
        }

        // The identity encoding is always supported.
        if encoding.eq_ignore_ascii_case("identity") {
            return response.take().unwrap();
        }
    }

    // No encoding accepted, don't do anything.
    response.take().unwrap()
}

// Returns true if the Content-Type of the response is a type that should be encoded.
// Since encoding is purely an optimisation, it's not a problem if the function sometimes has
// false positives or false negatives.
fn response_is_text(response: &Response) -> bool {
    response.headers.iter().any(|&(ref key, ref value)| {
        if !key.eq_ignore_ascii_case("Content-Type") {
            return false;
        }

        // TODO: perform case-insensitive comparison
        value.starts_with("text/")
            || value.contains("javascript")
            || value.contains("json")
            || value.contains("xml")
            || value.contains("font")
    })
}

/// Returns an iterator of the list of content encodings accepted by the request.
///
/// # Example
///
/// ```
/// use rouille::{Request, Response};
/// use rouille::content_encoding;
///
/// fn handle(request: &Request) -> Response {
///     for encoding in content_encoding::accepted_content_encodings(request) {
///         // ...
///     }
///
///     // ...
/// # panic!()
/// }
/// ```
pub fn accepted_content_encodings(request: &Request) -> AcceptedContentEncodingsIter {
    let elems = request.header("Accept-Encoding").unwrap_or("").split(',');
    AcceptedContentEncodingsIter { elements: elems }
}

/// Iterator to the list of content encodings accepted by a request.
pub struct AcceptedContentEncodingsIter<'a> {
    elements: str::Split<'a, char>,
}

impl<'a> Iterator for AcceptedContentEncodingsIter<'a> {
    type Item = &'a str;

    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        loop {
            match self.elements.next() {
                None => return None,
                Some(e) => {
                    let e = e.trim();
                    if !e.is_empty() {
                        return Some(e);
                    }
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, max) = self.elements.size_hint();
        (0, max)
    }
}

#[cfg(feature = "gzip")]
fn gzip(e: &str, response: &mut Option<Response>) -> bool {
    use deflate::deflate_bytes_gzip;
    use std::io;
    use std::mem;
    use ResponseBody;

    if !e.eq_ignore_ascii_case("gzip") {
        return false;
    }

    let response = response.as_mut().unwrap();
    response
        .headers
        .push(("Content-Encoding".into(), "gzip".into()));
    let previous_body = mem::replace(&mut response.data, ResponseBody::empty());
    let (mut raw_data, size) = previous_body.into_reader_and_size();
    let mut src = match size {
        Some(size) => Vec::with_capacity(size),
        None => Vec::new(),
    };
    io::copy(&mut raw_data, &mut src).expect("Failed reading response body while gzipping");
    let zipped = deflate_bytes_gzip(&src);
    response.data = ResponseBody::from_data(zipped);
    true
}

#[cfg(not(feature = "gzip"))]
#[inline]
fn gzip(e: &str, response: &mut Option<Response>) -> bool {
    false
}

#[cfg(feature = "brotli")]
fn brotli(e: &str, response: &mut Option<Response>) -> bool {
    use brotli2::read::BrotliEncoder;
    use std::mem;
    use ResponseBody;

    if !e.eq_ignore_ascii_case("br") {
        return false;
    }

    let response = response.as_mut().unwrap();
    response
        .headers
        .push(("Content-Encoding".into(), "br".into()));
    let previous_body = mem::replace(&mut response.data, ResponseBody::empty());
    let (raw_data, _) = previous_body.into_reader_and_size();
    response.data = ResponseBody::from_reader(BrotliEncoder::new(raw_data, 6));
    true
}

#[cfg(not(feature = "brotli"))]
#[inline]
fn brotli(e: &str, response: &mut Option<Response>) -> bool {
    false
}

#[cfg(test)]
mod tests {
    use content_encoding;
    use Request;

    #[test]
    fn no_req_encodings() {
        let request = Request::fake_http("GET", "/", vec![], vec![]);
        assert_eq!(
            content_encoding::accepted_content_encodings(&request).count(),
            0
        );
    }

    #[test]
    fn empty_req_encodings() {
        let request = {
            let h = vec![("Accept-Encoding".to_owned(), "".to_owned())];
            Request::fake_http("GET", "/", h, vec![])
        };

        assert_eq!(
            content_encoding::accepted_content_encodings(&request).count(),
            0
        );
    }

    #[test]
    fn one_req_encoding() {
        let request = {
            let h = vec![("Accept-Encoding".to_owned(), "foo".to_owned())];
            Request::fake_http("GET", "/", h, vec![])
        };

        let mut list = content_encoding::accepted_content_encodings(&request);
        assert_eq!(list.next().unwrap(), "foo");
        assert_eq!(list.next(), None);
    }

    #[test]
    fn multi_req_encoding() {
        let request = {
            let h = vec![("Accept-Encoding".to_owned(), "foo, bar".to_owned())];
            Request::fake_http("GET", "/", h, vec![])
        };

        let mut list = content_encoding::accepted_content_encodings(&request);
        assert_eq!(list.next().unwrap(), "foo");
        assert_eq!(list.next().unwrap(), "bar");
        assert_eq!(list.next(), None);
    }

    // TODO: more tests for encoding stuff
}
<commit_msg>Fix a broken content_encoding doc-test<commit_after>// Copyright (c) 2016 The Rouille developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Apply content encodings (such as gzip compression) to the response.
//!
//! This module provides access to the content encodings supported by a request as well as
//! a function to automatically apply common content encodings to a response.
//! # Basic example
//!
//! Here is a basic example showing how to use content encodings:
//!
//! ```
//! use rouille::Request;
//! use rouille::Response;
//! use rouille::content_encoding;
//!
//! fn handle_request(request: &Request) -> Response {
//!     let mut text = String::new();
//!     for encoding in content_encoding::accepted_content_encodings(request) {
//!         text.push_str(encoding);
//!         text.push('\n');
//!     }
//!     let response = Response::text(&text);
//!     content_encoding::apply(&request, response)
//! }
//! ```
use std::str;
use Request;
use Response;

/// Applies content encoding to the response.
///
/// Analyzes the `Accept-Encoding` header of the request. If one of the encodings is recognized and
/// supported by rouille, it adds a `Content-Encoding` header to the `Response` and encodes its
/// body.
///
/// If the response already has a `Content-Encoding` header, this function is a no-op.
/// If the response has a `Content-Type` header that isn't textual content, this function is a
/// no-op.
///
/// The gzip encoding is supported only if you enable the `gzip` feature of rouille (which is
/// enabled by default).
///
/// # Example
///
/// ```rust
/// use rouille::content_encoding;
/// use rouille::Request;
/// use rouille::Response;
///
/// fn handle(request: &Request) -> Response {
///     content_encoding::apply(request, Response::text("hello world"))
/// }
/// ```
pub fn apply(request: &Request, response: Response) -> Response {
    // Only text should be encoded. Otherwise just return.
    if !response_is_text(&response) {
        return response;
    }

    // If any of the response's headers is equal to `Content-Encoding`, ignore the function
    // call and return immediately.
    if response
        .headers
        .iter()
        .any(|&(ref key, _)| key.eq_ignore_ascii_case("Content-Encoding"))
    {
        return response;
    }

    // Put the response in an Option for later.
    let mut response = Some(response);

    // Now let's get the list of content encodings accepted by the request.
    // The list should be ordered from the most desired to the list desired.
    // TODO: use input::priority_header_preferred instead
    for encoding in accepted_content_encodings(request) {
        // Try the brotli encoding.
        if brotli(encoding, &mut response) {
            return response.take().unwrap();
        }

        // Try the gzip encoding.
        if gzip(encoding, &mut response) {
            return response.take().unwrap();
        }

        // The identity encoding is always supported.
        if encoding.eq_ignore_ascii_case("identity") {
            return response.take().unwrap();
        }
    }

    // No encoding accepted, don't do anything.
    response.take().unwrap()
}

// Returns true if the Content-Type of the response is a type that should be encoded.
// Since encoding is purely an optimisation, it's not a problem if the function sometimes has
// false positives or false negatives.
fn response_is_text(response: &Response) -> bool {
    response.headers.iter().any(|&(ref key, ref value)| {
        if !key.eq_ignore_ascii_case("Content-Type") {
            return false;
        }

        // TODO: perform case-insensitive comparison
        value.starts_with("text/")
            || value.contains("javascript")
            || value.contains("json")
            || value.contains("xml")
            || value.contains("font")
    })
}

/// Returns an iterator of the list of content encodings accepted by the request.
///
/// # Example
///
/// ```
/// use rouille::{Request, Response};
/// use rouille::content_encoding;
///
/// fn handle(request: &Request) -> Response {
///     for encoding in content_encoding::accepted_content_encodings(request) {
///         // ...
///     }
///
///     // ...
/// # panic!()
/// }
/// ```
pub fn accepted_content_encodings(request: &Request) -> AcceptedContentEncodingsIter {
    let elems = request.header("Accept-Encoding").unwrap_or("").split(',');
    AcceptedContentEncodingsIter { elements: elems }
}

/// Iterator to the list of content encodings accepted by a request.
pub struct AcceptedContentEncodingsIter<'a> {
    elements: str::Split<'a, char>,
}

impl<'a> Iterator for AcceptedContentEncodingsIter<'a> {
    type Item = &'a str;

    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        loop {
            match self.elements.next() {
                None => return None,
                Some(e) => {
                    let e = e.trim();
                    if !e.is_empty() {
                        return Some(e);
                    }
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, max) = self.elements.size_hint();
        (0, max)
    }
}

#[cfg(feature = "gzip")]
fn gzip(e: &str, response: &mut Option<Response>) -> bool {
    use deflate::deflate_bytes_gzip;
    use std::io;
    use std::mem;
    use ResponseBody;

    if !e.eq_ignore_ascii_case("gzip") {
        return false;
    }

    let response = response.as_mut().unwrap();
    response
        .headers
        .push(("Content-Encoding".into(), "gzip".into()));
    let previous_body = mem::replace(&mut response.data, ResponseBody::empty());
    let (mut raw_data, size) = previous_body.into_reader_and_size();
    let mut src = match size {
        Some(size) => Vec::with_capacity(size),
        None => Vec::new(),
    };
    io::copy(&mut raw_data, &mut src).expect("Failed reading response body while gzipping");
    let zipped = deflate_bytes_gzip(&src);
    response.data = ResponseBody::from_data(zipped);
    true
}

#[cfg(not(feature = "gzip"))]
#[inline]
fn gzip(e: &str, response: &mut Option<Response>) -> bool {
    false
}

#[cfg(feature = "brotli")]
fn brotli(e: &str, response: &mut Option<Response>) -> bool {
    use brotli2::read::BrotliEncoder;
    use std::mem;
    use ResponseBody;

    if !e.eq_ignore_ascii_case("br") {
        return false;
    }

    let response = response.as_mut().unwrap();
    response
        .headers
        .push(("Content-Encoding".into(), "br".into()));
    let previous_body = mem::replace(&mut response.data, ResponseBody::empty());
    let (raw_data, _) = previous_body.into_reader_and_size();
    response.data = ResponseBody::from_reader(BrotliEncoder::new(raw_data, 6));
    true
}

#[cfg(not(feature = "brotli"))]
#[inline]
fn brotli(e: &str, response: &mut Option<Response>) -> bool {
    false
}

#[cfg(test)]
mod tests {
    use content_encoding;
    use Request;

    #[test]
    fn no_req_encodings() {
        let request = Request::fake_http("GET", "/", vec![], vec![]);
        assert_eq!(
            content_encoding::accepted_content_encodings(&request).count(),
            0
        );
    }

    #[test]
    fn empty_req_encodings() {
        let request = {
            let h = vec![("Accept-Encoding".to_owned(), "".to_owned())];
            Request::fake_http("GET", "/", h, vec![])
        };

        assert_eq!(
            content_encoding::accepted_content_encodings(&request).count(),
            0
        );
    }

    #[test]
    fn one_req_encoding() {
        let request = {
            let h = vec![("Accept-Encoding".to_owned(), "foo".to_owned())];
            Request::fake_http("GET", "/", h, vec![])
        };

        let mut list = content_encoding::accepted_content_encodings(&request);
        assert_eq!(list.next().unwrap(), "foo");
        assert_eq!(list.next(), None);
    }

    #[test]
    fn multi_req_encoding() {
        let request = {
            let h = vec![("Accept-Encoding".to_owned(), "foo, bar".to_owned())];
            Request::fake_http("GET", "/", h, vec![])
        };

        let mut list = content_encoding::accepted_content_encodings(&request);
        assert_eq!(list.next().unwrap(), "foo");
        assert_eq!(list.next().unwrap(), "bar");
        assert_eq!(list.next(), None);
    }

    // TODO: more tests for encoding stuff
}
<|endoftext|>


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

//!
//! Roughtime server
//!
//! # Configuration
//! The `roughenough` server is configured via a config file:
//!
//! ```yaml
//! interface: 127.0.0.1
//! port: 8686
//! seed: f61075c988feb9cb700a4a6a3291bfbc9cab11b9c9eca8c802468eb38a43d7d3
//! ```
//!
//! Where:
//!
//!   * **interface** - IP address or interface name for listening to client requests
//!   * **port** - UDP port to listen to requests
//!   * **seed** - A 32-byte hexadecimal value used as the seed to generate the
//!                server's long-term key pair. **This is a secret value**, treat it
//!                with care.
//!
//! # Running the Server
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```

#![allow(deprecated)] // for mio::Timer

extern crate byteorder;
extern crate ring;
extern crate roughenough;
extern crate time;
extern crate untrusted;
extern crate ctrlc;
extern crate yaml_rust;
#[macro_use]
extern crate log;
extern crate simple_logger;
extern crate mio;
extern crate hex;

use std::env;
use std::process;
use std::fs::File;
use std::io::Read;
use std::time::Duration;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

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

use byteorder::{LittleEndian, WriteBytesExt};

use roughenough::{RtMessage, Tag, Error};
use roughenough::{VERSION, CERTIFICATE_CONTEXT, MIN_REQUEST_LENGTH, SIGNED_RESPONSE_CONTEXT, TREE_LEAF_TWEAK};
use roughenough::sign::Signer;

use ring::{digest, rand};
use ring::rand::SecureRandom;

use yaml_rust::YamlLoader;

const MESSAGE: Token = Token(0);
const STATUS: Token = Token(1);

fn create_ephemeral_key() -> Signer {
    let rng = rand::SystemRandom::new();
    let mut seed = [0u8; 32];
    rng.fill(&mut seed).unwrap();

    Signer::new(&seed)
}

fn make_dele_bytes(ephemeral_key: &Signer) -> Result<Vec<u8>, Error> {
    let zeros = [0u8; 8];
    let max = [0xff; 8];

    let mut dele_msg = RtMessage::new(3);
    dele_msg.add_field(Tag::PUBK, ephemeral_key.public_key_bytes())?;
    dele_msg.add_field(Tag::MINT, &zeros)?;
    dele_msg.add_field(Tag::MAXT, &max)?;

    dele_msg.encode()
}

fn make_key_and_cert(seed: &[u8]) -> (Signer, Vec<u8>) {
    let mut long_term_key = Signer::new(seed);
    let ephemeral_key = create_ephemeral_key();

    info!("Long-term public key: {}", hex::encode(long_term_key.public_key_bytes()));
    info!("Ephemeral public key: {}", hex::encode(ephemeral_key.public_key_bytes()));

    // Make DELE and sign it with long-term key
    let dele_bytes = make_dele_bytes(&ephemeral_key).unwrap();
    let dele_signature = {
        long_term_key.update(CERTIFICATE_CONTEXT.as_bytes());
        long_term_key.update(&dele_bytes);
        long_term_key.sign()
    };

    // Create CERT
    let cert_bytes = {
        let mut cert_msg = RtMessage::new(2);
        cert_msg.add_field(Tag::SIG, &dele_signature).unwrap();
        cert_msg.add_field(Tag::DELE, &dele_bytes).unwrap();

        cert_msg.encode().unwrap()
    };

    (ephemeral_key, cert_bytes)
}

fn make_response(ephemeral_key: &mut Signer, cert_bytes: &[u8], nonce: &[u8]) -> RtMessage {
    //   create SREP
    //   sign SREP
    //   create response:
    //    - SIG
    //    - PATH (always 0)
    //    - SREP
    //    - CERT (pre-created)
    //    - INDX (always 0)

    let path = [0u8; 0];
    let zeros = [0u8; 4];

    let mut radi: Vec<u8> = Vec::with_capacity(4);
    let mut midp: Vec<u8> = Vec::with_capacity(8);

    // one second (in microseconds)
    radi.write_u32::<LittleEndian>(1_000_000).unwrap();

    // current epoch time in microseconds
    let now = {
        let tv = time::get_time();
        let secs = (tv.sec as u64) * 1_000_000;
        let nsecs = (tv.nsec as u64) / 1_000;

        secs + nsecs
    };
    midp.write_u64::<LittleEndian>(now).unwrap();

    // Signed response SREP
    let srep_bytes = {
        // hash request nonce
        let mut ctx = digest::Context::new(&digest::SHA512);
        ctx.update(TREE_LEAF_TWEAK);
        ctx.update(nonce);
        let digest = ctx.finish();

        let mut srep_msg = RtMessage::new(3);
        srep_msg.add_field(Tag::RADI, &radi).unwrap();
        srep_msg.add_field(Tag::MIDP, &midp).unwrap();
        srep_msg.add_field(Tag::ROOT, digest.as_ref()).unwrap();

        srep_msg.encode().unwrap()
    };

    // signature on SREP
    let srep_signature = {
        ephemeral_key.update(SIGNED_RESPONSE_CONTEXT.as_bytes());
        ephemeral_key.update(&srep_bytes);
        ephemeral_key.sign()
    };

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

    response
}

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

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

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

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

fn load_config(config_file: &str) -> (SocketAddr, Vec<u8>) {
    let mut infile = File::open(config_file)
        .expect("failed to open config file");

    let mut contents = String::new();
    infile.read_to_string(&mut contents)
        .expect("could not read config file");

    let cfg = YamlLoader::load_from_str(&contents)
        .expect("could not parse config file");

    if cfg.len() != 1 {
        panic!("empty or malformed config file");
    }

    let mut port: u16 = 0;
    let mut iface: String = "unknown".to_string();
    let mut seed: String = "".to_string();

    for (key, value) in cfg[0].as_hash().unwrap() {
        match key.as_str().unwrap() {
            "port" => port = value.as_i64().unwrap() as u16,
            "interface" => iface = value.as_str().unwrap().to_string(),
            "seed" => seed = value.as_str().unwrap().to_string(),
            _ => warn!("ignoring unknown config key '{}'", key.as_str().unwrap())
        }
    }

    let addr = format!("{}:{}", iface, port);
    let sock_addr: SocketAddr = addr.parse()
        .expect(&format!("could not create socket address from {}", addr));

    let binseed = hex::decode(seed)
        .expect("seed value invalid; 'seed' should be 32 byte hex value");

    (sock_addr, binseed)
}

fn polling_loop(addr: &SocketAddr, mut ephemeral_key: &mut Signer, cert_bytes: &[u8]) {
    let keep_running = Arc::new(AtomicBool::new(true));
    let kr = keep_running.clone();

    ctrlc::set_handler(move || kr.store(false, Ordering::Release))
        .expect("failed setting Ctrl-C handler");

    let socket = UdpSocket::bind(addr).expect("failed to bind to socket");
    let status_duration = Duration::from_secs(6_000);
    let poll_duration = Some(Duration::from_millis(100));

    let mut timer: Timer<()> = Timer::default();
    timer.set_timeout(status_duration, ()).expect("unable to set_timeout");

    let mut buf = [0u8; 65_536];
    let mut events = Events::with_capacity(32);
    let mut num_responses = 0u64;
    let mut num_bad_requests = 0u64;

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

    loop {
        if !keep_running.load(Ordering::Acquire) {
            info!("Ctrl-C caught, exiting...");
            break;
        }

        poll.poll(&mut events, poll_duration).expect("poll failed");

        for event in events.iter() {
            match event.token() {
                MESSAGE => {
                    let (num_bytes, src_addr) = socket.recv_from(&mut buf).expect("recv_from failed");

                    if let Ok(nonce) = nonce_from_request(&buf, num_bytes) {
                        let resp = make_response(&mut ephemeral_key, cert_bytes, nonce);
                        let resp_bytes = resp.encode().unwrap();

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

                        num_responses += 1;
                        info!("Responded {} bytes to {} for '{}..' (resp #{})", bytes_sent, src_addr, nonce[0..4].to_hex(), num_responses);
                    } else {
                        num_bad_requests += 1;
                        info!("Invalid request ({} bytes) from {} (resp #{})", num_bytes, src_addr, num_responses);
                    }
                }

                STATUS => {
                    info!("responses {}, invalid requests {}", num_responses, num_bad_requests);
                    timer.set_timeout(status_duration, ()).expect("unable to set_timeout");
                }

                _ => unreachable!()
            }
        }
    }
}

fn main() {
    use log::Level;
    simple_logger::init_with_level(Level::Info).unwrap();

    info!("Roughenough server v{} starting", VERSION);

    let mut args = env::args();
    if args.len() != 2 {
        error!("Usage: server /path/to/config.file");
        process::exit(1);
    }

    let (addr, key_seed) = load_config(&args.nth(1).unwrap());
    let (mut ephemeral_key, cert_bytes) = make_key_and_cert(&key_seed);

    info!("Server listening on {}", addr);

    polling_loop(&addr, &mut ephemeral_key, &cert_bytes);

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

//!
//! Roughtime server
//!
//! # Configuration
//! The `roughenough` server is configured via a config file:
//!
//! ```yaml
//! interface: 127.0.0.1
//! port: 8686
//! seed: f61075c988feb9cb700a4a6a3291bfbc9cab11b9c9eca8c802468eb38a43d7d3
//! ```
//!
//! Where:
//!
//!   * **interface** - IP address or interface name for listening to client requests
//!   * **port** - UDP port to listen to requests
//!   * **seed** - A 32-byte hexadecimal value used as the seed to generate the
//!                server's long-term key pair. **This is a secret value**, treat it
//!                with care.
//!
//! # Running the Server
//!
//! ```bash
//! $ cargo run --release --bin server /path/to/config.file
//! ```

#![allow(deprecated)] // for mio::Timer

extern crate byteorder;
extern crate ring;
extern crate roughenough;
extern crate time;
extern crate untrusted;
extern crate ctrlc;
extern crate yaml_rust;
#[macro_use]
extern crate log;
extern crate simple_logger;
extern crate mio;
extern crate hex;

use std::env;
use std::process;
use std::fs::File;
use std::io::Read;
use std::time::Duration;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

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

use byteorder::{LittleEndian, WriteBytesExt};

use roughenough::{RtMessage, Tag, Error};
use roughenough::{VERSION, CERTIFICATE_CONTEXT, MIN_REQUEST_LENGTH, SIGNED_RESPONSE_CONTEXT, TREE_LEAF_TWEAK};
use roughenough::sign::Signer;

use ring::{digest, rand};
use ring::rand::SecureRandom;

use yaml_rust::YamlLoader;

const MESSAGE: Token = Token(0);
const STATUS: Token = Token(1);

fn create_ephemeral_key() -> Signer {
    let rng = rand::SystemRandom::new();
    let mut seed = [0u8; 32];
    rng.fill(&mut seed).unwrap();

    Signer::new(&seed)
}

fn make_dele_bytes(ephemeral_key: &Signer) -> Result<Vec<u8>, Error> {
    let zeros = [0u8; 8];
    let max = [0xff; 8];

    let mut dele_msg = RtMessage::new(3);
    dele_msg.add_field(Tag::PUBK, ephemeral_key.public_key_bytes())?;
    dele_msg.add_field(Tag::MINT, &zeros)?;
    dele_msg.add_field(Tag::MAXT, &max)?;

    dele_msg.encode()
}

fn make_key_and_cert(seed: &[u8]) -> (Signer, Vec<u8>) {
    let mut long_term_key = Signer::new(seed);
    let ephemeral_key = create_ephemeral_key();

    info!("Long-term public key: {}", hex::encode(long_term_key.public_key_bytes()));
    info!("Ephemeral public key: {}", hex::encode(ephemeral_key.public_key_bytes()));

    // Make DELE and sign it with long-term key
    let dele_bytes = make_dele_bytes(&ephemeral_key).unwrap();
    let dele_signature = {
        long_term_key.update(CERTIFICATE_CONTEXT.as_bytes());
        long_term_key.update(&dele_bytes);
        long_term_key.sign()
    };

    // Create CERT
    let cert_bytes = {
        let mut cert_msg = RtMessage::new(2);
        cert_msg.add_field(Tag::SIG, &dele_signature).unwrap();
        cert_msg.add_field(Tag::DELE, &dele_bytes).unwrap();

        cert_msg.encode().unwrap()
    };

    (ephemeral_key, cert_bytes)
}

fn make_response(ephemeral_key: &mut Signer, cert_bytes: &[u8], nonce: &[u8]) -> RtMessage {
    //   create SREP
    //   sign SREP
    //   create response:
    //    - SIG
    //    - PATH (always 0)
    //    - SREP
    //    - CERT (pre-created)
    //    - INDX (always 0)

    let path = [0u8; 0];
    let zeros = [0u8; 4];

    let mut radi: Vec<u8> = Vec::with_capacity(4);
    let mut midp: Vec<u8> = Vec::with_capacity(8);

    // one second (in microseconds)
    radi.write_u32::<LittleEndian>(1_000_000).unwrap();

    // current epoch time in microseconds
    let now = {
        let tv = time::get_time();
        let secs = (tv.sec as u64) * 1_000_000;
        let nsecs = (tv.nsec as u64) / 1_000;

        secs + nsecs
    };
    midp.write_u64::<LittleEndian>(now).unwrap();

    // Signed response SREP
    let srep_bytes = {
        // hash request nonce
        let mut ctx = digest::Context::new(&digest::SHA512);
        ctx.update(TREE_LEAF_TWEAK);
        ctx.update(nonce);
        let digest = ctx.finish();

        let mut srep_msg = RtMessage::new(3);
        srep_msg.add_field(Tag::RADI, &radi).unwrap();
        srep_msg.add_field(Tag::MIDP, &midp).unwrap();
        srep_msg.add_field(Tag::ROOT, digest.as_ref()).unwrap();

        srep_msg.encode().unwrap()
    };

    // signature on SREP
    let srep_signature = {
        ephemeral_key.update(SIGNED_RESPONSE_CONTEXT.as_bytes());
        ephemeral_key.update(&srep_bytes);
        ephemeral_key.sign()
    };

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

    response
}

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

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

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

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

fn load_config(config_file: &str) -> (SocketAddr, Vec<u8>) {
    let mut infile = File::open(config_file)
        .expect("failed to open config file");

    let mut contents = String::new();
    infile.read_to_string(&mut contents)
        .expect("could not read config file");

    let cfg = YamlLoader::load_from_str(&contents)
        .expect("could not parse config file");

    if cfg.len() != 1 {
        panic!("empty or malformed config file");
    }

    let mut port: u16 = 0;
    let mut iface: String = "unknown".to_string();
    let mut seed: String = "".to_string();

    for (key, value) in cfg[0].as_hash().unwrap() {
        match key.as_str().unwrap() {
            "port" => port = value.as_i64().unwrap() as u16,
            "interface" => iface = value.as_str().unwrap().to_string(),
            "seed" => seed = value.as_str().unwrap().to_string(),
            _ => warn!("ignoring unknown config key '{}'", key.as_str().unwrap())
        }
    }

    let addr = format!("{}:{}", iface, port);
    let sock_addr: SocketAddr = addr.parse()
        .expect(&format!("could not create socket address from {}", addr));

    let binseed = hex::decode(seed)
        .expect("seed value invalid; 'seed' should be 32 byte hex value");

    (sock_addr, binseed)
}

fn polling_loop(addr: &SocketAddr, mut ephemeral_key: &mut Signer, cert_bytes: &[u8]) {
    let keep_running = Arc::new(AtomicBool::new(true));
    let kr = keep_running.clone();

    ctrlc::set_handler(move || kr.store(false, Ordering::Release))
        .expect("failed setting Ctrl-C handler");

    let socket = UdpSocket::bind(addr).expect("failed to bind to socket");
    let status_duration = Duration::from_secs(6_000);
    let poll_duration = Some(Duration::from_millis(100));

    let mut timer: Timer<()> = Timer::default();
    timer.set_timeout(status_duration, ()).expect("unable to set_timeout");

    let mut buf = [0u8; 65_536];
    let mut events = Events::with_capacity(32);
    let mut num_responses = 0u64;
    let mut num_bad_requests = 0u64;

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

    loop {
        if !keep_running.load(Ordering::Acquire) {
            info!("Ctrl-C caught, exiting...");
            break;
        }

        poll.poll(&mut events, poll_duration).expect("poll failed");

        for event in events.iter() {
            match event.token() {
                MESSAGE => {
                    let (num_bytes, src_addr) = socket.recv_from(&mut buf).expect("recv_from failed");

                    if let Ok(nonce) = nonce_from_request(&buf, num_bytes) {
                        let resp = make_response(&mut ephemeral_key, cert_bytes, nonce);
                        let resp_bytes = resp.encode().unwrap();

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

                        num_responses += 1;
                        info!("Responded {} bytes to {} for '{}..' (resp #{})", bytes_sent, src_addr, hex::encode(&nonce[0..4]), num_responses);
                    } else {
                        num_bad_requests += 1;
                        info!("Invalid request ({} bytes) from {} (resp #{})", num_bytes, src_addr, num_responses);
                    }
                }

                STATUS => {
                    info!("responses {}, invalid requests {}", num_responses, num_bad_requests);
                    timer.set_timeout(status_duration, ()).expect("unable to set_timeout");
                }

                _ => unreachable!()
            }
        }
    }
}

fn main() {
    use log::Level;
    simple_logger::init_with_level(Level::Info).unwrap();

    info!("Roughenough server v{} starting", VERSION);

    let mut args = env::args();
    if args.len() != 2 {
        error!("Usage: server /path/to/config.file");
        process::exit(1);
    }

    let (addr, key_seed) = load_config(&args.nth(1).unwrap());
    let (mut ephemeral_key, cert_bytes) = make_key_and_cert(&key_seed);

    info!("Server listening on {}", addr);

    polling_loop(&addr, &mut ephemeral_key, &cert_bytes);

    info!("Done.");
    process::exit(0);
}
<|endoftext|>


<commit_before>mod debugger_command;
mod http_handlers;
mod breakpoint_map;
mod cpu_snapshot;

use asm6502::{Instruction, InstructionDecoder};
use chan::{self, Receiver, Sender};
use cpu::Cpu;
use cpu::debugger::breakpoint_map::BreakpointMap;
use cpu::debugger::cpu_snapshot::{CpuSnapshot, MemorySnapshot};
use cpu::debugger::debugger_command::{BreakReason, DebuggerCommand};
use cpu::debugger::http_handlers::*;
use errors::*;
use iron::prelude::*;
use memory::{ADDRESSABLE_MEMORY, Memory};
use router::Router;
use serde_json;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
use websocket::{Message as WsMessage, Server as WsServer};

const DEBUGGER_HTTP_ADDR: &'static str = "127.0.0.1:9975";
const DEBUGGER_WS_ADDR: &'static str = "127.0.0.1:9976";

pub struct HttpDebugger<Mem: Memory> {
    ws_tx: Sender<DebuggerCommand>,
    ws_rx: Receiver<DebuggerCommand>,
    cpu: Arc<Mutex<Cpu<Mem>>>,
    breakpoints: Arc<Mutex<BreakpointMap>>,
    cpu_thread_handle: thread::Thread,
    cpu_paused: Arc<AtomicBool>,
    last_pc: u16,
    last_mem_hash: u64,
    instructions: Arc<Vec<Instruction>>, // TODO: https://github.com/bgourlie/rs-nes/issues/9
}

impl<Mem: Memory> HttpDebugger<Mem> {
    pub fn new(cpu: Cpu<Mem>) -> Self {
        let mut buf = Vec::new();
        cpu.memory.dump(&mut buf);
        let instructions = InstructionDecoder::new(&buf, cpu.registers.pc).collect();
        let (ws_sender, ws_receiver) = chan::sync(0);
        HttpDebugger {
            ws_tx: ws_sender,
            ws_rx: ws_receiver,
            cpu: Arc::new(Mutex::new(cpu)),
            breakpoints: Arc::new(Mutex::new(BreakpointMap::new())),
            cpu_thread_handle: thread::current(),
            cpu_paused: Arc::new(AtomicBool::new(true)),
            last_pc: 0,
            last_mem_hash: 0,
            instructions: Arc::new(instructions),
        }
    }

    pub fn start(&mut self) -> Result<()> {
        self.start_http_server_thread()?;
        self.start_websocket_thread()?;
        Ok(())
    }

    pub fn step(&mut self) -> Result<()> {
        let cpu = &mut (*self.cpu.lock().unwrap());
        if let Some(break_reason) = self.break_reason(cpu) {
            {
                let mem_snapshot = self.memory_snapshot(cpu);
                if let MemorySnapshot::Updated(hash, _) = mem_snapshot {
                    debug!("Memory altered");
                    self.last_mem_hash = hash;
                }

                let snapshot = CpuSnapshot::new(mem_snapshot, cpu.registers.clone(), cpu.cycles);
                self.ws_tx.send(DebuggerCommand::Break(break_reason, snapshot));
            }
            thread::park();
        }
        self.last_pc = cpu.registers.pc;
        let result = cpu.step();

        if let Err(Error(ErrorKind::Crash(ref reason), _)) = result {
            let mem_snapshot = self.memory_snapshot(cpu);
            let snapshot = CpuSnapshot::new(mem_snapshot, cpu.registers.clone(), cpu.cycles);
            self.ws_tx.send(DebuggerCommand::Crash(reason.clone(), snapshot));

            // Give the web socket thread enough time to send the Crash message
            thread::sleep(Duration::from_millis(100));
        }

        result
    }

    fn break_reason(&self, cpu: &Cpu<Mem>) -> Option<BreakReason> {
        // Stepping deliberately takes the least precedence when determining the break reason
        if self.last_pc == cpu.registers.pc {
            debug!("Trap detected @ {:0>4X}. CPU thread paused.",
                   cpu.registers.pc);
            Some(BreakReason::Trap)
        } else if self.at_breakpoint(cpu.registers.pc) {
            debug!("Breakpoint hit @ {:0>4X}. CPU thread paused.",
                   cpu.registers.pc);
            Some(BreakReason::Breakpoint)
        } else if self.cpu_paused.load(Ordering::Relaxed) {
            debug!("Stepping @ {:0>4X}. CPU thread paused.", cpu.registers.pc);
            Some(BreakReason::Step)
        } else {
            None
        }
    }

    fn memory_snapshot(&self, cpu: &Cpu<Mem>) -> MemorySnapshot {
        let hash = cpu.memory.hash();
        if hash != self.last_mem_hash {
            let mut buf = Vec::with_capacity(ADDRESSABLE_MEMORY);
            cpu.memory.dump(&mut buf);
            MemorySnapshot::Updated(hash, buf)
        } else {
            MemorySnapshot::NoChange(hash)
        }
    }

    fn start_websocket_thread(&mut self) -> Result<()> {
        info!("Starting web socket server at {}", DEBUGGER_WS_ADDR);
        let mut ws_server = WsServer::bind(DEBUGGER_WS_ADDR).map_err(|e| e.to_string())?;
        info!("Waiting for debugger to attach");
        let connection = ws_server.accept();
        info!("Debugger attached!");
        let ws_rx = self.ws_rx.clone();
        thread::spawn(move || {
            let request = connection.unwrap().read_request().unwrap();
            request.validate().unwrap();
            let response = request.accept();
            let mut sender = response.send().unwrap();

            while let Some(debugger_msg) = ws_rx.recv() {
                let message: WsMessage = WsMessage::text(serde_json::to_string(&debugger_msg)
                    .unwrap());

                if sender.send_message(&message).is_err() {
                    break;
                }
            }

            info!("Websocket thread is terminating!")
        });

        Ok(())
    }

    fn start_http_server_thread(&self) -> Result<()> {
        info!("Starting http debugger at {}", DEBUGGER_HTTP_ADDR);
        let cpu_thread = self.cpu_thread_handle.clone();
        let breakpoints = self.breakpoints.clone();
        let cpu_paused = self.cpu_paused.clone();
        let instructions = self.instructions.clone();

        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/step", StepHandler::new(cpu_thread.clone()), "step");
            router.get("/instructions",
                       InstructionHandler::new(instructions.clone()),
                       "instructions");
            router.get("/continue",
                       ContinueHandler::new(cpu_thread.clone(), cpu_paused),
                       "continue");
            router.get("/toggle_breakpoint/:addr",
                       ToggleBreakpointHandler::new(breakpoints.clone()),
                       "toggle_breakpoint");
            Iron::new(router).http(DEBUGGER_HTTP_ADDR).unwrap();
        });

        Ok(())
    }

    fn at_breakpoint(&self, pc: u16) -> bool {
        let breakpoints = &(*self.breakpoints.lock().unwrap());
        if breakpoints.is_set(pc) {
            self.cpu_paused.compare_and_swap(false, true, Ordering::Relaxed);
            true
        } else {
            false
        }
    }
}
<commit_msg>Simplify debugger<commit_after>mod debugger_command;
mod http_handlers;
mod breakpoint_map;
mod cpu_snapshot;

use asm6502::{Instruction, InstructionDecoder};
use chan::{self, Receiver, Sender};
use cpu::Cpu;
use cpu::debugger::breakpoint_map::BreakpointMap;
use cpu::debugger::cpu_snapshot::{CpuSnapshot, MemorySnapshot};
use cpu::debugger::debugger_command::{BreakReason, DebuggerCommand};
use cpu::debugger::http_handlers::*;
use errors::*;
use iron::prelude::*;
use memory::{ADDRESSABLE_MEMORY, Memory};
use router::Router;
use serde_json;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;
use websocket::{Message as WsMessage, Server as WsServer};

const DEBUGGER_HTTP_ADDR: &'static str = "127.0.0.1:9975";
const DEBUGGER_WS_ADDR: &'static str = "127.0.0.1:9976";

pub struct HttpDebugger<Mem: Memory> {
    ws_tx: Sender<DebuggerCommand>,
    ws_rx: Receiver<DebuggerCommand>,
    cpu: Cpu<Mem>,
    breakpoints: Arc<Mutex<BreakpointMap>>,
    cpu_thread_handle: thread::Thread,
    cpu_paused: Arc<AtomicBool>,
    last_pc: u16,
    last_mem_hash: u64,
    instructions: Arc<Vec<Instruction>>, // TODO: https://github.com/bgourlie/rs-nes/issues/9
}

impl<Mem: Memory> HttpDebugger<Mem> {
    pub fn new(cpu: Cpu<Mem>) -> Self {
        let mut buf = Vec::new();
        cpu.memory.dump(&mut buf);
        let instructions = InstructionDecoder::new(&buf, cpu.registers.pc).collect();
        let (ws_sender, ws_receiver) = chan::sync(0);
        HttpDebugger {
            ws_tx: ws_sender,
            ws_rx: ws_receiver,
            cpu: cpu,
            breakpoints: Arc::new(Mutex::new(BreakpointMap::new())),
            cpu_thread_handle: thread::current(),
            cpu_paused: Arc::new(AtomicBool::new(true)),
            last_pc: 0,
            last_mem_hash: 0,
            instructions: Arc::new(instructions),
        }
    }

    pub fn start(&mut self) -> Result<()> {
        self.start_http_server_thread()?;
        self.start_websocket_thread()?;
        Ok(())
    }

    pub fn step(&mut self) -> Result<()> {
        if let Some(break_reason) = self.break_reason() {
            {
                let snapshot = self.cpu_snapshot();
                self.ws_tx.send(DebuggerCommand::Break(break_reason, snapshot));
            }
            thread::park();
        }
        self.last_pc = self.cpu.registers.pc;
        let result = self.cpu.step();

        if let Err(Error(ErrorKind::Crash(ref reason), _)) = result {
            let snapshot = self.cpu_snapshot();
            self.ws_tx.send(DebuggerCommand::Crash(reason.clone(), snapshot));

            // Give the web socket thread enough time to send the Crash message
            thread::sleep(Duration::from_millis(100));
        }

        result
    }

    fn break_reason(&self) -> Option<BreakReason> {
        // Stepping deliberately takes the least precedence when determining the break reason
        if self.last_pc == self.cpu.registers.pc {
            debug!("Trap detected @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Trap)
        } else if self.at_breakpoint(self.cpu.registers.pc) {
            debug!("Breakpoint hit @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Breakpoint)
        } else if self.cpu_paused.load(Ordering::Relaxed) {
            debug!("Stepping @ {:0>4X}. CPU thread paused.",
                   self.cpu.registers.pc);
            Some(BreakReason::Step)
        } else {
            None
        }
    }

    fn cpu_snapshot(&mut self) -> CpuSnapshot {
        let hash = self.cpu.memory.hash();
        let mem_snapshot = if hash != self.last_mem_hash {
            debug!("Memory altered");
            let mut buf = Vec::with_capacity(ADDRESSABLE_MEMORY);
            self.cpu.memory.dump(&mut buf);
            self.last_mem_hash = hash;
            MemorySnapshot::Updated(hash, buf)
        } else {
            MemorySnapshot::NoChange(hash)
        };

        CpuSnapshot::new(mem_snapshot, self.cpu.registers.clone(), self.cpu.cycles)
    }

    fn start_websocket_thread(&mut self) -> Result<()> {
        info!("Starting web socket server at {}", DEBUGGER_WS_ADDR);
        let mut ws_server = WsServer::bind(DEBUGGER_WS_ADDR).map_err(|e| e.to_string())?;
        info!("Waiting for debugger to attach");
        let connection = ws_server.accept();
        info!("Debugger attached!");
        let ws_rx = self.ws_rx.clone();
        thread::spawn(move || {
            let request = connection.unwrap().read_request().unwrap();
            request.validate().unwrap();
            let response = request.accept();
            let mut sender = response.send().unwrap();

            while let Some(debugger_msg) = ws_rx.recv() {
                let message: WsMessage = WsMessage::text(serde_json::to_string(&debugger_msg)
                    .unwrap());

                if sender.send_message(&message).is_err() {
                    break;
                }
            }

            info!("Websocket thread is terminating!")
        });

        Ok(())
    }

    fn start_http_server_thread(&self) -> Result<()> {
        info!("Starting http debugger at {}", DEBUGGER_HTTP_ADDR);
        let cpu_thread = self.cpu_thread_handle.clone();
        let breakpoints = self.breakpoints.clone();
        let cpu_paused = self.cpu_paused.clone();
        let instructions = self.instructions.clone();

        thread::spawn(move || {
            let mut router = Router::new();
            router.get("/step", StepHandler::new(cpu_thread.clone()), "step");
            router.get("/instructions",
                       InstructionHandler::new(instructions.clone()),
                       "instructions");
            router.get("/continue",
                       ContinueHandler::new(cpu_thread.clone(), cpu_paused),
                       "continue");
            router.get("/toggle_breakpoint/:addr",
                       ToggleBreakpointHandler::new(breakpoints.clone()),
                       "toggle_breakpoint");
            Iron::new(router).http(DEBUGGER_HTTP_ADDR).unwrap();
        });

        Ok(())
    }

    fn at_breakpoint(&self, pc: u16) -> bool {
        let breakpoints = &(*self.breakpoints.lock().unwrap());
        if breakpoints.is_set(pc) {
            self.cpu_paused.compare_and_swap(false, true, Ordering::Relaxed);
            true
        } else {
            false
        }
    }
}
<|endoftext|>


<commit_before>//! Task execution related traits and utilities.
//!
//! In the Tokio execution model, futures are lazy. When a future is created, no
//! work is performed. In order for the work defined by the future to happen,
//! the future must be submitted to an executor. A future that is submitted to
//! an executor is called a "task".
//!
//! The executor is responsible for ensuring that [`Future::poll`] is called
//! whenever the task is [notified]. Notification happens when the internal
//! state of a task transitions from "not ready" to ready. For example, a socket
//! might have received data and a call to `read` will now be able to succeed.
//!
//! This crate provides traits and utilities that are necessary for building an
//! executor, including:
//!
//! * The [`Executor`] trait describes the API for spawning a future onto an
//!   executor.
//!
//! * [`enter`] marks that the the current thread is entering an execution
//!   context. This prevents a second executor from accidentally starting from
//!   within the context of one that is already running.
//!
//! * [`DefaultExecutor`] spawns tasks onto the default executor for the current
//!   context.
//!
//! * [`Park`] abstracts over blocking and unblocking the current thread.
//!
//! [`Executor`]: trait.Executor.html
//! [`enter`]: fn.enter.html
//! [`DefaultExecutor`]: struct.DefaultExecutor.html
//! [`Park`]: park/index.html

#![deny(missing_docs, missing_debug_implementations, warnings)]
#![doc(html_root_url = "https://docs.rs/tokio-executor/0.1.2")]

extern crate futures;

#[cfg(feature = "unstable-futures")]
extern crate futures2;

mod enter;
mod global;
pub mod park;

pub use enter::{enter, Enter, EnterError};
pub use global::{spawn, with_default, DefaultExecutor};

#[cfg(feature = "unstable-futures")]
pub use global::spawn2;

use futures::Future;

/// A value that executes futures.
///
/// The [`spawn`] function is used to submit a future to an executor. Once
/// submitted, the executor takes ownership of the future and becomes
/// responsible for driving the future to completion.
///
/// The strategy employed by the executor to handle the future is less defined
/// and is left up to the `Executor` implementation. The `Executor` instance is
/// expected to call [`poll`] on the future once it has been notified, however
/// the "when" and "how" can vary greatly.
///
/// For example, the executor might be a thread pool, in which case a set of
/// threads have already been spawned up and the future is inserted into a
/// queue. A thread will acquire the future and poll it.
///
/// The `Executor` trait is only for futures that **are** `Send`. These are most
/// common. There currently is no trait that describes executors that operate
/// entirely on the current thread (i.e., are able to spawn futures that are not
/// `Send`). Note that single threaded executors can still implement `Executor`,
/// but only futures that are `Send` can be spawned via the trait.
///
/// # Errors
///
/// The [`spawn`] function returns `Result` with an error type of `SpawnError`.
/// This error type represents the reason that the executor was unable to spawn
/// the future. The two current represented scenarios are:
///
/// * An executor being at capacity or full. As such, the executor is not able
///   to accept a new future. This error state is expected to be transient.
/// * An executor has been shutdown and can no longer accept new futures. This
///   error state is expected to be permanent.
///
/// If a caller encounters an at capacity error, the caller should try to shed
/// load. This can be as simple as dropping the future that was spawned.
///
/// If the caller encounters a shutdown error, the caller should attempt to
/// gracefully shutdown.
///
/// # Examples
///
/// ```rust
/// # extern crate futures;
/// # extern crate tokio_executor;
/// # use tokio_executor::Executor;
/// # fn docs(my_executor: &mut Executor) {
/// use futures::future::lazy;
/// my_executor.spawn(Box::new(lazy(|| {
///     println!("running on the executor");
///     Ok(())
/// }))).unwrap();
/// # }
/// # fn main() {}
/// ```
///
/// [`spawn`]: #tymethod.spawn
/// [`poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll
pub trait Executor {
    /// Spawns a future object to run on this executor.
    ///
    /// `future` is passed to the executor, which will begin running it. The
    /// future may run on the current thread or another thread at the discretion
    /// of the `Executor` implementation.
    ///
    /// # Panics
    ///
    /// Implementors are encouraged to avoid panics. However, a panic is
    /// permitted and the caller should check the implementation specific
    /// documentation for more details on possible panics.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate tokio_executor;
    /// # use tokio_executor::Executor;
    /// # fn docs(my_executor: &mut Executor) {
    /// use futures::future::lazy;
    /// my_executor.spawn(Box::new(lazy(|| {
    ///     println!("running on the executor");
    ///     Ok(())
    /// }))).unwrap();
    /// # }
    /// # fn main() {}
    /// ```
    fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
             -> Result<(), SpawnError>;

    /// Like `spawn`, but compatible with futures 0.2
    #[cfg(feature = "unstable-futures")]
    fn spawn2(&mut self, future: Box<futures2::Future<Item = (), Error = futures2::Never> + Send>)
             -> Result<(), futures2::executor::SpawnError>;

    /// Provides a best effort **hint** to whether or not `spawn` will succeed.
    ///
    /// This function may return both false positives **and** false negatives.
    /// If `status` returns `Ok`, then a call to `spawn` will *probably*
    /// succeed, but may fail. If `status` returns `Err`, a call to `spawn` will
    /// *probably* fail, but may succeed.
    ///
    /// This allows a caller to avoid creating the task if the call to `spawn`
    /// has a high likelihood of failing.
    ///
    /// # Panics
    ///
    /// This function must not panic. Implementors must ensure that panics do
    /// not happen.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate tokio_executor;
    /// # use tokio_executor::Executor;
    /// # fn docs(my_executor: &mut Executor) {
    /// use futures::future::lazy;
    ///
    /// if my_executor.status().is_ok() {
    ///     my_executor.spawn(Box::new(lazy(|| {
    ///         println!("running on the executor");
    ///         Ok(())
    ///     }))).unwrap();
    /// } else {
    ///     println!("the executor is not in a good state");
    /// }
    /// # }
    /// # fn main() {}
    /// ```
    fn status(&self) -> Result<(), SpawnError> {
        Ok(())
    }
}

/// Errors returned by `Executor::spawn`.
///
/// Spawn errors should represent relatively rare scenarios. Currently, the two
/// scenarios represented by `SpawnError` are:
///
/// * An executor being at capacity or full. As such, the executor is not able
///   to accept a new future. This error state is expected to be transient.
/// * An executor has been shutdown and can no longer accept new futures. This
///   error state is expected to be permanent.
#[derive(Debug)]
pub struct SpawnError {
    is_shutdown: bool,
}

impl SpawnError {
    /// Return a new `SpawnError` reflecting a shutdown executor failure.
    pub fn shutdown() -> Self {
        SpawnError { is_shutdown: true }
    }

    /// Return a new `SpawnError` reflecting an executor at capacity failure.
    pub fn at_capacity() -> Self {
        SpawnError { is_shutdown: false }
    }

    /// Returns `true` if the error reflects a shutdown executor failure.
    pub fn is_shutdown(&self) -> bool {
        self.is_shutdown
    }

    /// Returns `true` if the error reflects an executor at capacity failure.
    pub fn is_at_capacity(&self) -> bool {
        !self.is_shutdown
    }
}
<commit_msg>Implement Executor for Box<E: Executor> (#420)<commit_after>//! Task execution related traits and utilities.
//!
//! In the Tokio execution model, futures are lazy. When a future is created, no
//! work is performed. In order for the work defined by the future to happen,
//! the future must be submitted to an executor. A future that is submitted to
//! an executor is called a "task".
//!
//! The executor is responsible for ensuring that [`Future::poll`] is called
//! whenever the task is [notified]. Notification happens when the internal
//! state of a task transitions from "not ready" to ready. For example, a socket
//! might have received data and a call to `read` will now be able to succeed.
//!
//! This crate provides traits and utilities that are necessary for building an
//! executor, including:
//!
//! * The [`Executor`] trait describes the API for spawning a future onto an
//!   executor.
//!
//! * [`enter`] marks that the the current thread is entering an execution
//!   context. This prevents a second executor from accidentally starting from
//!   within the context of one that is already running.
//!
//! * [`DefaultExecutor`] spawns tasks onto the default executor for the current
//!   context.
//!
//! * [`Park`] abstracts over blocking and unblocking the current thread.
//!
//! [`Executor`]: trait.Executor.html
//! [`enter`]: fn.enter.html
//! [`DefaultExecutor`]: struct.DefaultExecutor.html
//! [`Park`]: park/index.html

#![deny(missing_docs, missing_debug_implementations, warnings)]
#![doc(html_root_url = "https://docs.rs/tokio-executor/0.1.2")]

extern crate futures;

#[cfg(feature = "unstable-futures")]
extern crate futures2;

mod enter;
mod global;
pub mod park;

pub use enter::{enter, Enter, EnterError};
pub use global::{spawn, with_default, DefaultExecutor};

#[cfg(feature = "unstable-futures")]
pub use global::spawn2;

use futures::Future;

/// A value that executes futures.
///
/// The [`spawn`] function is used to submit a future to an executor. Once
/// submitted, the executor takes ownership of the future and becomes
/// responsible for driving the future to completion.
///
/// The strategy employed by the executor to handle the future is less defined
/// and is left up to the `Executor` implementation. The `Executor` instance is
/// expected to call [`poll`] on the future once it has been notified, however
/// the "when" and "how" can vary greatly.
///
/// For example, the executor might be a thread pool, in which case a set of
/// threads have already been spawned up and the future is inserted into a
/// queue. A thread will acquire the future and poll it.
///
/// The `Executor` trait is only for futures that **are** `Send`. These are most
/// common. There currently is no trait that describes executors that operate
/// entirely on the current thread (i.e., are able to spawn futures that are not
/// `Send`). Note that single threaded executors can still implement `Executor`,
/// but only futures that are `Send` can be spawned via the trait.
///
/// # Errors
///
/// The [`spawn`] function returns `Result` with an error type of `SpawnError`.
/// This error type represents the reason that the executor was unable to spawn
/// the future. The two current represented scenarios are:
///
/// * An executor being at capacity or full. As such, the executor is not able
///   to accept a new future. This error state is expected to be transient.
/// * An executor has been shutdown and can no longer accept new futures. This
///   error state is expected to be permanent.
///
/// If a caller encounters an at capacity error, the caller should try to shed
/// load. This can be as simple as dropping the future that was spawned.
///
/// If the caller encounters a shutdown error, the caller should attempt to
/// gracefully shutdown.
///
/// # Examples
///
/// ```rust
/// # extern crate futures;
/// # extern crate tokio_executor;
/// # use tokio_executor::Executor;
/// # fn docs(my_executor: &mut Executor) {
/// use futures::future::lazy;
/// my_executor.spawn(Box::new(lazy(|| {
///     println!("running on the executor");
///     Ok(())
/// }))).unwrap();
/// # }
/// # fn main() {}
/// ```
///
/// [`spawn`]: #tymethod.spawn
/// [`poll`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html#tymethod.poll
pub trait Executor {
    /// Spawns a future object to run on this executor.
    ///
    /// `future` is passed to the executor, which will begin running it. The
    /// future may run on the current thread or another thread at the discretion
    /// of the `Executor` implementation.
    ///
    /// # Panics
    ///
    /// Implementors are encouraged to avoid panics. However, a panic is
    /// permitted and the caller should check the implementation specific
    /// documentation for more details on possible panics.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate tokio_executor;
    /// # use tokio_executor::Executor;
    /// # fn docs(my_executor: &mut Executor) {
    /// use futures::future::lazy;
    /// my_executor.spawn(Box::new(lazy(|| {
    ///     println!("running on the executor");
    ///     Ok(())
    /// }))).unwrap();
    /// # }
    /// # fn main() {}
    /// ```
    fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
             -> Result<(), SpawnError>;

    /// Like `spawn`, but compatible with futures 0.2
    #[cfg(feature = "unstable-futures")]
    fn spawn2(&mut self, future: Box<futures2::Future<Item = (), Error = futures2::Never> + Send>)
             -> Result<(), futures2::executor::SpawnError>;

    /// Provides a best effort **hint** to whether or not `spawn` will succeed.
    ///
    /// This function may return both false positives **and** false negatives.
    /// If `status` returns `Ok`, then a call to `spawn` will *probably*
    /// succeed, but may fail. If `status` returns `Err`, a call to `spawn` will
    /// *probably* fail, but may succeed.
    ///
    /// This allows a caller to avoid creating the task if the call to `spawn`
    /// has a high likelihood of failing.
    ///
    /// # Panics
    ///
    /// This function must not panic. Implementors must ensure that panics do
    /// not happen.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate futures;
    /// # extern crate tokio_executor;
    /// # use tokio_executor::Executor;
    /// # fn docs(my_executor: &mut Executor) {
    /// use futures::future::lazy;
    ///
    /// if my_executor.status().is_ok() {
    ///     my_executor.spawn(Box::new(lazy(|| {
    ///         println!("running on the executor");
    ///         Ok(())
    ///     }))).unwrap();
    /// } else {
    ///     println!("the executor is not in a good state");
    /// }
    /// # }
    /// # fn main() {}
    /// ```
    fn status(&self) -> Result<(), SpawnError> {
        Ok(())
    }
}

impl<E: Executor + ?Sized> Executor for Box<E> {
    fn spawn(&mut self, future: Box<Future<Item = (), Error = ()> + Send>)
        -> Result<(), SpawnError>
    {
        (**self).spawn(future)
    }

    #[cfg(feature = "unstable-futures")]
    fn spawn2(&mut self, future: Box<futures2::Future<Item = (), Error = futures2::Never> + Send>)
        -> Result<(), futures2::executor::SpawnError>
    {
        (**self).spawn2(future)
    }

    fn status(&self) -> Result<(), SpawnError> {
        (**self).status()
    }
}

/// Errors returned by `Executor::spawn`.
///
/// Spawn errors should represent relatively rare scenarios. Currently, the two
/// scenarios represented by `SpawnError` are:
///
/// * An executor being at capacity or full. As such, the executor is not able
///   to accept a new future. This error state is expected to be transient.
/// * An executor has been shutdown and can no longer accept new futures. This
///   error state is expected to be permanent.
#[derive(Debug)]
pub struct SpawnError {
    is_shutdown: bool,
}

impl SpawnError {
    /// Return a new `SpawnError` reflecting a shutdown executor failure.
    pub fn shutdown() -> Self {
        SpawnError { is_shutdown: true }
    }

    /// Return a new `SpawnError` reflecting an executor at capacity failure.
    pub fn at_capacity() -> Self {
        SpawnError { is_shutdown: false }
    }

    /// Returns `true` if the error reflects a shutdown executor failure.
    pub fn is_shutdown(&self) -> bool {
        self.is_shutdown
    }

    /// Returns `true` if the error reflects an executor at capacity failure.
    pub fn is_at_capacity(&self) -> bool {
        !self.is_shutdown
    }
}
<|endoftext|>


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

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

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

#[cfg(feature = "unstable-futures")]
use futures2;

/// An I/O object representing a TCP socket listening for incoming connections.
///
/// This object can be converted into a stream of incoming connections for
/// various forms of processing.
pub struct TcpListener {
    io: PollEvented<mio::net::TcpListener>,
}

impl TcpListener {
    /// Create a new TCP listener associated with this event loop.
    ///
    /// The TCP listener will bind to the provided `addr` address, if available.
    /// If the result is `Ok`, the socket has successfully bound.
    pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
        let l = mio::net::TcpListener::bind(addr)?;
        Ok(TcpListener::new(l))
    }

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

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// Note that typically for simple usage it's easier to treat incoming
    /// connections as a `Stream` of `TcpStream`s with the `incoming` method
    /// below.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    pub fn poll_accept(&mut self) -> Poll<(TcpStream, SocketAddr), io::Error> {
        let (io, addr) = try_ready!(self.poll_accept_std());

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

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

    /// Like `poll_accept`, but for futures 0.2
    #[cfg(feature = "unstable-futures")]
    pub fn poll_accept2(&mut self, cx: &mut futures2::task::Context)
        -> futures2::Poll<(TcpStream, SocketAddr), io::Error>
    {
        let (io, addr) = match self.poll_accept_std2(cx)? {
            futures2::Async::Ready(x) => x,
            futures2::Async::Pending => return Ok(futures2::Async::Pending),
        };

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

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

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

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// This function is the asme as `accept` above except that it returns a
    /// `std::net::TcpStream` instead of a `tokio::net::TcpStream`. This in turn
    /// can then allow for the TCP stream to be assoiated with a different
    /// reactor than the one this `TcpListener` is associated with.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    pub fn poll_accept_std(&mut self) -> Poll<(net::TcpStream, SocketAddr), io::Error> {
        try_ready!(self.io.poll_read_ready(mio::Ready::readable()));

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

    /// Like `poll_accept_std`, but for futures 0.2.
    #[cfg(feature = "unstable-futures")]
    pub fn poll_accept_std2(&mut self, cx: &mut futures2::task::Context)
        -> futures2::Poll<(net::TcpStream, SocketAddr), io::Error>
    {
        if let futures2::Async::Pending = self.io.poll_read_ready2(cx, mio::Ready::readable())? {
            return Ok(futures2::Async::Pending);
        }

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

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

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

    /// Returns the local address that this listener is bound to.
    ///
    /// This can be useful, for example, when binding to port 0 to figure out
    /// which port was actually bound.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().local_addr()
    }

    /// Consumes this listener, returning a stream of the sockets this listener
    /// accepts.
    ///
    /// This method returns an implementation of the `Stream` trait which
    /// resolves to the sockets the are accepted on this listener.
    pub fn incoming(self) -> Incoming {
        Incoming::new(self)
    }

    /// Gets the value of the `IP_TTL` option for this socket.
    ///
    /// For more information about this option, see [`set_ttl`].
    ///
    /// [`set_ttl`]: #method.set_ttl
    pub fn ttl(&self) -> io::Result<u32> {
        self.io.get_ref().ttl()
    }

    /// Sets the value for the `IP_TTL` option on this socket.
    ///
    /// This value sets the time-to-live field that is used in every packet sent
    /// from this socket.
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.get_ref().set_ttl(ttl)
    }
}

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

#[cfg(all(unix, not(target_os = "fuchsia")))]
mod sys {
    use std::os::unix::prelude::*;
    use super::TcpListener;

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

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

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

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

#[cfg(feature = "unstable-futures")]
use futures2;

/// An I/O object representing a TCP socket listening for incoming connections.
///
/// This object can be converted into a stream of incoming connections for
/// various forms of processing.
pub struct TcpListener {
    io: PollEvented<mio::net::TcpListener>,
}

impl TcpListener {
    /// Create a new TCP listener associated with this event loop.
    ///
    /// The TCP listener will bind to the provided `addr` address, if available.
    /// If the result is `Ok`, the socket has successfully bound.
    pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
        let l = mio::net::TcpListener::bind(addr)?;
        Ok(TcpListener::new(l))
    }

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

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// Note that typically for simple usage it's easier to treat incoming
    /// connections as a `Stream` of `TcpStream`s with the `incoming` method
    /// below.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    pub fn poll_accept(&mut self) -> Poll<(TcpStream, SocketAddr), io::Error> {
        let (io, addr) = try_ready!(self.poll_accept_std());

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

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

    /// Like `poll_accept`, but for futures 0.2
    #[cfg(feature = "unstable-futures")]
    pub fn poll_accept2(&mut self, cx: &mut futures2::task::Context)
        -> futures2::Poll<(TcpStream, SocketAddr), io::Error>
    {
        let (io, addr) = match self.poll_accept_std2(cx)? {
            futures2::Async::Ready(x) => x,
            futures2::Async::Pending => return Ok(futures2::Async::Pending),
        };

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

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

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

    /// Attempt to accept a connection and create a new connected `TcpStream` if
    /// successful.
    ///
    /// This function is the same as `accept` above except that it returns a
    /// `std::net::TcpStream` instead of a `tokio::net::TcpStream`. This in turn
    /// can then allow for the TCP stream to be assoiated with a different
    /// reactor than the one this `TcpListener` is associated with.
    ///
    /// # Return
    ///
    /// On success, returns `Ok(Async::Ready((socket, addr)))`.
    ///
    /// If the listener is not ready to accept, the method returns
    /// `Ok(Async::NotReady)` and arranges for the current task to receive a
    /// notification when the listener becomes ready to accept.
    ///
    /// # Panics
    ///
    /// This function will panic if called from outside of a task context.
    pub fn poll_accept_std(&mut self) -> Poll<(net::TcpStream, SocketAddr), io::Error> {
        try_ready!(self.io.poll_read_ready(mio::Ready::readable()));

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

    /// Like `poll_accept_std`, but for futures 0.2.
    #[cfg(feature = "unstable-futures")]
    pub fn poll_accept_std2(&mut self, cx: &mut futures2::task::Context)
        -> futures2::Poll<(net::TcpStream, SocketAddr), io::Error>
    {
        if let futures2::Async::Pending = self.io.poll_read_ready2(cx, mio::Ready::readable())? {
            return Ok(futures2::Async::Pending);
        }

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

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

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

    /// Returns the local address that this listener is bound to.
    ///
    /// This can be useful, for example, when binding to port 0 to figure out
    /// which port was actually bound.
    pub fn local_addr(&self) -> io::Result<SocketAddr> {
        self.io.get_ref().local_addr()
    }

    /// Consumes this listener, returning a stream of the sockets this listener
    /// accepts.
    ///
    /// This method returns an implementation of the `Stream` trait which
    /// resolves to the sockets the are accepted on this listener.
    pub fn incoming(self) -> Incoming {
        Incoming::new(self)
    }

    /// Gets the value of the `IP_TTL` option for this socket.
    ///
    /// For more information about this option, see [`set_ttl`].
    ///
    /// [`set_ttl`]: #method.set_ttl
    pub fn ttl(&self) -> io::Result<u32> {
        self.io.get_ref().ttl()
    }

    /// Sets the value for the `IP_TTL` option on this socket.
    ///
    /// This value sets the time-to-live field that is used in every packet sent
    /// from this socket.
    pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
        self.io.get_ref().set_ttl(ttl)
    }
}

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

#[cfg(all(unix, not(target_os = "fuchsia")))]
mod sys {
    use std::os::unix::prelude::*;
    use super::TcpListener;

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

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