<commit_before>use state::{Selectable, Editable, Named};
use std::cmp;
use std::io::{stdout, Stdout, BufWriter, Write, Result};
use std::iter;
use termion::terminal_size;
use termion::input::MouseTerminal;
use termion::screen::AlternateScreen;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::{clear, style, cursor, color};

pub struct View {
    stdout: BufWriter<MouseTerminal<AlternateScreen<RawTerminal<Stdout>>>>,
    message: Option<String>,
    is_prompt: bool,
    line_offset: u16,
}

const TAB_LENGTH: usize = 4;

impl View {
    pub fn new() -> Result<View> {
        Ok(View {
            stdout: BufWriter::new(MouseTerminal::from(AlternateScreen::from(stdout()
                                                                         .into_raw_mode()
                                                                         .unwrap()))),
               message: None,
               is_prompt: false,
               line_offset: 0,
           })
    }

    pub fn message(&mut self, message: &str) {
        self.is_prompt = false;
        self.message = Some(String::from(message));
    }

    pub fn prompt(&mut self, prompt: &str, message: &str) {
        self.is_prompt = true;
        let msg = String::from(prompt) + message;
        self.message = Some(msg);
    }

    pub fn quiet(&mut self) {
        self.is_prompt = false;
        self.message = None;
    }

    pub fn center_view(&mut self, line: usize) {
        self.line_offset = match line.checked_sub(self.lines_height() as usize / 2) {
            None => 0,
            Some(val) => val as u16,
        }
    }

    pub fn adjust_view(&mut self, line: usize) {
        let line = line as u16;
        if line < self.line_offset {
            self.line_offset = line;
        } else if line + 1 >= self.line_offset + self.lines_height() {
            self.line_offset = 1 + line - self.lines_height();
        }
    }

    pub fn scroll_view<T: Editable>(&mut self, offset: isize, content: &T) {
        self.line_offset = cmp::min(cmp::max((self.line_offset as isize) + offset, 0),
                                    (content.line_count() as isize) - 1) as
                           u16;
    }

    pub fn render<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Named + Selectable
    {
        self.paint_lines(content)?;
        self.paint_status(content)?;
        self.paint_message()?;
        self.paint_cursor(content)?;
        self.stdout.flush()?;
        Ok(())
    }

    pub fn translate_coordinates<T>(&self, content: &T, x: u16, y: u16) -> (usize, usize)
        where T: Editable
    {
        let line = cmp::min((y as isize + self.line_offset as isize - 1) as usize,
                            content.line_count() - 1);
        let visual_col = (cmp::max(0,
                                   x as isize -
                                   self.line_number_width(content.line_count()) as isize -
                                   2)) as usize;
        // find out if we clicked through a tab
        let col = content
            .iter_line(line)
            .scan(0, |state, x| {
                *state += if x == '\t' { TAB_LENGTH } else { 1 };
                Some(*state)
            })
            .take_while(|&x| x <= visual_col)
            .count();
        (line, col)
    }

    fn paint_message(&mut self) -> Result<()> {
        if let Some(ref message) = self.message {
            let y = self.lines_height() + 1;
            write!(self.stdout, "{}{}", cursor::Goto(1, 1 + y as u16), message)?;
            self.stdout.flush()?;
        }
        Ok(())
    }

    fn paint_cursor<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Selectable
    {
        // FIXME: don't print the cursor if off screen, though we should in the future for long
        // lines
        if (content.line() as u16) < self.line_offset ||
           content.line() as u16 >= self.line_offset + self.lines_height() ||
           content.col() as u16 >= self.lines_width(content.line_count()) ||
           content.sel().is_some() {
            write!(self.stdout, "{}", cursor::Hide)?;
            return Ok(());
        }

        // in the case of a prompt, the cursor should be drawn in the message line
        let (x, y) = if self.is_prompt {
            (self.message.clone().unwrap().chars().count() as u16, self.lines_height() + 1)
        } else {
            let (a, b) = self.cursor_pos(content);
            (a as u16, b as u16)
        };
        write!(self.stdout,
               "{}{}",
               cursor::Show,
               cursor::Goto(1 + x, 1 + y))?;
        Ok(())
    }

    fn paint_status<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Named
    {
        let line = content.line();
        let column = content.col();
        let line_count = content.line_count();
        let advance = ((line + 1) as f64 / line_count as f64 * 100.0).floor();

        let (screen_width, _) = terminal_size().unwrap();
        let empty_line = (0..screen_width).map(|_| ' ').collect::<String>();
        let y = self.lines_height() as u16;

        write!(self.stdout,
               "{}{}{}{}{}{}",
               color::Fg(color::White),
               style::Invert,
               cursor::Goto(1, 1 + y),
               empty_line,
               cursor::Goto(1, 1 + y),
               content.name())?;

        let position_info = format!("{}% {}/{}: {}", advance, line + 1, line_count, column);
        let x = screen_width - position_info.len() as u16;
        write!(self.stdout,
               "{}{}{}",
               cursor::Goto(1 + x, 1 + y),
               position_info,
               style::Reset)?;
        Ok(())
    }

    fn paint_lines<T>(&mut self, content: &T) -> Result<()>
        where T: Editable + Selectable
    {
        let line_offset = self.line_offset as usize;
        let lines_height = self.lines_height() as usize;
        let lines_width = self.lines_width(content.line_count()) as usize;
        let line_count = content.line_count();

        let line_start = self.line_number_width(line_count) + 1;

        write!(self.stdout, "{}", cursor::Hide)?;

        for (y, line) in content
                .lines()
                .skip(line_offset)
                .take(cmp::min(lines_height, line_count))
                .enumerate() {
            // paint line number and initialize display for this line
            let line_index = line_offset + y;
            write!(self.stdout,
                   "{}{}{}{}{}{}",
                   cursor::Goto(1, 1 + y as u16),
                   clear::CurrentLine,
                   color::Fg(color::White),
                   1 + line_index, // the line number
                   style::Reset,
                   cursor::Goto(1 + line_start, 1 + y as u16))?;

            if line.char_count() > 0 {
                let line_start_char_index = content.line_index_to_char_index(line_index);
                for (x, c) in line.char_iter()
                        .flat_map(|c| if c == '\t' {
                                      iter::repeat(' ').take(TAB_LENGTH)
                                  } else {
                                      iter::repeat(c).take(1)
                                  })
                        .enumerate() {

                    let char_index = line_start_char_index + x;

                    if x < lines_width {
                        if content.in_sel(char_index) {
                            write!(self.stdout, "{}{}{}", style::Invert, c, style::Reset)?;
                        } else {
                            write!(self.stdout, "{}", c)?;
                        }
                    }
                }
            } else if content.line_in_sel(line_offset + y) {
                write!(self.stdout,
                       "{}{} {}",
                       clear::CurrentLine,
                       style::Invert,
                       style::Reset)?;
            }
        }
        write!(self.stdout, "{}{}", clear::AfterCursor, cursor::Show)?;
        Ok(())
    }

    fn cursor_pos<T: Editable>(&self, content: &T) -> (usize, usize) {
        // TODO: column offsetting for long lines
        let line = content.line();
        let first_line = self.line_offset;
        let y = line - first_line as usize;
        // we can't trust the actual column because tabs have variable length
        let visual_col = content.col();
        let column = content
            .iter_line(line)
            .map(|x| if x == '\t' { TAB_LENGTH } else { 1 })
            .take(visual_col)
            .fold(0, |acc, x| acc + x);
        ((self.line_number_width(content.line_count()) as usize + 1 + column), y)
    }

    fn line_number_width(&self, line_count: usize) -> u16 {
        line_count.to_string().len() as u16
    }

    fn status_height(&self) -> u16 {
        2
    }

    pub fn lines_height(&self) -> u16 {
        let (_, screen_height) = terminal_size().unwrap();
        let incompressible = self.status_height();
        cmp::max(screen_height, incompressible) - incompressible
    }

    pub fn lines_width(&self, line_count: usize) -> u16 {
        let (screen_width, _) = terminal_size().unwrap();
        let incompressible = self.line_number_width(line_count) + 1;
        cmp::max(screen_width, incompressible) - incompressible
    }
}
<commit_msg>actual output buffering<commit_after>use state::{Selectable, Editable, Named};
use std::cmp;
use std::io::{stdout, Stdout, Write, BufWriter, Result};
use std::iter;
use termion::terminal_size;
use termion::input::MouseTerminal;
use termion::screen::AlternateScreen;
use termion::raw::{IntoRawMode, RawTerminal};
use termion::{clear, style, cursor, color};

pub struct View {
    message: Option<String>,
    is_prompt: bool,
    line_offset: u16,
    _stdout_handle: MouseTerminal<AlternateScreen<RawTerminal<Stdout>>>,
}

const TAB_LENGTH: usize = 4;

impl View {
    pub fn new() -> Result<View> {
        Ok(View {
               message: None,
               is_prompt: false,
               line_offset: 0,
               _stdout_handle: MouseTerminal::from(AlternateScreen::from(stdout()
                                                                             .into_raw_mode()
                                                                             .unwrap())),
           })
    }

    pub fn message(&mut self, message: &str) {
        self.is_prompt = false;
        self.message = Some(String::from(message));
    }

    pub fn prompt(&mut self, prompt: &str, message: &str) {
        self.is_prompt = true;
        let msg = String::from(prompt) + message;
        self.message = Some(msg);
    }

    pub fn quiet(&mut self) {
        self.is_prompt = false;
        self.message = None;
    }

    pub fn center_view(&mut self, line: usize) {
        self.line_offset = match line.checked_sub(self.lines_height() as usize / 2) {
            None => 0,
            Some(val) => val as u16,
        }
    }

    pub fn adjust_view(&mut self, line: usize) {
        let line = line as u16;
        if line < self.line_offset {
            self.line_offset = line;
        } else if line + 1 >= self.line_offset + self.lines_height() {
            self.line_offset = 1 + line - self.lines_height();
        }
    }

    pub fn scroll_view<T: Editable>(&mut self, offset: isize, content: &T) {
        self.line_offset = cmp::min(cmp::max((self.line_offset as isize) + offset, 0),
                                    (content.line_count() as isize) - 1) as
                           u16;
    }

    pub fn render<T>(&self, content: &T) -> Result<()>
        where T: Editable + Named + Selectable
    {
        // the held stdout will keep us in the correct mode
        let mut out = BufWriter::new(stdout()); // get a new output stream

        self.paint_lines(content, &mut out)?;
        self.paint_status(content, &mut out)?;
        self.paint_message(&mut out)?;
        self.paint_cursor(content, &mut out)?;

        let mut buf_out = out.into_inner()?;
        buf_out.flush()?;
        Ok(())
    }

    pub fn translate_coordinates<T>(&self, content: &T, x: u16, y: u16) -> (usize, usize)
        where T: Editable
    {
        let line = cmp::min((y as isize + self.line_offset as isize - 1) as usize,
                            content.line_count() - 1);
        let visual_col = (cmp::max(0,
                                   x as isize -
                                   self.line_number_width(content.line_count()) as isize -
                                   2)) as usize;
        // find out if we clicked through a tab
        let col = content
            .iter_line(line)
            .scan(0, |state, x| {
                *state += if x == '\t' { TAB_LENGTH } else { 1 };
                Some(*state)
            })
            .take_while(|&x| x <= visual_col)
            .count();
        (line, col)
    }

    fn paint_message<W: Write>(&self, out: &mut W) -> Result<()> {
        if let Some(ref message) = self.message {
            let y = self.lines_height() + 1;
            write!(out, "{}{}", cursor::Goto(1, 1 + y as u16), message)?;
            out.flush()?;
        }
        Ok(())
    }

    fn paint_cursor<T, W>(&self, content: &T, out: &mut W) -> Result<()>
        where T: Editable + Selectable,
              W: Write
    {
        // FIXME: don't print the cursor if off screen, though we should in the future for long
        // lines
        if (content.line() as u16) < self.line_offset ||
           content.line() as u16 >= self.line_offset + self.lines_height() ||
           content.col() as u16 >= self.lines_width(content.line_count()) ||
           content.sel().is_some() {
            write!(out, "{}", cursor::Hide)?;
            return Ok(());
        }

        // in the case of a prompt, the cursor should be drawn in the message line
        let (x, y) = if self.is_prompt {
            (self.message.clone().unwrap().chars().count() as u16, self.lines_height() + 1)
        } else {
            let (a, b) = self.cursor_pos(content);
            (a as u16, b as u16)
        };
        write!(out, "{}{}", cursor::Show, cursor::Goto(1 + x, 1 + y))?;
        Ok(())
    }

    fn paint_status<T, W>(&self, content: &T, out: &mut W) -> Result<()>
        where T: Editable + Named,
              W: Write
    {
        let line = content.line();
        let column = content.col();
        let line_count = content.line_count();
        let advance = ((line + 1) as f64 / line_count as f64 * 100.0).floor();

        let (screen_width, _) = terminal_size().unwrap();
        let empty_line = (0..screen_width).map(|_| ' ').collect::<String>();
        let y = self.lines_height() as u16;

        write!(out,
               "{}{}{}{}{}{}",
               color::Fg(color::White),
               style::Invert,
               cursor::Goto(1, 1 + y),
               empty_line,
               cursor::Goto(1, 1 + y),
               content.name())?;

        let position_info = format!("{}% {}/{}: {}", advance, line + 1, line_count, column);
        let x = screen_width - position_info.len() as u16;
        write!(out,
               "{}{}{}",
               cursor::Goto(1 + x, 1 + y),
               position_info,
               style::Reset)?;
        Ok(())
    }

    fn paint_lines<T, W>(&self, content: &T, out: &mut W) -> Result<()>
        where T: Editable + Selectable,
              W: Write
    {
        let line_offset = self.line_offset as usize;
        let lines_height = self.lines_height() as usize;
        let lines_width = self.lines_width(content.line_count()) as usize;
        let line_count = content.line_count();

        let line_start = self.line_number_width(line_count) + 1;

        write!(out, "{}", cursor::Hide)?;

        for (y, line) in content
                .lines()
                .skip(line_offset)
                .take(cmp::min(lines_height, line_count))
                .enumerate() {
            // paint line number and initialize display for this line
            let line_index = line_offset + y;
            write!(out,
                   "{}{}{}{}{}{}",
                   cursor::Goto(1, 1 + y as u16),
                   clear::CurrentLine,
                   color::Fg(color::White),
                   1 + line_index, // the line number
                   style::Reset,
                   cursor::Goto(1 + line_start, 1 + y as u16))?;

            if line.char_count() > 0 {
                let line_start_char_index = content.line_index_to_char_index(line_index);
                for (x, c) in line.char_iter()
                        .flat_map(|c| if c == '\t' {
                                      iter::repeat(' ').take(TAB_LENGTH)
                                  } else {
                                      iter::repeat(c).take(1)
                                  })
                        .enumerate() {

                    let char_index = line_start_char_index + x;

                    if x < lines_width {
                        if content.in_sel(char_index) {
                            write!(out, "{}{}{}", style::Invert, c, style::Reset)?;
                        } else {
                            write!(out, "{}", c)?;
                        }
                    }
                }
            } else if content.line_in_sel(line_offset + y) {
                write!(out,
                       "{}{} {}",
                       clear::CurrentLine,
                       style::Invert,
                       style::Reset)?;
            }
        }
        write!(out, "{}{}", clear::AfterCursor, cursor::Show)?;
        Ok(())
    }

    fn cursor_pos<T: Editable>(&self, content: &T) -> (usize, usize) {
        // TODO: column offsetting for long lines
        let line = content.line();
        let first_line = self.line_offset;
        let y = line - first_line as usize;
        // we can't trust the actual column because tabs have variable length
        let visual_col = content.col();
        let column = content
            .iter_line(line)
            .map(|x| if x == '\t' { TAB_LENGTH } else { 1 })
            .take(visual_col)
            .fold(0, |acc, x| acc + x);
        ((self.line_number_width(content.line_count()) as usize + 1 + column), y)
    }

    fn line_number_width(&self, line_count: usize) -> u16 {
        line_count.to_string().len() as u16
    }

    fn status_height(&self) -> u16 {
        2
    }

    pub fn lines_height(&self) -> u16 {
        let (_, screen_height) = terminal_size().unwrap();
        let incompressible = self.status_height();
        cmp::max(screen_height, incompressible) - incompressible
    }

    pub fn lines_width(&self, line_count: usize) -> u16 {
        let (screen_width, _) = terminal_size().unwrap();
        let incompressible = self.line_number_width(line_count) + 1;
        cmp::max(screen_width, incompressible) - incompressible
    }
}
<|endoftext|>


<commit_before>// Rust Bitcoin Library
// Written in 2014 by
//     Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Network message
//!
//! This module defines the `Message` traits which are used
//! for (de)serializing Bitcoin objects for transmission on the network. It
//! also defines (de)serialization routines for many primitives.
//!

use std::iter;
use std::io::Cursor;
use std::sync::mpsc::Sender;

use blockdata::block;
use blockdata::transaction;
use network::address::Address;
use network::message_network;
use network::message_blockdata;
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::encodable::CheckedData;
use network::serialize::{serialize, RawDecoder, SimpleEncoder, SimpleDecoder};
use util::{self, propagate_err};

/// Serializer for command string
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CommandString(pub String);

impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
    #[inline]
    fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
        let &CommandString(ref inner_str) = self;
        let mut rawbytes = [0u8; 12];
        let strbytes = inner_str.as_bytes();
        if strbytes.len() > 12 {
            panic!("Command string longer than 12 bytes");
        }
        for x in 0..strbytes.len() {
            rawbytes[x] = strbytes[x];
        }
        rawbytes.consensus_encode(s)
    }
}

impl<D: SimpleDecoder> ConsensusDecodable<D> for CommandString {
    #[inline]
    fn consensus_decode(d: &mut D) -> Result<CommandString, D::Error> {
        let rawbytes: [u8; 12] = try!(ConsensusDecodable::consensus_decode(d));
        let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
        Ok(CommandString(rv))
    }
}

/// A Network message
pub struct RawNetworkMessage {
    /// Magic bytes to identify the network these messages are meant for
    pub magic: u32,
    /// The actual message data
    pub payload: NetworkMessage
}

/// A response from the peer-connected socket
pub enum SocketResponse {
    /// A message was received
    MessageReceived(NetworkMessage),
    /// An error occured and the socket needs to close
    ConnectionFailed(util::Error, Sender<()>)
}

#[derive(Clone, PartialEq, Eq, Debug)]
/// A Network message payload. Proper documentation is available on at
/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
pub enum NetworkMessage {
    /// `version`
    Version(message_network::VersionMessage),
    /// `verack`
    Verack,
    /// `addr`
    Addr(Vec<(u32, Address)>),
    /// `inv`
    Inv(Vec<message_blockdata::Inventory>),
    /// `getdata`
    GetData(Vec<message_blockdata::Inventory>),
    /// `notfound`
    NotFound(Vec<message_blockdata::Inventory>),
    /// `getblocks`
    GetBlocks(message_blockdata::GetBlocksMessage),
    /// `getheaders`
    GetHeaders(message_blockdata::GetHeadersMessage),
    /// `mempool`
    MemPool,
    /// tx
    Tx(transaction::Transaction),
    /// `block`
    Block(block::Block),
    /// `headers`
    Headers(Vec<block::LoneBlockHeader>),
    /// `getaddr`
    GetAddr,
    // TODO: checkorder,
    // TODO: submitorder,
    // TODO: reply,
    /// `ping`
    Ping(u64),
    /// `pong`
    Pong(u64),
    // TODO: reject,
    // TODO: bloom filtering
    // TODO: alert
    /// `alert`
    Alert(Vec<u8>)
}

impl RawNetworkMessage {
    pub fn command(&self) -> String {
        match self.payload {
            NetworkMessage::Version(_) => "version",
            NetworkMessage::Verack     => "verack",
            NetworkMessage::Addr(_)    => "addr",
            NetworkMessage::Inv(_)     => "inv",
            NetworkMessage::GetData(_) => "getdata",
            NetworkMessage::NotFound(_) => "notfound",
            NetworkMessage::GetBlocks(_) => "getblocks",
            NetworkMessage::GetHeaders(_) => "getheaders",
            NetworkMessage::MemPool    => "mempool",
            NetworkMessage::Tx(_)      => "tx",
            NetworkMessage::Block(_)   => "block",
            NetworkMessage::Headers(_) => "headers",
            NetworkMessage::GetAddr    => "getaddr",
            NetworkMessage::Ping(_)    => "ping",
            NetworkMessage::Pong(_)    => "pong",
            NetworkMessage::Alert(_)    => "alert",
        }.to_owned()
    }
}

impl<S: SimpleEncoder> ConsensusEncodable<S> for RawNetworkMessage {
    fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
        try!(self.magic.consensus_encode(s));
        try!(CommandString(self.command()).consensus_encode(s));
        try!(CheckedData(match self.payload {
            NetworkMessage::Version(ref dat) => serialize(dat),
            NetworkMessage::Verack           => Ok(vec![]),
            NetworkMessage::Addr(ref dat)    => serialize(dat),
            NetworkMessage::Inv(ref dat)     => serialize(dat),
            NetworkMessage::GetData(ref dat) => serialize(dat),
            NetworkMessage::NotFound(ref dat) => serialize(dat),
            NetworkMessage::GetBlocks(ref dat) => serialize(dat),
            NetworkMessage::GetHeaders(ref dat) => serialize(dat),
            NetworkMessage::MemPool          => Ok(vec![]),
            NetworkMessage::Tx(ref dat)      => serialize(dat),
            NetworkMessage::Block(ref dat)   => serialize(dat),
            NetworkMessage::Headers(ref dat) => serialize(dat),
            NetworkMessage::GetAddr          => Ok(vec![]),
            NetworkMessage::Ping(ref dat)    => serialize(dat),
            NetworkMessage::Pong(ref dat)    => serialize(dat),
            NetworkMessage::Alert(ref dat)    => serialize(dat)
        }.unwrap()).consensus_encode(s));
        Ok(())
    }
}

// TODO: restriction on D::Error is so that `propagate_err` will work;
//       is there a more generic way to handle this?
impl<D: SimpleDecoder<Error=util::Error>> ConsensusDecodable<D> for RawNetworkMessage {
    fn consensus_decode(d: &mut D) -> Result<RawNetworkMessage, D::Error> {
        let magic = try!(ConsensusDecodable::consensus_decode(d));
        let CommandString(cmd): CommandString= try!(ConsensusDecodable::consensus_decode(d));
        let CheckedData(raw_payload): CheckedData = try!(ConsensusDecodable::consensus_decode(d));

        let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
        let payload = match &cmd[..] {
            "version" => NetworkMessage::Version(try!(propagate_err("version".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "verack"  => NetworkMessage::Verack,
            "addr"    => NetworkMessage::Addr(try!(propagate_err("addr".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "inv"     => NetworkMessage::Inv(try!(propagate_err("inv".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getdata" => NetworkMessage::GetData(try!(propagate_err("getdata".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "notfound" => NetworkMessage::NotFound(try!(propagate_err("notfound".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getblocks" => NetworkMessage::GetBlocks(try!(propagate_err("getblocks".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getheaders" => NetworkMessage::GetHeaders(try!(propagate_err("getheaders".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "mempool" => NetworkMessage::MemPool,
            "block"   => NetworkMessage::Block(try!(propagate_err("block".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "headers" => NetworkMessage::Headers(try!(propagate_err("headers".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getaddr" => NetworkMessage::GetAddr,
            "ping"    => NetworkMessage::Ping(try!(propagate_err("ping".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "pong"    => NetworkMessage::Pong(try!(propagate_err("pong".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "tx"      => NetworkMessage::Tx(try!(propagate_err("tx".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "alert"   => NetworkMessage::Alert(try!(propagate_err("alert".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            cmd => return Err(d.error(format!("unrecognized network command `{}`", cmd)))
        };
        Ok(RawNetworkMessage {
            magic: magic,
            payload: payload
        })
    }
}

#[cfg(test)]
mod test {
    use super::{RawNetworkMessage, NetworkMessage, CommandString};

    use network::serialize::{deserialize, serialize};

    #[test]
    fn serialize_commandstring_test() {
        let cs = CommandString("Andrew".to_owned());
        assert_eq!(serialize(&cs).ok(), Some(vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]));
    }

    #[test]
    fn deserialize_commandstring_test() {
        let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
        assert!(cs.is_ok());
        assert_eq!(cs.unwrap(), CommandString("Andrew".to_owned()));

        let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
        assert!(short_cs.is_err());
    }

    #[test]
    fn serialize_verack_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Verack }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61,
                                       0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]));
    }

    #[test]
    fn serialize_ping_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Ping(100) }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67,
                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d,
                                       0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
    }

    #[test]
    fn serialize_mempool_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::MemPool }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70,
                                       0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]));
    }

    #[test]
    fn serialize_getaddr_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::GetAddr }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
                                       0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]));
    }

}
<commit_msg>add documentation<commit_after>// Rust Bitcoin Library
// Written in 2014 by
//     Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Network message
//!
//! This module defines the `Message` traits which are used
//! for (de)serializing Bitcoin objects for transmission on the network. It
//! also defines (de)serialization routines for many primitives.
//!

use std::iter;
use std::io::Cursor;
use std::sync::mpsc::Sender;

use blockdata::block;
use blockdata::transaction;
use network::address::Address;
use network::message_network;
use network::message_blockdata;
use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::encodable::CheckedData;
use network::serialize::{serialize, RawDecoder, SimpleEncoder, SimpleDecoder};
use util::{self, propagate_err};

/// Serializer for command string
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct CommandString(pub String);

impl<S: SimpleEncoder> ConsensusEncodable<S> for CommandString {
    #[inline]
    fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
        let &CommandString(ref inner_str) = self;
        let mut rawbytes = [0u8; 12];
        let strbytes = inner_str.as_bytes();
        if strbytes.len() > 12 {
            panic!("Command string longer than 12 bytes");
        }
        for x in 0..strbytes.len() {
            rawbytes[x] = strbytes[x];
        }
        rawbytes.consensus_encode(s)
    }
}

impl<D: SimpleDecoder> ConsensusDecodable<D> for CommandString {
    #[inline]
    fn consensus_decode(d: &mut D) -> Result<CommandString, D::Error> {
        let rawbytes: [u8; 12] = try!(ConsensusDecodable::consensus_decode(d));
        let rv = iter::FromIterator::from_iter(rawbytes.iter().filter_map(|&u| if u > 0 { Some(u as char) } else { None }));
        Ok(CommandString(rv))
    }
}

/// A Network message
pub struct RawNetworkMessage {
    /// Magic bytes to identify the network these messages are meant for
    pub magic: u32,
    /// The actual message data
    pub payload: NetworkMessage
}

/// A response from the peer-connected socket
pub enum SocketResponse {
    /// A message was received
    MessageReceived(NetworkMessage),
    /// An error occured and the socket needs to close
    ConnectionFailed(util::Error, Sender<()>)
}

#[derive(Clone, PartialEq, Eq, Debug)]
/// A Network message payload. Proper documentation is available on at
/// [Bitcoin Wiki: Protocol Specification](https://en.bitcoin.it/wiki/Protocol_specification)
pub enum NetworkMessage {
    /// `version`
    Version(message_network::VersionMessage),
    /// `verack`
    Verack,
    /// `addr`
    Addr(Vec<(u32, Address)>),
    /// `inv`
    Inv(Vec<message_blockdata::Inventory>),
    /// `getdata`
    GetData(Vec<message_blockdata::Inventory>),
    /// `notfound`
    NotFound(Vec<message_blockdata::Inventory>),
    /// `getblocks`
    GetBlocks(message_blockdata::GetBlocksMessage),
    /// `getheaders`
    GetHeaders(message_blockdata::GetHeadersMessage),
    /// `mempool`
    MemPool,
    /// tx
    Tx(transaction::Transaction),
    /// `block`
    Block(block::Block),
    /// `headers`
    Headers(Vec<block::LoneBlockHeader>),
    /// `getaddr`
    GetAddr,
    // TODO: checkorder,
    // TODO: submitorder,
    // TODO: reply,
    /// `ping`
    Ping(u64),
    /// `pong`
    Pong(u64),
    // TODO: reject,
    // TODO: bloom filtering
    // TODO: alert
    /// `alert`
    Alert(Vec<u8>)
}

impl RawNetworkMessage {
    /// Return the message command. This is useful for debug outputs.
    pub fn command(&self) -> String {
        match self.payload {
            NetworkMessage::Version(_) => "version",
            NetworkMessage::Verack     => "verack",
            NetworkMessage::Addr(_)    => "addr",
            NetworkMessage::Inv(_)     => "inv",
            NetworkMessage::GetData(_) => "getdata",
            NetworkMessage::NotFound(_) => "notfound",
            NetworkMessage::GetBlocks(_) => "getblocks",
            NetworkMessage::GetHeaders(_) => "getheaders",
            NetworkMessage::MemPool    => "mempool",
            NetworkMessage::Tx(_)      => "tx",
            NetworkMessage::Block(_)   => "block",
            NetworkMessage::Headers(_) => "headers",
            NetworkMessage::GetAddr    => "getaddr",
            NetworkMessage::Ping(_)    => "ping",
            NetworkMessage::Pong(_)    => "pong",
            NetworkMessage::Alert(_)    => "alert",
        }.to_owned()
    }
}

impl<S: SimpleEncoder> ConsensusEncodable<S> for RawNetworkMessage {
    fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
        try!(self.magic.consensus_encode(s));
        try!(CommandString(self.command()).consensus_encode(s));
        try!(CheckedData(match self.payload {
            NetworkMessage::Version(ref dat) => serialize(dat),
            NetworkMessage::Verack           => Ok(vec![]),
            NetworkMessage::Addr(ref dat)    => serialize(dat),
            NetworkMessage::Inv(ref dat)     => serialize(dat),
            NetworkMessage::GetData(ref dat) => serialize(dat),
            NetworkMessage::NotFound(ref dat) => serialize(dat),
            NetworkMessage::GetBlocks(ref dat) => serialize(dat),
            NetworkMessage::GetHeaders(ref dat) => serialize(dat),
            NetworkMessage::MemPool          => Ok(vec![]),
            NetworkMessage::Tx(ref dat)      => serialize(dat),
            NetworkMessage::Block(ref dat)   => serialize(dat),
            NetworkMessage::Headers(ref dat) => serialize(dat),
            NetworkMessage::GetAddr          => Ok(vec![]),
            NetworkMessage::Ping(ref dat)    => serialize(dat),
            NetworkMessage::Pong(ref dat)    => serialize(dat),
            NetworkMessage::Alert(ref dat)    => serialize(dat)
        }.unwrap()).consensus_encode(s));
        Ok(())
    }
}

// TODO: restriction on D::Error is so that `propagate_err` will work;
//       is there a more generic way to handle this?
impl<D: SimpleDecoder<Error=util::Error>> ConsensusDecodable<D> for RawNetworkMessage {
    fn consensus_decode(d: &mut D) -> Result<RawNetworkMessage, D::Error> {
        let magic = try!(ConsensusDecodable::consensus_decode(d));
        let CommandString(cmd): CommandString= try!(ConsensusDecodable::consensus_decode(d));
        let CheckedData(raw_payload): CheckedData = try!(ConsensusDecodable::consensus_decode(d));

        let mut mem_d = RawDecoder::new(Cursor::new(raw_payload));
        let payload = match &cmd[..] {
            "version" => NetworkMessage::Version(try!(propagate_err("version".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "verack"  => NetworkMessage::Verack,
            "addr"    => NetworkMessage::Addr(try!(propagate_err("addr".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "inv"     => NetworkMessage::Inv(try!(propagate_err("inv".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getdata" => NetworkMessage::GetData(try!(propagate_err("getdata".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "notfound" => NetworkMessage::NotFound(try!(propagate_err("notfound".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getblocks" => NetworkMessage::GetBlocks(try!(propagate_err("getblocks".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getheaders" => NetworkMessage::GetHeaders(try!(propagate_err("getheaders".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "mempool" => NetworkMessage::MemPool,
            "block"   => NetworkMessage::Block(try!(propagate_err("block".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "headers" => NetworkMessage::Headers(try!(propagate_err("headers".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "getaddr" => NetworkMessage::GetAddr,
            "ping"    => NetworkMessage::Ping(try!(propagate_err("ping".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "pong"    => NetworkMessage::Pong(try!(propagate_err("pong".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "tx"      => NetworkMessage::Tx(try!(propagate_err("tx".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            "alert"   => NetworkMessage::Alert(try!(propagate_err("alert".to_owned(), ConsensusDecodable::consensus_decode(&mut mem_d)))),
            cmd => return Err(d.error(format!("unrecognized network command `{}`", cmd)))
        };
        Ok(RawNetworkMessage {
            magic: magic,
            payload: payload
        })
    }
}

#[cfg(test)]
mod test {
    use super::{RawNetworkMessage, NetworkMessage, CommandString};

    use network::serialize::{deserialize, serialize};

    #[test]
    fn serialize_commandstring_test() {
        let cs = CommandString("Andrew".to_owned());
        assert_eq!(serialize(&cs).ok(), Some(vec![0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]));
    }

    #[test]
    fn deserialize_commandstring_test() {
        let cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0, 0]);
        assert!(cs.is_ok());
        assert_eq!(cs.unwrap(), CommandString("Andrew".to_owned()));

        let short_cs: Result<CommandString, _> = deserialize(&[0x41u8, 0x6e, 0x64, 0x72, 0x65, 0x77, 0, 0, 0, 0, 0]);
        assert!(short_cs.is_err());
    }

    #[test]
    fn serialize_verack_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Verack }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x76, 0x65, 0x72, 0x61,
                                       0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]));
    }

    #[test]
    fn serialize_ping_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::Ping(100) }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x70, 0x69, 0x6e, 0x67,
                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d,
                                       0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
    }

    #[test]
    fn serialize_mempool_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::MemPool }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x6d, 0x65, 0x6d, 0x70,
                                       0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]));
    }

    #[test]
    fn serialize_getaddr_test() {
        assert_eq!(serialize(&RawNetworkMessage { magic: 0xd9b4bef9, payload: NetworkMessage::GetAddr }).ok(),
                             Some(vec![0xf9, 0xbe, 0xb4, 0xd9, 0x67, 0x65, 0x74, 0x61,
                                       0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
                                       0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]));
    }

}
<|endoftext|>


<commit_before>use std::io::{self,ErrorKind,Read,Write};
use std::net::{SocketAddr,SocketAddrV4,SocketAddrV6};
use mio::tcp::{TcpListener,TcpStream};
use rustls::{ServerSession, Session};
use net2::TcpBuilder;
use net2::unix::UnixTcpBuilderExt;
#[cfg(feature = "use-openssl")]
use openssl::ssl::{Error, ErrorCode, SslStream};

#[derive(Debug,PartialEq,Copy,Clone)]
pub enum SocketResult {
  Continue,
  Closed,
  WouldBlock,
  Error
}

pub trait SocketHandler {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult);
  fn socket_write(&mut self, buf: &[u8])    -> (usize, SocketResult);
  fn socket_ref(&self) -> &TcpStream;
}

impl SocketHandler for TcpStream {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            error!("SOCKET\tsocket_read error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            //FIXME: timeout and other common errors should be sent up
            error!("SOCKET\tsocket_write error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self }
}

#[cfg(feature = "use-openssl")]
impl SocketHandler for SslStream<TcpStream> {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              error!("SOCKET-TLS\treadable TLS socket err");
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            _ => return (size, SocketResult::Error)
          }
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              error!("SOCKET-TLS\twritable TLS socket err");
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            err => {
              error!("SOCKET-TLS\twritable TLS socket err={:?}", err);
              return (size, SocketResult::Error)
            }
          }
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self.get_ref() }
}

pub struct FrontRustls {
  pub stream:  TcpStream,
  pub session: ServerSession,
}

impl SocketHandler for FrontRustls {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size      = 0usize;
    let mut can_read  = true;
    let mut is_error  = false;
    let mut is_closed = false;

    loop {
      if size == buf.len() {
        break;
      }

      if !can_read | is_error | is_closed {
        break;
      }

      match self.session.read_tls(&mut self.stream) {
        Ok(0)  => can_read = false,
        Ok(sz) => {},
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            can_read = false;
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            is_closed = true;
          },
          _ => {
            error!("could not read TLS stream from socket: {:?}", e);
            is_error = true;
            break;
           }
        }
      }

      if let Err(e) = self.session.process_new_packets() {
        error!("could not process read TLS packets: {:?}", e);
        is_error = true;
        break;
      }

      while !self.session.wants_read() {
        match self.session.read(&mut buf[size..]) {
          Ok(sz) => size += sz,
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => {
              break;
            },
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not read data from TLS stream: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    if is_error {
      (size, SocketResult::Error)
    } else if is_closed {
      (size, SocketResult::Closed)
    } else if !can_read {
      (size, SocketResult::WouldBlock)
    } else {
      (size, SocketResult::Continue)
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut buffered_size = 0usize;
    let mut sent_size     = 0usize;
    let mut can_write     = true;
    let mut is_error      = false;
    let mut is_closed     = false;

    loop {
      if buffered_size == buf.len() {
        break;
      }

      if !can_write | is_error | is_closed {
        break;
      }

      match self.session.write(&buf[buffered_size..]) {
        Ok(0)  => {
          break;
        },
        Ok(sz) => {
          buffered_size += sz;
        },
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            // we don't need to do anything, the session will return false in wants_write?
            //error!("rustls socket_write wouldblock");
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            //FIXME: this should probably not happen here
            is_closed = true;
            break;
          },
          _ => {
            error!("could not write data to TLS stream: {:?}", e);
            is_error = true;
            break;
          }
        }
      }

      loop {
        match self.session.write_tls(&mut self.stream) {
          Ok(0)  => {
            can_write = false;
            break;
          },
          Ok(sz) => {
            sent_size += sz;
          },
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => can_write = false,
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not write TLS stream to socket: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    let res = if is_error {
      (buffered_size, SocketResult::Error)
    } else if is_closed {
      (buffered_size, SocketResult::Closed)
    } else if !can_write {
      (buffered_size, SocketResult::WouldBlock)
    } else {
      (buffered_size, SocketResult::Continue)
    };
    res
  }

  fn socket_ref(&self) -> &TcpStream { &self.stream }
}

pub fn server_bind(addr: &SocketAddr) -> io::Result<TcpListener> {
  let sock = try!(match *addr {
    SocketAddr::V4(..) => TcpBuilder::new_v4(),
    SocketAddr::V6(..) => TcpBuilder::new_v6(),
  });

  // set so_reuseaddr, but only on unix (mirrors what libstd does)
  if cfg!(unix) {
    try!(sock.reuse_address(true));
  }

  try!(sock.reuse_port(true));

  // bind the socket
  try!(sock.bind(addr));

  // listen
  // FIXME: make the backlog configurable?
  let listener = try!(sock.listen(1024));
  TcpListener::from_std(listener)
}

<commit_msg>0 bytes written to the TLS socket is not necessarily a WouldBlock error<commit_after>use std::io::{self,ErrorKind,Read,Write};
use std::net::{SocketAddr,SocketAddrV4,SocketAddrV6};
use mio::tcp::{TcpListener,TcpStream};
use rustls::{ServerSession, Session};
use net2::TcpBuilder;
use net2::unix::UnixTcpBuilderExt;
#[cfg(feature = "use-openssl")]
use openssl::ssl::{Error, ErrorCode, SslStream};

#[derive(Debug,PartialEq,Copy,Clone)]
pub enum SocketResult {
  Continue,
  Closed,
  WouldBlock,
  Error
}

pub trait SocketHandler {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult);
  fn socket_write(&mut self, buf: &[u8])    -> (usize, SocketResult);
  fn socket_ref(&self) -> &TcpStream;
}

impl SocketHandler for TcpStream {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            error!("SOCKET\tsocket_read error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            return (size, SocketResult::Closed)
          },
          _ => {
            //FIXME: timeout and other common errors should be sent up
            error!("SOCKET\tsocket_write error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self }
}

#[cfg(feature = "use-openssl")]
impl SocketHandler for SslStream<TcpStream> {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              error!("SOCKET-TLS\treadable TLS socket err");
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            _ => return (size, SocketResult::Error)
          }
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => {
          match e.code() {
            ErrorCode::WANT_READ  => return (size, SocketResult::WouldBlock),
            ErrorCode::WANT_WRITE => return (size, SocketResult::WouldBlock),
            ErrorCode::SSL        => {
              error!("SOCKET-TLS\twritable TLS socket err");
              return (size, SocketResult::Error)
            },
            ErrorCode::ZERO_RETURN => {
              return (size, SocketResult::Closed)
            },
            err => {
              error!("SOCKET-TLS\twritable TLS socket err={:?}", err);
              return (size, SocketResult::Error)
            }
          }
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self.get_ref() }
}

pub struct FrontRustls {
  pub stream:  TcpStream,
  pub session: ServerSession,
}

impl SocketHandler for FrontRustls {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size      = 0usize;
    let mut can_read  = true;
    let mut is_error  = false;
    let mut is_closed = false;

    loop {
      if size == buf.len() {
        break;
      }

      if !can_read | is_error | is_closed {
        break;
      }

      match self.session.read_tls(&mut self.stream) {
        Ok(0)  => can_read = false,
        Ok(sz) => {},
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            can_read = false;
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            is_closed = true;
          },
          _ => {
            error!("could not read TLS stream from socket: {:?}", e);
            is_error = true;
            break;
           }
        }
      }

      if let Err(e) = self.session.process_new_packets() {
        error!("could not process read TLS packets: {:?}", e);
        is_error = true;
        break;
      }

      while !self.session.wants_read() {
        match self.session.read(&mut buf[size..]) {
          Ok(sz) => size += sz,
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => {
              break;
            },
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not read data from TLS stream: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    if is_error {
      (size, SocketResult::Error)
    } else if is_closed {
      (size, SocketResult::Closed)
    } else if !can_read {
      (size, SocketResult::WouldBlock)
    } else {
      (size, SocketResult::Continue)
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut buffered_size = 0usize;
    let mut sent_size     = 0usize;
    let mut can_write     = true;
    let mut is_error      = false;
    let mut is_closed     = false;

    loop {
      if buffered_size == buf.len() {
        break;
      }

      if !can_write | is_error | is_closed {
        break;
      }

      match self.session.write(&buf[buffered_size..]) {
        Ok(0)  => {
          break;
        },
        Ok(sz) => {
          buffered_size += sz;
        },
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            // we don't need to do anything, the session will return false in wants_write?
            //error!("rustls socket_write wouldblock");
          },
          ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
            //FIXME: this should probably not happen here
            is_closed = true;
            break;
          },
          _ => {
            error!("could not write data to TLS stream: {:?}", e);
            is_error = true;
            break;
          }
        }
      }

      loop {
        match self.session.write_tls(&mut self.stream) {
          Ok(0)  => {
            //can_write = false;
            break;
          },
          Ok(sz) => {
            sent_size += sz;
          },
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => can_write = false,
            ErrorKind::ConnectionReset | ErrorKind::ConnectionAborted | ErrorKind::BrokenPipe => {
              is_closed = true;
              break;
            },
            _ => {
              error!("could not write TLS stream to socket: {:?}", e);
              is_error = true;
              break;
            }
          }
        }
      }
    }

    let res = if is_error {
      (buffered_size, SocketResult::Error)
    } else if is_closed {
      (buffered_size, SocketResult::Closed)
    } else if !can_write {
      (buffered_size, SocketResult::WouldBlock)
    } else {
      (buffered_size, SocketResult::Continue)
    };
    res
  }

  fn socket_ref(&self) -> &TcpStream { &self.stream }
}

pub fn server_bind(addr: &SocketAddr) -> io::Result<TcpListener> {
  let sock = try!(match *addr {
    SocketAddr::V4(..) => TcpBuilder::new_v4(),
    SocketAddr::V6(..) => TcpBuilder::new_v6(),
  });

  // set so_reuseaddr, but only on unix (mirrors what libstd does)
  if cfg!(unix) {
    try!(sock.reuse_address(true));
  }

  try!(sock.reuse_port(true));

  // bind the socket
  try!(sock.bind(addr));

  // listen
  // FIXME: make the backlog configurable?
  let listener = try!(sock.listen(1024));
  TcpListener::from_std(listener)
}

<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;
use structopt::StructOpt;

fn part1(input: &[isize]) -> isize {
    input.iter().map(|val| val / 3 - 2).sum()
}

fn main() {
    let handle = File::open(Opt::from_args().input).expect("error opening file");
    let input: Vec<_> = BufReader::new(handle)
        .lines()
        .map(|line| line.expect("error reading input"))
        .map(|line| {
            line.parse::<isize>()
                .unwrap_or_else(|err| panic!("could not parse line \"{}\": {:?}", line, err))
        })
        .collect();
    println!("Part 1: {}", part1(&input));
}

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}
<commit_msg>2019 day 01 part 2<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;
use structopt::StructOpt;

fn part1(input: &[isize]) -> isize {
    input.iter().map(|val| val / 3 - 2).sum()
}

fn extra_fuel(mass: isize) -> isize {
    let mut total = 0;
    let mut remainder = mass;
    loop {
        remainder = remainder / 3 - 2;
        if remainder > 0 {
            total += remainder;
        } else {
            break;
        }
    }
    total
}

fn part2(input: &[isize]) -> isize {
    input
        .iter()
        .map(|val| val / 3 - 2)
        .map(|mass| mass + extra_fuel(mass))
        .sum()
}

fn main() {
    let handle = File::open(Opt::from_args().input).expect("error opening file");
    let input: Vec<_> = BufReader::new(handle)
        .lines()
        .map(|line| line.expect("error reading input"))
        .map(|line| {
            line.parse::<isize>()
                .unwrap_or_else(|err| panic!("could not parse line \"{}\": {:?}", line, err))
        })
        .collect();
    println!("Part 1: {}", part1(&input));
    println!("Part 2: {}", part2(&input));
}

#[derive(StructOpt)]
struct Opt {
    #[structopt(parse(from_os_str))]
    input: PathBuf,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_part2() {
        let expected = vec![(14, 2), (1969, 966), (100756, 50346)];
        for (input, output) in expected {
            assert_eq!(extra_fuel(input), output);
        }
    }
}
<|endoftext|>


<commit_before>// Example of how to monitor card & card reader state changes.

extern crate pcsc;

use pcsc::*;

fn main() {
    let ctx = Context::establish(Scope::User).expect("failed to establish context");

    let mut readers_buf = [0; 2048];
    let mut reader_states = vec![
        // Listen for reader insertions/removals.
        ReaderState::new(PNP_NOTIFICATION(), STATE_UNAWARE),
    ];
    loop {
        // Remove dead readers.
        fn is_dead(rs: &ReaderState) -> bool {
            rs.event_state().intersects(STATE_UNKNOWN | STATE_IGNORE)
        }
        for rs in &reader_states {
            if is_dead(rs) {
                println!("Removing {:?}", rs.name());
            }
        }
        reader_states.retain(|rs| !is_dead(rs));

        // Add new readers.
        let names = ctx.list_readers(&mut readers_buf).expect("failed to list readers");
        for name in names {
            if !reader_states[1..].iter().any(|rs| rs.name() == name) {
                println!("Adding {:?}", name);
                reader_states.push(ReaderState::new(name, STATE_UNAWARE));
            }
        }

        // Update the view of the state to wait on.
        for rs in &mut reader_states {
            rs.sync_current_state();
        }

        // Wait until the state changes.
        ctx.get_status_change(None, &mut reader_states).expect("failed to get status change");

        // Print current state.
        println!();
        for rs in &reader_states[1..] {
            println!("{:?} {:?}", rs.name(), rs.event_state());
        }
    }
}
<commit_msg>Fix panics in the monitor example if PNP_NOTIFICATION is not supported<commit_after>// Example of how to monitor card & card reader state changes.

extern crate pcsc;

use pcsc::*;

fn main() {
    let ctx = Context::establish(Scope::User).expect("failed to establish context");

    let mut readers_buf = [0; 2048];
    let mut reader_states = vec![
        // Listen for reader insertions/removals, if supported.
        ReaderState::new(PNP_NOTIFICATION(), STATE_UNAWARE),
    ];
    loop {
        // Remove dead readers.
        fn is_dead(rs: &ReaderState) -> bool {
            rs.event_state().intersects(STATE_UNKNOWN | STATE_IGNORE)
        }
        for rs in &reader_states {
            if is_dead(rs) {
                println!("Removing {:?}", rs.name());
            }
        }
        reader_states.retain(|rs| !is_dead(rs));

        // Add new readers.
        let names = ctx.list_readers(&mut readers_buf).expect("failed to list readers");
        for name in names {
            if !reader_states.iter().any(|rs| rs.name() == name) {
                println!("Adding {:?}", name);
                reader_states.push(ReaderState::new(name, STATE_UNAWARE));
            }
        }

        // Update the view of the state to wait on.
        for rs in &mut reader_states {
            rs.sync_current_state();
        }

        // Wait until the state changes.
        ctx.get_status_change(None, &mut reader_states).expect("failed to get status change");

        // Print current state.
        println!();
        for rs in &reader_states {
            if rs.name() != PNP_NOTIFICATION() {
                println!("{:?} {:?}", rs.name(), rs.event_state());
            }
        }
    }
}
<|endoftext|>


<commit_before>
use sound_stream_settings::SoundStreamSettings;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Formatter;
use std::fmt::Result;
use std::fmt::Show;

/* /// The mixer input for handling volume and
/// panning of incoming audio from inputs.
#[deriving(Clone)]
pub struct MixerInput {
    node: Rc<RefCell<Node>>,
    vol: f32,
    pan: f32,
} */

/// Need to explicitly implement Show due to
/// Rc pointer.
impl<T: Node> Show for MixerInput<T> {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "node: {}, vol: {}, pan{}",
               self.node.borrow_mut().get_node_data(), self.vol, self.pan)
    }
}

impl<T: Node> MixerInput<T> {
    /// Constructor for a Mixer Input.
    pub fn new(node: Rc<RefCell<T>>) -> MixerInput<T> {
        MixerInput {
            node: node,
            vol: 1f32,
            pan: 0f32
        }
    }
}

/// The DSP Node contains a vector of children
/// nodes (within the `MixerInput`s), from which
/// audio can be requested as well as the current
/// SoundStream settings.
#[deriving(Show, Clone)]
pub struct NodeData {
    /// SoundStreamSettings for buffer calculations.
    pub settings: SoundStreamSettings,
    /// Master volume for DSP node.
    pub vol: f32,
    /// Panning for DSP node.
    pub pan: f32
}

/// DSP Node trait. Implement this for any audio
/// instrument or effects types. Be sure to add
/// the `Node` struct to a field as well, and
/// override the `get_node` and `get_node_mut`
/// methods by returning a ref (/mut) to it.
pub trait Node: Clone {

    /// Return a reference a NodeData struct owned by the Node.
    fn get_node_data<'a>(&'a mut self) -> &'a mut NodeData;
    /// Return a reference to the inputs for the Node.
    fn get_inputs<'a>(&'a self) -> Vec<&MixerInput> { Vec::new() }
    /// Return a mutable reference to the inputs for the Node.
    fn get_inputs_mut<'a>(&'a mut self) -> Vec<&mut MixerInput> { Vec::new() }

    /// Apply settings to self and all inputs.
    fn apply_settings<T: Node>(&mut self, settings: SoundStreamSettings) {
        match self.get_inputs::<T>() {
            Some(inputs) => {
                for input in inputs.iter() {
                    input.node.borrow_mut().apply_settings::<T>(settings);
                }
            },
            None => ()
        }
        self.get_node_data().settings = settings;
    }

    /// Add a new input.
    fn add_input<T: Node>(&mut self, input: Rc<RefCell<T>>) {
        match self.get_inputs_mut::<T>() {
            Some(inputs) => inputs.push(MixerInput::new(input)),
            None => ()
        }
    }

    /// Remove an input. Find the input by comparing
    /// the address of the given input to each of the
    /// inputs' addresses.
    fn remove_input<T: Node>(&mut self, to_remove: &Rc<RefCell<T>>) {
        match self.get_inputs_mut::<T>() {
            Some(inputs) => {
                for i in range(0, inputs.len()) {
                    if &(*inputs.get(i).node.borrow()) as *_ ==
                        &(*to_remove.borrow()) as *_ {
                        inputs.remove(i);
                        break;
                    }
                }
            },
            None => ()
        }
    }

    /// Remove all inputs from the `inputs` vector.
    fn remove_all_inputs<T: Node>(&mut self) {
        match self.get_inputs_mut::<T>() {
            Some(inputs) => inputs.clear(),
            None => ()
        }
    }

    /// Add all inputs held by another node.
    fn add_inputs_from<T: Node>(&mut self, other: &Rc<RefCell<T>>) {
        match self.get_inputs_mut::<T>() {
            Some(inputs) => {
                match other.borrow().get_inputs::<T>() {
                    Some(other_inputs) => inputs.push_all(other_inputs.as_slice()),
                    None => ()
                }
            },
            None => ()
        }
    }

    /// Receive incoming audio (override this
    /// to do something with the input).
    fn audio_received(&mut self, _input: &Vec<f32>) {}

    /// Request audio from inputs, process and
    /// pass back to the output! Override this
    /// method for any synthesis or generative
    /// types.
    fn audio_requested<T: Node>(&mut self, output: &mut Vec<f32>) {
        let master_vol = self.get_node_data().master_vol;
        let frames = self.get_node_data().settings.frames as uint;
        let channels = self.get_node_data().settings.channels as uint;
        let mut vol_per_channel: Vec<f32> = Vec::from_elem(channels, 1f32);
        for i in range(0, self.get_inputs::<T>().len()) {
            let input = self.get_inputs::<T>().get(i);
            let mut working: Vec<f32> = Vec::from_elem((frames * channels) as uint, 0f32);
            // Call audio_requested for each input.
            input.node.borrow_mut().audio_requested::<T>(&mut working);
            // Construct precalculated volume and
            // pan array (for efficiency).
            let vol_l: f32 = input.vol * (1f32 - input.pan);
            let vol_r: f32 = input.vol * input.pan;
            for j in range(0, vol_per_channel.len()) {
                *vol_per_channel.get_mut(j) = if j == 0 { vol_l } else { vol_r } * master_vol;
            }
            // Sum all input nodes to output (considering
            // pan, vol and interleaving).
            for j in range(0, frames) {
                for k in range(0, channels) {
                    *output.get_mut(j * channels + k) +=
                        *working.get(j * channels + k) * *vol_per_channel.get(k);
                }
            }
        }
        // Custom buffer processing.
        self.process_buffer(output);
    }

    /// Override for custom processing of audio per
    /// buffer. This is mainly for audio effects. Get's
    /// called at the end of audio_requested.
    fn process_buffer(&mut self, _output: &mut Vec<f32>) {}

}

<commit_msg> minimized node trait, removed add/remove input functionality<commit_after>
use sound_stream_settings::SoundStreamSettings;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Formatter;
use std::fmt::Result;
use std::fmt::Show;

/// The DSP Node contains a vector of children
/// nodes (within the `MixerInput`s), from which
/// audio can be requested as well as the current
/// SoundStream settings.
#[deriving(Show, Clone)]
pub struct NodeData {
    /// SoundStreamSettings for buffer calculations.
    pub settings: SoundStreamSettings,
    /// Master volume for DSP node.
    pub vol: f32,
    /// Panning for DSP node.
    pub pan: f32
}

impl NodeData {
    /// Default constructor for a NodeData struct.
    pub fn new(settings: SoundStreamSettings) -> NodeData {
        NodeData {
            settings: settings,
            vol: 1f32,
            pan: 0f32,
        }
    }
}

/// DSP Node trait. Implement this for any audio
/// instrument or effects types. Be sure to add
/// the `Node` struct to a field as well, and
/// override the `get_node` and `get_node_mut`
/// methods by returning a ref (/mut) to it.
pub trait Node: Clone {

    /// Return a reference a NodeData struct owned by the Node.
    fn get_node_data<'a>(&'a mut self) -> &'a mut NodeData;
    /// Return a reference to the inputs for the Node.
    fn get_inputs<'a>(&'a self) -> Vec<&'a Node> { Vec::new() }
    /// Return a mutable reference to the inputs for the Node.
    fn get_inputs_mut<'a>(&'a mut self) -> Vec<&'a mut Node> { Vec::new() }

    /// Apply settings to self and all inputs.
    fn apply_settings(&mut self, settings: SoundStreamSettings) {
        for input in self.get_inputs_mut().iter() {
            input.node.borrow_mut().apply_settings(settings);
        }
        self.get_node_data().settings = settings;
    }

    /// Remove all inputs from the `inputs` vector.
    fn remove_all_inputs(&mut self) {
        self.get_inputs_mut().clear();
    }

    /// Receive incoming audio (override this
    /// to do something with the input).
    fn audio_received(&mut self, _input: &Vec<f32>) {}

    /// Request audio from inputs, process and
    /// pass back to the output! Override this
    /// method for any synthesis or generative
    /// types.
    fn audio_requested(&mut self, output: &mut Vec<f32>) {
        let master_vol = self.get_node_data().master_vol;
        let frames = self.get_node_data().settings.frames as uint;
        let channels = self.get_node_data().settings.channels as uint;
        let mut vol_per_channel: Vec<f32> = Vec::from_elem(channels, 1f32);
        for i in range(0, self.get_inputs().len()) {
            let input = self.get_inputs().get(i);
            let mut working: Vec<f32> = Vec::from_elem((frames * channels) as uint, 0f32);
            // Call audio_requested for each input.
            input.node.borrow_mut().audio_requested(&mut working);
            // Construct precalculated volume and
            // pan array (for efficiency).
            let vol_l: f32 = input.vol * (1f32 - input.pan);
            let vol_r: f32 = input.vol * input.pan;
            for j in range(0, vol_per_channel.len()) {
                *vol_per_channel.get_mut(j) = if j == 0 { vol_l } else { vol_r } * master_vol;
            }
            // Sum all input nodes to output (considering
            // pan, vol and interleaving).
            for j in range(0, frames) {
                for k in range(0, channels) {
                    *output.get_mut(j * channels + k) +=
                        *working.get(j * channels + k) * *vol_per_channel.get(k);
                }
            }
        }
        // Custom buffer processing.
        self.process_buffer(output);
    }

    /// Override for custom processing of audio per
    /// buffer. This is mainly for audio effects. Get's
    /// called at the end of audio_requested.
    fn process_buffer(&mut self, _output: &mut Vec<f32>) {}

}

<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// 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.

//! Traps and notifies UNIX signals.

use std::{collections::VecDeque,
          sync::{Mutex,
                 Once,
                 ONCE_INIT}};

use crate::os::process::{Signal,
                         SignalCode};

use super::SignalEvent;

static INIT: Once = ONCE_INIT;

lazy_static::lazy_static! {
    static ref CAUGHT_SIGNALS: Mutex<VecDeque<SignalCode>> = Mutex::new(VecDeque::new());
}

// Functions from POSIX libc.
extern "C" {
    fn signal(sig: SignalCode,
              cb: unsafe extern "C" fn(SignalCode))
              -> unsafe extern "C" fn(SignalCode);
}

unsafe extern "C" fn handle_signal(signal: SignalCode) {
    CAUGHT_SIGNALS.lock()
                  .expect("Signal mutex poisoned")
                  .push_back(signal);
}

pub fn init() {
    INIT.call_once(|| {
            self::set_signal_handlers();
        });
}

/// Consumers should call this function fairly frequently and since the vast
/// majority of the time there is at most one signal event waiting, we return
/// at most one. If multiple signals have been received since the last call,
/// they will be returned, one per call in the order they were received.
pub fn check_for_signal() -> Option<SignalEvent> {
    let mut signals = CAUGHT_SIGNALS.lock().expect("Signal mutex poisoned");

    if let Some(code) = signals.pop_front() {
        match from_signal_code(code) {
            Some(Signal::INT) | Some(Signal::TERM) => Some(SignalEvent::Shutdown),
            Some(Signal::CHLD) => Some(SignalEvent::WaitForChild),
            Some(signal) => Some(SignalEvent::Passthrough(signal)),
            None => {
                println!("Received invalid signal: #{}", code);
                None
            }
        }
    } else {
        None
    }
}

fn set_signal_handlers() {
    unsafe {
        signal(libc::SIGHUP, handle_signal);
        signal(libc::SIGINT, handle_signal);
        signal(libc::SIGQUIT, handle_signal);
        signal(libc::SIGALRM, handle_signal);
        signal(libc::SIGTERM, handle_signal);
        signal(libc::SIGUSR1, handle_signal);
        signal(libc::SIGUSR2, handle_signal);
        signal(libc::SIGCHLD, handle_signal);
    }
}

/// These are the signals that we can eventually translate into
/// some kind of event
fn from_signal_code(code: SignalCode) -> Option<Signal> {
    // only 3 signals are explicitly acted upon... everything else
    // is passed through to the supervisor
    //
    // If it gets a HUP, it restarts the Supervisor
    // process... anything else will pretty much kill the
    // supervisor outright (I think)
    //
    // Also, these are things that get sent to the launcher.
    match code {
        libc::SIGHUP => Some(Signal::HUP),
        libc::SIGINT => Some(Signal::INT), // -> shutdown
        libc::SIGILL => Some(Signal::ILL),
        libc::SIGABRT => Some(Signal::ABRT),
        libc::SIGFPE => Some(Signal::FPE),
        libc::SIGKILL => Some(Signal::KILL),
        libc::SIGSEGV => Some(Signal::SEGV),
        libc::SIGTERM => Some(Signal::TERM), // -> wait on child
        libc::SIGCHLD => Some(Signal::CHLD), // -> shutdown
        _ => None,
    }
}
<commit_msg>Remove signal translations for unhandled signals<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// 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.

//! Traps and notifies UNIX signals.

use std::{collections::VecDeque,
          sync::{Mutex,
                 Once,
                 ONCE_INIT}};

use crate::os::process::{Signal,
                         SignalCode};

use super::SignalEvent;

static INIT: Once = ONCE_INIT;

lazy_static::lazy_static! {
    static ref CAUGHT_SIGNALS: Mutex<VecDeque<SignalCode>> = Mutex::new(VecDeque::new());
}

// Functions from POSIX libc.
extern "C" {
    fn signal(sig: SignalCode,
              cb: unsafe extern "C" fn(SignalCode))
              -> unsafe extern "C" fn(SignalCode);
}

unsafe extern "C" fn handle_signal(signal: SignalCode) {
    CAUGHT_SIGNALS.lock()
                  .expect("Signal mutex poisoned")
                  .push_back(signal);
}

pub fn init() {
    INIT.call_once(|| {
            self::set_signal_handlers();
        });
}

/// Consumers should call this function fairly frequently and since the vast
/// majority of the time there is at most one signal event waiting, we return
/// at most one. If multiple signals have been received since the last call,
/// they will be returned, one per call in the order they were received.
pub fn check_for_signal() -> Option<SignalEvent> {
    let mut signals = CAUGHT_SIGNALS.lock().expect("Signal mutex poisoned");

    if let Some(code) = signals.pop_front() {
        match from_signal_code(code) {
            Some(Signal::INT) | Some(Signal::TERM) => Some(SignalEvent::Shutdown),
            Some(Signal::CHLD) => Some(SignalEvent::WaitForChild),
            Some(signal) => Some(SignalEvent::Passthrough(signal)),
            None => {
                println!("Received invalid signal: #{}", code);
                None
            }
        }
    } else {
        None
    }
}

fn set_signal_handlers() {
    unsafe {
        signal(libc::SIGHUP, handle_signal);
        signal(libc::SIGINT, handle_signal);
        signal(libc::SIGQUIT, handle_signal);
        signal(libc::SIGALRM, handle_signal);
        signal(libc::SIGTERM, handle_signal);
        signal(libc::SIGUSR1, handle_signal);
        signal(libc::SIGUSR2, handle_signal);
        signal(libc::SIGCHLD, handle_signal);
    }
}

/// These are the signals that we can eventually translate into
/// some kind of event
fn from_signal_code(code: SignalCode) -> Option<Signal> {
    match code {
        libc::SIGHUP => Some(Signal::HUP),
        libc::SIGINT => Some(Signal::INT),
        libc::SIGTERM => Some(Signal::TERM),
        libc::SIGCHLD => Some(Signal::CHLD),
        _ => None,
    }
}
<|endoftext|>


<commit_before>extern crate rustbox;
use std::comm::{Receiver};

struct Editor {
    events: Receiver<rustbox::Event>,
}

enum Response {
    Continue,
    Quit,
}

impl Editor {
    pub fn handle_events(&self) -> Response {
        let evt = self.events.recv();
        match evt {
            rustbox::KeyEvent(_, _, ch) => {
                match std::char::from_u32(ch) {
                    Some('q') => Quit,
                    _ => Continue,
                }
            },
            _ => Continue,
        }
    }

    pub fn start(&self) -> Response {
        let resp = self.handle_events();
        resp
    }
}

fn main() {
    rustbox::init();

    let(events, receiver) = channel();
    let editor = Editor {events: receiver};

    spawn(proc() {
        loop {
            events.send(rustbox::poll_event());
            //break;
        }
    });

    editor.start();

    rustbox::shutdown();
}
<commit_msg>Change events loop<commit_after>extern crate rustbox;
use std::comm::{Receiver};

struct Editor {
    events: Receiver<rustbox::Event>,
}

enum Response {
    Continue,
    Quit,
}

impl Editor {
    pub fn handle_key_event(&self, ch: u32) -> Response {
        match std::char::from_u32(ch) {
            Some('q') => Quit,
            _ => Continue,
        }
    }

    pub fn start(&self) -> bool {
        loop {
            let status = match self.events.recv() {
                rustbox::KeyEvent(_, _, ch) => {
                    let status = self.handle_key_event(ch);
                    match status {
                        Quit => { false },
                        _ => { true },
                    }
                },
                _ => { true }
            };
            if status == false {
                return false;
            }
        }
    }
}

fn main() {
    rustbox::init();

    let(events, receiver) = channel();
    let editor = Editor {events: receiver};

    spawn(proc() {
        loop {
            events.send(rustbox::poll_event());
            //break;
        }
    });

    editor.start();

    rustbox::shutdown();
}
<|endoftext|>


<commit_before>use std::error::Error as StdError;
use base::ast;
use check::typecheck::{Type, TypeEnv, Typed};
use vm::vm::{VM, RootStr, Status, typecheck_expr, load_script};
use vm::api::{VMFunction, IO};

fn type_of_expr(vm: &VM) -> Status {
    let closure: &Fn(_) -> _ = &|args: RootStr| -> IO<String> {
        IO(match typecheck_expr(vm, &args) {
            Ok((expr, infos)) => {
                let ref env = (vm.env(), infos);
                format!("{}", expr.env_type_of(env))
            }
            Err(msg) => format!("{}", msg)
        })
    };
    closure.unpack_and_call(vm)
}

fn find_type_info(vm: &VM) -> Status {
    let closure: &Fn(RootStr) -> IO<String> = &|args| {
        let args = args.trim();
        IO(match vm.env().find_type_info(&vm.intern(args)) {
            Some((generic_args, typ)) => {
                match typ {
                    Some(typ) => {
                        format!("type {} {:?} = {}", args, generic_args, typ)
                    }
                    None => {
                        format!("type {} {:?} = <abstract>", args, generic_args)
                    }
                }
            }
            None => format!("'{}' is not a type", args)
        })
    };
    closure.unpack_and_call(vm)
}

#[allow(dead_code)]
pub fn run() -> Result<(), Box<StdError>> {
    let vm = VM::new();
    let io = |t| ast::ASTType::from(ast::type_con(vm.intern("IO"), vec![t]));
    try!(vm.extern_function_io("type_of_expr", 2, Type::function(vec![Type::string()], io(Type::string())), Box::new(type_of_expr)));
    try!(vm.extern_function_io("find_type_info", 2, Type::function(vec![Type::string()], io(Type::string())), Box::new(find_type_info)));
    try!(load_file(&vm, "std/prelude.hs"));
    try!(load_file(&vm, "std/repl.hs"));
    Ok(())
}

fn load_file(vm: &VM, filename: &str) -> Result<(), Box<StdError>> {
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;
    let path = Path::new(filename);
    let mut file = try!(File::open(path));
    let mut buffer = String::new();
    try!(file.read_to_string(&mut buffer));
    let name = path.file_stem().and_then(|f| f.to_str()).expect("filename");
    load_script(vm, name, &buffer)
}

<commit_msg>FIX: Do not use {:?} when returning type info to the repl<commit_after>use std::error::Error as StdError;
use base::ast;
use check::typecheck::{Type, TypeEnv, Typed};
use vm::vm::{VM, RootStr, Status, typecheck_expr, load_script};
use vm::api::{VMFunction, IO};

fn type_of_expr(vm: &VM) -> Status {
    let closure: &Fn(_) -> _ = &|args: RootStr| -> IO<String> {
        IO(match typecheck_expr(vm, &args) {
            Ok((expr, infos)) => {
                let ref env = (vm.env(), infos);
                format!("{}", expr.env_type_of(env))
            }
            Err(msg) => format!("{}", msg)
        })
    };
    closure.unpack_and_call(vm)
}

fn find_type_info(vm: &VM) -> Status {
    let closure: &Fn(RootStr) -> IO<String> = &|args| {
        let args = args.trim();
        IO(match vm.env().find_type_info(&vm.intern(args)) {
            Some((generic_args, typ)) => {
                let fmt = || -> Result<String, ::std::fmt::Error> {
                    use std::fmt::Write;
                    let mut buffer = String::new();
                    try!(write!(&mut buffer, "type {}", args));
                    for g in generic_args {
                        try!(write!(&mut buffer, " {}", g))
                    }
                    try!(write!(&mut buffer, " = "));
                    match typ {
                        Some(typ) => try!(write!(&mut buffer, "{}", typ)),
                        None => try!(write!(&mut buffer, "<abstract>"))
                    }
                    Ok(buffer)
                };
                fmt().unwrap()
            }
            None => format!("'{}' is not a type", args)
        })
    };
    closure.unpack_and_call(vm)
}

#[allow(dead_code)]
pub fn run() -> Result<(), Box<StdError>> {
    let vm = VM::new();
    let io = |t| ast::ASTType::from(ast::type_con(vm.intern("IO"), vec![t]));
    try!(vm.extern_function_io("type_of_expr", 2, Type::function(vec![Type::string()], io(Type::string())), Box::new(type_of_expr)));
    try!(vm.extern_function_io("find_type_info", 2, Type::function(vec![Type::string()], io(Type::string())), Box::new(find_type_info)));
    try!(load_file(&vm, "std/prelude.hs"));
    try!(load_file(&vm, "std/repl.hs"));
    Ok(())
}

fn load_file(vm: &VM, filename: &str) -> Result<(), Box<StdError>> {
    use std::fs::File;
    use std::io::Read;
    use std::path::Path;
    let path = Path::new(filename);
    let mut file = try!(File::open(path));
    let mut buffer = String::new();
    try!(file.read_to_string(&mut buffer));
    let name = path.file_stem().and_then(|f| f.to_str()).expect("filename");
    load_script(vm, name, &buffer)
}

<|endoftext|>


<commit_before>use rand::distributions::{IndependentSample, Range};
use rand;
use gl;
use std;
use shader::Shader;
use shader::ShaderProgram;
use shader::ShaderType;
use super::graphics::vao::VAO;

#[derive(Debug)]
struct Particle {
    x: f32,
    y: f32,
    z: f32,
    w: f32
}

pub struct ParticleSystem {
    particles: Vec<Particle>,
    draw_shader_program: ShaderProgram,
    vao: VAO,
    now: std::time::Instant
}

impl ParticleSystem {
    pub fn new(particle_count: usize) -> ParticleSystem {
        let mut system = ParticleSystem {
            particles: Vec::with_capacity(particle_count),
            draw_shader_program: ShaderProgram::new(),
            vao: VAO::new(),
            now: std::time::Instant::now()
        };

        let mut rng = rand::thread_rng();
        let range = Range::new(-1000.0, 1000.0);

        for i in 0..particle_count {
            let particle = Particle {
                x : range.ind_sample(&mut rng),
                y : range.ind_sample(&mut rng),
                z : range.ind_sample(&mut rng),
                w : 0.0
            };

            system.particles.push(particle);
        }

        system
    }

    pub fn update(& self, dt: f64) {

    }

    pub fn init_graphics_resources(&mut self) {
        let vertices: Vec<f32> = vec!(
            -0.5, -0.5, 0.0,
             0.5, -0.5, 0.0,
             0.0,  0.5, 0.0
        );

        self.vao.set_buffer(&vertices, 0);

        let mut vertex_shader = Shader::new(ShaderType::Vertex, "shaders/vertex_shader.v.glsl");
        vertex_shader.compile();

        let mut fragment_shader = Shader::new(ShaderType::Fragment, "shaders/pixel_shader.p.glsl");
        fragment_shader.compile();

        self.draw_shader_program.attach_shader(&vertex_shader);
        self.draw_shader_program.attach_shader(&fragment_shader);
        self.draw_shader_program.link();

    }

    pub fn render(&self) {

        self.draw_shader_program.use_program();
        let elapsed = self.now.elapsed().as_secs();
        let colorg = (elapsed % 10) as f32 / 10.0f32;
        self.draw_shader_program.set_uniform4f("vtxColor", vec![0.3, colorg, 0.3, 1.0].as_slice());
        unsafe {
            self.vao.bind();
            gl::DrawArrays(gl::TRIANGLES, 0, 3);
        }
    }
}
<commit_msg>No need for vec!<commit_after>use rand::distributions::{IndependentSample, Range};
use rand;
use gl;
use std;
use shader::Shader;
use shader::ShaderProgram;
use shader::ShaderType;
use super::graphics::vao::VAO;

#[derive(Debug)]
struct Particle {
    x: f32,
    y: f32,
    z: f32,
    w: f32
}

pub struct ParticleSystem {
    particles: Vec<Particle>,
    draw_shader_program: ShaderProgram,
    vao: VAO,
    now: std::time::Instant
}

impl ParticleSystem {
    pub fn new(particle_count: usize) -> ParticleSystem {
        let mut system = ParticleSystem {
            particles: Vec::with_capacity(particle_count),
            draw_shader_program: ShaderProgram::new(),
            vao: VAO::new(),
            now: std::time::Instant::now()
        };

        let mut rng = rand::thread_rng();
        let range = Range::new(-1000.0, 1000.0);

        for i in 0..particle_count {
            let particle = Particle {
                x : range.ind_sample(&mut rng),
                y : range.ind_sample(&mut rng),
                z : range.ind_sample(&mut rng),
                w : 0.0
            };

            system.particles.push(particle);
        }

        system
    }

    pub fn update(& self, dt: f64) {

    }

    pub fn init_graphics_resources(&mut self) {
        let vertices: Vec<f32> = vec!(
            -0.5, -0.5, 0.0,
             0.5, -0.5, 0.0,
             0.0,  0.5, 0.0
        );

        self.vao.set_buffer(&vertices, 0);

        let mut vertex_shader = Shader::new(ShaderType::Vertex, "shaders/vertex_shader.v.glsl");
        vertex_shader.compile();

        let mut fragment_shader = Shader::new(ShaderType::Fragment, "shaders/pixel_shader.p.glsl");
        fragment_shader.compile();

        self.draw_shader_program.attach_shader(&vertex_shader);
        self.draw_shader_program.attach_shader(&fragment_shader);
        self.draw_shader_program.link();

    }

    pub fn render(&self) {

        self.draw_shader_program.use_program();
        let elapsed = self.now.elapsed().as_secs();
        let colorg = (elapsed % 10) as f32 / 10.0f32;
        self.draw_shader_program.set_uniform4f("vtxColor", &[0.3, colorg, 0.3, 1.0]);
        unsafe {
            self.vao.bind();
            gl::DrawArrays(gl::TRIANGLES, 0, 3);
        }
    }
}
<|endoftext|>


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

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo <input>
       metadata --help

Options:
  -h, --help   Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
}

fn print_stream_info<P: StreamProducer>(stream: &Stream<P>) {
  let info    = stream.info();
  let mut md5 = String::with_capacity(32);

  for byte in &info.md5_sum {
    let hex = format!("{:02x}", byte);

    md5.push_str(&hex);
  }

  println!("StreamInfo
  Minimum block size: {}
  Maximum block size: {}
  Maximum frame size: {}
  Maximum frame size: {}
  Sample rate: {} Hz
  Number of channels: {}
  Bits per sample: {}
  Total samples: {}
  MD5 sum: {}",
  info.min_block_size, info.max_block_size,
  info.min_frame_size, info.max_frame_size,
  info.sample_rate, info.channels, info.bits_per_sample,
  info.total_samples, md5);
}

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

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream);
  }
}
<commit_msg>Fix type with `min_frame_size` display<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo <input>
       metadata --help

Options:
  -h, --help   Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_input: String,
  cmd_streaminfo: bool,
}

fn print_stream_info<P: StreamProducer>(stream: &Stream<P>) {
  let info    = stream.info();
  let mut md5 = String::with_capacity(32);

  for byte in &info.md5_sum {
    let hex = format!("{:02x}", byte);

    md5.push_str(&hex);
  }

  println!("StreamInfo
  Minimum block size: {}
  Maximum block size: {}
  Minimum frame size: {}
  Maximum frame size: {}
  Sample rate: {} Hz
  Number of channels: {}
  Bits per sample: {}
  Total samples: {}
  MD5 sum: {}",
  info.min_block_size, info.max_block_size,
  info.min_frame_size, info.max_frame_size,
  info.sample_rate, info.channels, info.bits_per_sample,
  info.total_samples, md5);
}

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

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_input)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream);
  }
}
<|endoftext|>