<commit_before>use std;
use std::cmp;
use std::io::stdout;
use std::io::Write;
use std::thread;
use std::time;

use termion;
use termion::clear;
use termion::color;
use termion::cursor;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::raw::RawTerminal;

use core::Core;
use update::Update;

pub struct Screen {
    pub stdout: MouseTerminal<RawTerminal<std::io::Stdout>>,
    pub size: (u16, u16),
}

impl Screen {
    pub fn new() -> Screen {
        let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
        write!(stdout, "{}", clear::All).unwrap();
        stdout.flush().unwrap();
        Screen {
            size: termion::terminal_size().unwrap(),
            stdout: stdout,
        }
    }

    // TODO: handle lines that are longer than terminal width.
    // Should we wrap them or truncate them?
    pub fn redraw(&mut self, update: &Update) {
        unimplemented!();
        /*
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();

        let nb_lines = cmp::min(update.lines.len(), self.size.1 as usize);
        if nb_lines > 0 {
            for line in update.lines.iter().take(nb_lines - 1) {
                write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();

                if let Some(selection) = line.selection {
                    let start = selection.0 as usize;
                    let end = selection.1 as usize;
                    let mut str_before = String::new();
                    for c in line.text.chars().take(start) {
                        str_before.push(c);
                    }
                    let mut str_selection = String::new();
                    for c in line.text.chars().skip(start).take(end) {
                        str_selection.push(c);
                    }
                    let mut str_after = String::new();
                    for c in line.text.chars().skip(end) {
                        str_after.push(c);
                    }
                    write!(self.stdout, "{}{}{}{}{}{}",
                           termion::style::Reset,
                           str_before,
                           termion::color::Bg(color::Red),
                           str_selection,
                           termion::style::Reset,
                           str_after).unwrap();
                } else {
                    self.stdout.write_all(line.text.as_bytes()).unwrap();
                }
            }

            // If the last line has a trailing \n, we need to remove it
            let mut last_line = update.lines[nb_lines - 1].text.clone();
            match last_line.pop() {
                Some('\n') | None => {
                },
                Some(c) => {
                    last_line.push(c);
                }
            }
            write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
            self.stdout.write_all(last_line.as_bytes()).unwrap();
        }

        let cursor_line_idx = update.scroll_to.0 - update.first_line;
        let cursor_line = update.lines[cursor_line_idx as usize].text.clone();
        let mut cols =  0;
        for c in cursor_line.chars().take(update.scroll_to.1 as usize) {
            if c == '\t' {
                cols += 4;
            } else {
                cols += 1;
            }
        }
        self.scroll(cols + 1, cursor_line_idx + 1);
        */
    }

    pub fn scroll(&mut self, col: u64, line: u64) {
        write!(self.stdout, "{}", cursor::Goto(col as u16, line as u16)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn init(&mut self) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn update(&mut self, core: &mut Core) {
        // TODO: check if terminal size changed. If so, send a `render_line` command to the backend,
        // and a `scroll` command for future updates.
        if let Ok(msg) = core.update_rx.try_recv() {
            let msg_list = msg.as_array().unwrap();
            let (method, params) = (msg_list[0].as_str().unwrap(), msg_list[1].as_object().unwrap());
            if method == "update" {
                let update = Update::from_value(params.get("update").unwrap());
                self.redraw(&update);
            } else if method == "scroll_to" {
                let (col, line) = (params.get("col").unwrap().as_u64().unwrap(), params.get("line").unwrap().as_u64().unwrap());
                self.scroll(col, line);
            } else if method == "set_style" {
                // TODO: ???
            } else {
                info!("Unknown request from backend {:?}", method);
            }
        } else {
            thread::sleep(time::Duration::from_millis(10));
        }
    }
}
<commit_msg>Fixes scroll method to actually unwrap the result<commit_after>use std;
use std::cmp;
use std::io::stdout;
use std::io::Write;
use std::thread;
use std::time;

use termion;
use termion::clear;
use termion::color;
use termion::cursor;
use termion::input::MouseTerminal;
use termion::raw::IntoRawMode;
use termion::raw::RawTerminal;

use core::Core;
use update::Update;

pub struct Screen {
    pub stdout: MouseTerminal<RawTerminal<std::io::Stdout>>,
    pub size: (u16, u16),
}

impl Screen {
    pub fn new() -> Screen {
        let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());
        write!(stdout, "{}", clear::All).unwrap();
        stdout.flush().unwrap();
        Screen {
            size: termion::terminal_size().unwrap(),
            stdout: stdout,
        }
    }

    // TODO: handle lines that are longer than terminal width.
    // Should we wrap them or truncate them?
    pub fn redraw(&mut self, update: &Update) {
        unimplemented!();
        /*
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();

        let nb_lines = cmp::min(update.lines.len(), self.size.1 as usize);
        if nb_lines > 0 {
            for line in update.lines.iter().take(nb_lines - 1) {
                write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();

                if let Some(selection) = line.selection {
                    let start = selection.0 as usize;
                    let end = selection.1 as usize;
                    let mut str_before = String::new();
                    for c in line.text.chars().take(start) {
                        str_before.push(c);
                    }
                    let mut str_selection = String::new();
                    for c in line.text.chars().skip(start).take(end) {
                        str_selection.push(c);
                    }
                    let mut str_after = String::new();
                    for c in line.text.chars().skip(end) {
                        str_after.push(c);
                    }
                    write!(self.stdout, "{}{}{}{}{}{}",
                           termion::style::Reset,
                           str_before,
                           termion::color::Bg(color::Red),
                           str_selection,
                           termion::style::Reset,
                           str_after).unwrap();
                } else {
                    self.stdout.write_all(line.text.as_bytes()).unwrap();
                }
            }

            // If the last line has a trailing \n, we need to remove it
            let mut last_line = update.lines[nb_lines - 1].text.clone();
            match last_line.pop() {
                Some('\n') | None => {
                },
                Some(c) => {
                    last_line.push(c);
                }
            }
            write!(self.stdout, "{}", cursor::Left(self.size.0)).unwrap();
            self.stdout.write_all(last_line.as_bytes()).unwrap();
        }

        let cursor_line_idx = update.scroll_to.0 - update.first_line;
        let cursor_line = update.lines[cursor_line_idx as usize].text.clone();
        let mut cols =  0;
        for c in cursor_line.chars().take(update.scroll_to.1 as usize) {
            if c == '\t' {
                cols += 4;
            } else {
                cols += 1;
            }
        }
        self.scroll(cols + 1, cursor_line_idx + 1);
        */
    }

    pub fn scroll(&mut self, col: u64, line: u64) {
        write!(self.stdout, "{}", cursor::Goto((col + 1) as u16, (line + 1) as u16)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn init(&mut self) {
        write!(self.stdout, "{}", termion::clear::All).unwrap();
        write!(self.stdout, "{}", cursor::Up(self.size.1)).unwrap();
        self.stdout.flush().unwrap();
    }

    pub fn update(&mut self, core: &mut Core) {
        // TODO: check if terminal size changed. If so, send a `render_line` command to the backend,
        // and a `scroll` command for future updates.
        if let Ok(msg) = core.update_rx.try_recv() {
            let msg_list = msg.as_array().unwrap();
            let (method, params) = (msg_list[0].as_str().unwrap(), msg_list[1].as_object().unwrap());
            if method == "update" {
                let update = Update::from_value(params.get("update").unwrap());
                self.redraw(&update);
            } else if method == "scroll_to" {
                let (col, line) = (params.get("col").unwrap().as_u64().unwrap(), params.get("line").unwrap().as_u64().unwrap());
                self.scroll(col, line);
            } else if method == "set_style" {
                // TODO: ???
            } else {
                info!("Unknown request from backend {:?}", method);
            }
        } else {
            thread::sleep(time::Duration::from_millis(10));
        }
    }
}
<|endoftext|>


<commit_before>use addressable::Addressable;
use addressable::AddressableUtil;
use ram::Ram;

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

struct Registers {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
}

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &Mos6502) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.reg.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.reg.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.reg.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.reg.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.reg.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.reg.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.reg.y as u16 },
		}
	}

	fn get (&self, cpu: &Mos6502) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.reg.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, cpu: &mut Mos6502, val: u8) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.reg.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

pub struct Mos6502<'self> {
	priv reg: Registers,		// internal CPU registers
	priv mem: Ram<u16>,			// memory as accessible to the CPU
}

impl<'self> Mos6502<'self> {
	pub fn new () -> Mos6502 {
		Mos6502 {
			reg: Registers { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0 },
			mem: Ram::new()
		}
	}
}

impl<'self> Addressable<u16> for Mos6502<'self> {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}

pub struct Mos6510<'self> {
	priv cpu: Mos6502<'self>,	// Core CPU
	priv port_ddr: u8,			// CPU port data direction register
	priv port_dat: u8,			// CPU port data register
}

impl<'self> Mos6510<'self> {
	pub fn new () -> Mos6510 {
		Mos6510 { cpu: Mos6502::new(), port_ddr: 0, port_dat: 0 }
	}
}
<commit_msg>Changed CPU to use passed memory instead of fixed ram<commit_after>use addressable::Addressable;
use addressable::AddressableUtil;
use memory::Memory;

static NMI_VECTOR: u16 = 0xfffa;
static RESET_VECTOR: u16 = 0xfffc;
static IRQ_VECTOR: u16 = 0xfffe;

struct Registers {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
}

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &Mos6502) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.reg.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.reg.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.reg.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.reg.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.reg.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.reg.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.reg.y as u16 },
		}
	}

	fn get (&self, cpu: &Mos6502) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.reg.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, cpu: &mut Mos6502, val: u8) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.reg.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

pub struct Mos6502<'self> {
	priv reg: Registers,					// internal CPU registers
	priv mem: &'self Memory<'self, u16>,	// memory as accessible to the CPU
}

impl<'self> Mos6502<'self> {
	pub fn new (mem: &'self Memory<u16>) -> Mos6502<'self> {
		Mos6502 {
			reg: Registers { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0 },
			mem: mem,
		}
	}
}

impl<'self> Addressable<u16> for Mos6502<'self> {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}

pub struct Mos6510<'self> {
	priv cpu: Mos6502<'self>,				// Core CPU
	priv port_ddr: u8,						// CPU port data direction register
	priv port_dat: u8,						// CPU port data register
}

impl<'self> Mos6510<'self> {
	pub fn new (mem: &'self Memory<u16>) -> Mos6510<'self> {
		Mos6510 { cpu: Mos6502::new(mem), port_ddr: 0, port_dat: 0 }
	}
}
<|endoftext|>


<commit_before>//! The nodes.

use std::collections::HashMap;
use std::fmt;

mod comment;
mod text;
mod value;

pub use self::comment::Comment;
pub use self::text::Text;
pub use self::value::Value;

/// Attributes.
pub type Attributes = HashMap<String, Value>;

/// Child nodes.
pub type Children = Vec<Box<dyn Node>>;

/// A node.
pub trait Node: 'static + fmt::Debug + fmt::Display + NodeClone {
    /// Append a child node.
    fn append<T>(&mut self, _: T)
    where
        Self: Sized,
        T: Node;

    /// Assign an attribute.
    fn assign<T, U>(&mut self, _: T, _: U)
    where
        Self: Sized,
        T: Into<String>,
        U: Into<Value>;
}

#[doc(hidden)]
pub trait NodeClone {
    fn clone(&self) -> Box<dyn Node>;
}

impl<T> NodeClone for T
where
    T: Node + Clone,
{
    #[inline]
    fn clone(&self) -> Box<dyn Node> {
        Box::new(Clone::clone(self))
    }
}

impl Clone for Box<dyn Node> {
    #[inline]
    fn clone(&self) -> Self {
        NodeClone::clone(&**self)
    }
}

macro_rules! node(
    ($struct_name:ident::$field_name:ident) => (
        impl $struct_name {
            /// Append a node.
            pub fn add<T>(mut self, node: T) -> Self
            where
                T: crate::node::Node,
            {
                crate::node::Node::append(&mut self, node);
                self
            }

            /// Assign an attribute.
            #[inline]
            pub fn set<T, U>(mut self, name: T, value: U) -> Self
            where
                T: Into<String>,
                U: Into<crate::node::Value>,
            {
                crate::node::Node::assign(&mut self, name, value);
                self
            }
        }

        impl crate::node::Node for $struct_name {
            #[inline]
            fn append<T>(&mut self, node: T) where T: crate::node::Node {
                self.$field_name.append(node);
            }

            #[inline]
            fn assign<T, U>(&mut self, name: T, value: U)
            where
                T: Into<String>,
                U: Into<crate::node::Value>,
            {
                self.$field_name.assign(name, value);
            }
        }

        impl ::std::fmt::Display for $struct_name {
            #[inline]
            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                self.$field_name.fmt(formatter)
            }
        }
    );
);

pub mod element;
<commit_msg>Make a cosmetic adjustment<commit_after>//! The nodes.

use std::collections::HashMap;
use std::fmt;

mod comment;
mod text;
mod value;

pub use self::comment::Comment;
pub use self::text::Text;
pub use self::value::Value;

/// Attributes.
pub type Attributes = HashMap<String, Value>;

/// Child nodes.
pub type Children = Vec<Box<dyn Node>>;

/// A node.
pub trait Node: 'static + fmt::Debug + fmt::Display + NodeClone {
    /// Append a child node.
    fn append<T>(&mut self, _: T)
    where
        Self: Sized,
        T: Node;

    /// Assign an attribute.
    fn assign<T, U>(&mut self, _: T, _: U)
    where
        Self: Sized,
        T: Into<String>,
        U: Into<Value>;
}

#[doc(hidden)]
pub trait NodeClone {
    fn clone(&self) -> Box<dyn Node>;
}

impl<T> NodeClone for T
where
    T: Node + Clone,
{
    #[inline]
    fn clone(&self) -> Box<dyn Node> {
        Box::new(Clone::clone(self))
    }
}

impl Clone for Box<dyn Node> {
    #[inline]
    fn clone(&self) -> Self {
        NodeClone::clone(&**self)
    }
}

macro_rules! node(
    ($struct_name:ident::$field_name:ident) => (
        impl $struct_name {
            /// Append a node.
            pub fn add<T>(mut self, node: T) -> Self
            where
                T: crate::node::Node,
            {
                crate::node::Node::append(&mut self, node);
                self
            }

            /// Assign an attribute.
            #[inline]
            pub fn set<T, U>(mut self, name: T, value: U) -> Self
            where
                T: Into<String>,
                U: Into<crate::node::Value>,
            {
                crate::node::Node::assign(&mut self, name, value);
                self
            }
        }

        impl crate::node::Node for $struct_name {
            #[inline]
            fn append<T>(&mut self, node: T)
            where
                T: crate::node::Node
            {
                self.$field_name.append(node);
            }

            #[inline]
            fn assign<T, U>(&mut self, name: T, value: U)
            where
                T: Into<String>,
                U: Into<crate::node::Value>,
            {
                self.$field_name.assign(name, value);
            }
        }

        impl ::std::fmt::Display for $struct_name {
            #[inline]
            fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
                self.$field_name.fmt(formatter)
            }
        }
    );
);

pub mod element;
<|endoftext|>


<commit_before>use ardite::Service;
use ardite::value::Value;
use ardite::error::{Error, MethodNotAllowed};
use inflections::Inflect;
use iron::prelude::*;
use iron::headers::{ContentType, ContentLength};
use iron::method;
use iron::modifiers::Header;
use iron::status::Status;
use iron::{Handler, Url};
use urlencoded::{UrlEncodedQuery, EmptyQuery};

use case::Case;
use resource::{Resource, Data};
use resource::root::Root;

pub struct Server {
  pub service: Service<'static>,
  pub root_url: Url,
  pub default_case: Case
}

impl Server {
  fn route<'a>(&'a self, path: Vec<String>) -> Option<Box<Resource + 'a>> {
    path.into_iter().fold(Some(Box::new(Root)), |opt_resource, part| {
      if part.is_kebab_case() {
        opt_resource.and_then(|resource| resource.route(self.service.definition(), part))
      } else {
        None
      }
    })
  }

  fn create_url(&self, path: Vec<String>) -> Url {
    let mut url = self.root_url.clone();
    for part in path {
      url.path.push(part.to_kebab_case());
    }
    url
  }

  /// Handles taking a request and turning it into a `Result<Value, Error>.`
  // TODO: Combine this with the `Handler` implementation.
  fn handle(&self, req: &mut Request) -> Result<Data, Error> {
    let mut path = req.url.path.clone();
    let create_url = &|path| self.create_url(path);

    // URLs like `google.com`, or `google.com/` have a path of `vec![""]`. We
    // would rather interpret this as the root path or `vec![]`.
    if path == vec![""] {
      path = vec![];
    }

    let mut resource = try!(self.route(path).ok_or(
      Error::not_found(format!("Resource '{}' not found.", self.create_url(req.url.path.clone())))
      .set_hint("Check the root resource for available top level paths.")
    ));

    // Get the query parameters and mutate the resource with it.
    match req.get_ref::<UrlEncodedQuery>() {
      Ok(ref query) => { resource.query(query); },
      Err(ref error) => {
        match error {
          &EmptyQuery => {},
          error @ _ => { return Err(Error::invalid(format!("{}", error), "Try fixing your query syntax.")); }
        };
      }
    };

    // TODO: `Allow` header.
    match &req.method {
      &method::Get => resource.get(create_url, &self.service),
      &method::Post => resource.post(create_url, &self.service),
      &method::Put => resource.put(create_url, &self.service),
      &method::Patch => resource.patch(create_url, &self.service),
      &method::Delete => resource.delete(create_url, &self.service),
      method @ _ => Err(
        Error::new(MethodNotAllowed, format!("Cannot perform a {} request on any resource in this API.", method))
        .set_hint("Try a HEAD, GET, POST, PUT, PATCH, or DELETE request instead.")
      )
    }
  }
}

// TODO: Combine this with the `Server` handle method.
impl Handler for Server {
  /// Handles taking a `Result<Value, Error>` and turning it into an `IronResult<Response>`.
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    // Allows users to ping the server.
    // TODO: *Only* try to use this after we can’t find any other `Resource`
    // to serve this request.
    if req.method == method::Options && req.url.path == vec![""] {
      use iron::headers::*;
      use iron::method::*;
      return Ok(
        Response::new()
        .set(Status::Ok)
        // TODO: `Allow` header isn’t actually accurate for every resource…
        // consider automating `OPTIONS` for every `Resource` which is always
        // accurate.
        .set(Header(Allow(vec![Get, Post, Put, Patch, Delete, Options])))
      );
    }

    let case = &self.default_case;

    match self.handle(req) {
      Ok(data) => {
        match data {
          Data::None => Ok(Response::new().set(Status::Ok)),
          Data::Value(value) => {
            let mut content = value_keys_to_case(value, case).to_json_pretty().unwrap();
            content.push_str("\n");

            let mut res = Response::new();

            res.set_mut(Status::Ok);
            res.set_mut(Header(ContentType(mime!(Application/Json; Charset=Utf8))));
            res.set_mut(Header(ContentLength(content.len() as u64)));
            res.set_mut(content);

            Ok(res)
          },
          // TODO: actually stream this…
          Data::Stream(iter) => {
            let array = Value::Array(iter.map(|value| value_keys_to_case(value, case)).collect());
            let mut content = array.to_json_pretty().unwrap();
            content.push_str("\n");

            let mut res = Response::new();

            res.set_mut(Status::Ok);
            res.set_mut(Header(ContentType(mime!(Application/Json; Charset=Utf8))));
            res.set_mut(Header(ContentLength(content.len() as u64)));
            res.set_mut(content);

            Ok(res)
          }
        }
      },
      Err(error) => {
        let mut content = error.to_value().to_json_pretty().unwrap();
        content.push_str("\n");

        let mut res = Response::new();

        res.set_mut(Status::from_u16(error.code().to_u16()));
        res.set_mut(Header(ContentType(mime!(Application/Json; Charset=Utf8))));
        res.set_mut(Header(ContentLength(content.len() as u64)));
        res.set_mut(content);

        Err(IronError {
          error: Box::new(error),
          response: res
        })
      }
    }
  }
}

fn value_keys_to_case(value: Value, case: &Case) -> Value {
  match value {
    value @ Value::Array(_) => value.map_values(|value| value_keys_to_case(value, case)),
    value @ _ => value.map_entries(|(key, value)| (case.to_case(&key), value_keys_to_case(value, case)))
  }
}
<commit_msg>refactor(server): options for all!<commit_after>use ardite::Service;
use ardite::value::Value;
use ardite::error::{Error, MethodNotAllowed};
use inflections::Inflect;
use iron::prelude::*;
use iron::headers::{ContentType, ContentLength};
use iron::method;
use iron::modifiers::Header;
use iron::status::Status;
use iron::{Handler, Url};
use urlencoded::{UrlEncodedQuery, EmptyQuery};

use case::Case;
use resource::{Resource, Data};
use resource::root::Root;

pub struct Server {
  pub service: Service<'static>,
  pub root_url: Url,
  pub default_case: Case
}

impl Server {
  fn route<'a>(&'a self, path: Vec<String>) -> Option<Box<Resource + 'a>> {
    path.into_iter().fold(Some(Box::new(Root)), |opt_resource, part| {
      if part.is_kebab_case() {
        opt_resource.and_then(|resource| resource.route(self.service.definition(), part))
      } else {
        None
      }
    })
  }

  fn create_url(&self, path: Vec<String>) -> Url {
    let mut url = self.root_url.clone();
    for part in path {
      url.path.push(part.to_kebab_case());
    }
    url
  }

  /// Handles taking a request and turning it into a `Result<Value, Error>.`
  // TODO: Combine this with the `Handler` implementation.
  fn handle(&self, req: &mut Request) -> Result<Data, Error> {
    let mut path = req.url.path.clone();
    let create_url = &|path| self.create_url(path);

    // URLs like `google.com`, or `google.com/` have a path of `vec![""]`. We
    // would rather interpret this as the root path or `vec![]`.
    if path == vec![""] {
      path = vec![];
    }

    let mut resource = try!(self.route(path).ok_or(
      Error::not_found(format!("Resource '{}' not found.", self.create_url(req.url.path.clone())))
      .set_hint("Check the root resource for available top level paths.")
    ));

    // Get the query parameters and mutate the resource with it.
    match req.get_ref::<UrlEncodedQuery>() {
      Ok(ref query) => { resource.query(query); },
      Err(ref error) => {
        match error {
          &EmptyQuery => {},
          error @ _ => { return Err(Error::invalid(format!("{}", error), "Try fixing your query syntax.")); }
        };
      }
    };

    // TODO: `Allow` header.
    match &req.method {
      &method::Get => resource.get(create_url, &self.service),
      &method::Post => resource.post(create_url, &self.service),
      &method::Put => resource.put(create_url, &self.service),
      &method::Patch => resource.patch(create_url, &self.service),
      &method::Delete => resource.delete(create_url, &self.service),
      method @ _ => Err(
        Error::new(MethodNotAllowed, format!("Cannot perform a {} request on any resource in this API.", method))
        .set_hint("Try an OPTIONS request to see what other methods you can use.")
      )
    }
  }
}

// TODO: Combine this with the `Server` handle method.
impl Handler for Server {
  /// Handles taking a `Result<Value, Error>` and turning it into an `IronResult<Response>`.
  fn handle(&self, req: &mut Request) -> IronResult<Response> {
    // Allows users to ping the server.
    // TODO: *Only* try to use this after we can’t find any other `Resource`
    // to serve this request.
    if req.method == method::Options {
      use iron::headers::*;
      use iron::method::*;
      return Ok(
        Response::new()
        .set(Status::Ok)
        // TODO: `Allow` header isn’t actually accurate for every resource…
        // consider automating `OPTIONS` for every `Resource` which is always
        // accurate.
        .set(Header(Allow(vec![Get, Post, Put, Patch, Delete, Options])))
      );
    }

    let case = &self.default_case;

    match self.handle(req) {
      Ok(data) => {
        match data {
          Data::None => Ok(Response::new().set(Status::Ok)),
          Data::Value(value) => {
            let mut content = value_keys_to_case(value, case).to_json_pretty().unwrap();
            content.push_str("\n");

            let mut res = Response::new();

            res.set_mut(Status::Ok);
            res.set_mut(Header(ContentType(mime!(Application/Json; Charset=Utf8))));
            res.set_mut(Header(ContentLength(content.len() as u64)));
            res.set_mut(content);

            Ok(res)
          },
          // TODO: actually stream this…
          Data::Stream(iter) => {
            let array = Value::Array(iter.map(|value| value_keys_to_case(value, case)).collect());
            let mut content = array.to_json_pretty().unwrap();
            content.push_str("\n");

            let mut res = Response::new();

            res.set_mut(Status::Ok);
            res.set_mut(Header(ContentType(mime!(Application/Json; Charset=Utf8))));
            res.set_mut(Header(ContentLength(content.len() as u64)));
            res.set_mut(content);

            Ok(res)
          }
        }
      },
      Err(error) => {
        let mut content = error.to_value().to_json_pretty().unwrap();
        content.push_str("\n");

        let mut res = Response::new();

        res.set_mut(Status::from_u16(error.code().to_u16()));
        res.set_mut(Header(ContentType(mime!(Application/Json; Charset=Utf8))));
        res.set_mut(Header(ContentLength(content.len() as u64)));
        res.set_mut(content);

        Err(IronError {
          error: Box::new(error),
          response: res
        })
      }
    }
  }
}

fn value_keys_to_case(value: Value, case: &Case) -> Value {
  match value {
    value @ Value::Array(_) => value.map_values(|value| value_keys_to_case(value, case)),
    value @ _ => value.map_entries(|(key, value)| (case.to_case(&key), value_keys_to_case(value, case)))
  }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Mutex;
use std::thread;

use hyper::header::{ContentType, CacheControl, CacheDirective};
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::method::Method;
use hyper::Result;
use hyper::server::{Handler, Listening, Request, Response, Server};
use hyper::status::StatusCode;
use hyper::uri::RequestUri::AbsolutePath;

use command::{WebDriverMessage, WebDriverCommand};
use error::{WebDriverResult, WebDriverError, ErrorStatus};
use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
use response::{CloseWindowResponse, WebDriverResponse};

enum DispatchMessage<U: WebDriverExtensionRoute> {
    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
    Quit
}

#[derive(PartialEq, Clone)]
pub struct Session {
    id: String
}

impl Session {
    fn new(id: String) -> Session {
        Session {
            id: id
        }
    }
}

pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler<U>,
                  U: WebDriverExtensionRoute> {
    handler: T,
    session: Option<Session>,
    extension_type: PhantomData<U>,
}

impl<T: WebDriverHandler<U>, U: WebDriverExtensionRoute> Dispatcher<T, U> {
    fn new(handler: T) -> Dispatcher<T, U> {
        Dispatcher {
            handler: handler,
            session: None,
            extension_type: PhantomData,
        }
    }

    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
        loop {
            match msg_chan.recv() {
                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
                    let resp = match self.check_session(&msg) {
                        Ok(_) => self.handler.handle_command(&self.session, msg),
                        Err(e) => Err(e),
                    };

                    match resp {
                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
                            self.session = Some(Session::new(new_session.sessionId.clone()));
                        }
                        Ok(WebDriverResponse::CloseWindow(CloseWindowResponse { ref window_handles })) => {
                            if window_handles.len() == 0 {
                                debug!("Last window was closed, deleting session");
                                self.delete_session();
                            }
                        }
                        Ok(WebDriverResponse::DeleteSession) => self.delete_session(),
                        Err(ref x) if x.delete_session => self.delete_session(),
                        _ => {}
                    }

                    if resp_chan.send(resp).is_err() {
                        error!("Sending response to the main thread failed");
                    };
                }
                Ok(DispatchMessage::Quit) => break,
                Err(_) => panic!("Error receiving message in handler"),
            }
        }
    }

    fn delete_session(&mut self) {
        debug!("Deleting session");
        self.handler.delete_session(&self.session);
        self.session = None;
    }

    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
        match msg.session_id {
            Some(ref msg_session_id) => {
                match self.session {
                    Some(ref existing_session) => {
                        if existing_session.id != *msg_session_id {
                            Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                format!("Got unexpected session id {} expected {}",
                                        msg_session_id,
                                        existing_session.id)))
                        } else {
                            Ok(())
                        }
                    },
                    None => Ok(())
                }
            },
            None => {
                match self.session {
                    Some(_) => {
                        match msg.command {
                            WebDriverCommand::Status => Ok(()),
                            WebDriverCommand::NewSession(_) => {
                                Err(WebDriverError::new(
                                    ErrorStatus::SessionNotCreated,
                                    "Session is already started"))
                            },
                            _ => {
                                //This should be impossible
                                error!("Got a message with no session id");
                                Err(WebDriverError::new(
                                    ErrorStatus::UnknownError,
                                    "Got a command with no session?!"))
                            }
                        }
                    },
                    None => {
                        match msg.command {
                            WebDriverCommand::NewSession(_) => Ok(()),
                            WebDriverCommand::Status => Ok(()),
                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

struct HttpHandler<U: WebDriverExtensionRoute> {
    chan: Mutex<Sender<DispatchMessage<U>>>,
    api: Mutex<WebDriverHttpApi<U>>
}

impl <U: WebDriverExtensionRoute> HttpHandler<U> {
    fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
        HttpHandler {
            chan: Mutex::new(chan),
            api: Mutex::new(api)
        }
    }
}

impl <U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
    fn handle(&self, req: Request, res: Response) {
        let mut req = req;
        let mut res = res;

        let mut body = String::new();
        if let Method::Post = req.method {
            req.read_to_string(&mut body).unwrap();
        }
        debug!("Got request {} {:?}", req.method, req.uri);
        match req.uri {
            AbsolutePath(path) => {
                let msg_result = {
                    // The fact that this locks for basically the whole request doesn't
                    // matter as long as we are only handling one request at a time.
                    match self.api.lock() {
                        Ok(ref api) => {
                            api.decode_request(req.method, &path[..], &body[..])
                        },
                        Err(_) => return
                    }
                };
                let (status, resp_body) = match msg_result {
                    Ok(message) => {
                        let (send_res, recv_res) = channel();
                        match self.chan.lock() {
                            Ok(ref c) => {
                                let res = c.send(DispatchMessage::HandleWebDriver(message,
                                                                                send_res));
                                match res {
                                    Ok(x) => x,
                                    Err(_) => {
                                        error!("Something terrible happened");
                                        return
                                    }
                                }
                            },
                            Err(_) => {
                                error!("Something terrible happened");
                                return
                            }
                        }
                        match recv_res.recv() {
                            Ok(data) => match data {
                                Ok(response) => (StatusCode::Ok, response.to_json_string()),
                                Err(err) => (err.http_status(), err.to_json_string()),
                            },
                            Err(e) => panic!("Error reading response: {:?}", e)
                        }
                    },
                    Err(err) => {
                        (err.http_status(), err.to_json_string())
                    }
                };
                debug!("Returning status {:?}", status);
                debug!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(
                    ContentType(Mime(TopLevel::Application, SubLevel::Json,
                                     vec![(Attr::Charset, Value::Utf8)])));
                res.headers_mut().set(CacheControl(vec![CacheDirective::NoCache]));
                res.send(&resp_body.as_bytes()).unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T, U>(address: SocketAddr,
                   handler: T,
                   extension_routes: &[(Method, &str, U)])
                   -> Result<Listening>
    where T: 'static + WebDriverHandler<U>,
          U: 'static + WebDriverExtensionRoute
{
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new(extension_routes);
    let http_handler = HttpHandler::new(api, msg_send);
    let mut server = try!(Server::http(address));
    server.keep_alive(None);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    try!(builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv);
    }));

    server.handle(http_handler)
}
<commit_msg>server: improve logging of http requests and responses<commit_after>use std::io::Read;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Mutex;
use std::thread;

use hyper::header::{ContentType, CacheControl, CacheDirective};
use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
use hyper::method::Method;
use hyper::Result;
use hyper::server::{Handler, Listening, Request, Response, Server};
use hyper::status::StatusCode;
use hyper::uri::RequestUri::AbsolutePath;

use command::{WebDriverMessage, WebDriverCommand};
use error::{WebDriverResult, WebDriverError, ErrorStatus};
use httpapi::{WebDriverHttpApi, WebDriverExtensionRoute, VoidWebDriverExtensionRoute};
use response::{CloseWindowResponse, WebDriverResponse};

enum DispatchMessage<U: WebDriverExtensionRoute> {
    HandleWebDriver(WebDriverMessage<U>, Sender<WebDriverResult<WebDriverResponse>>),
    Quit
}

#[derive(PartialEq, Clone)]
pub struct Session {
    id: String
}

impl Session {
    fn new(id: String) -> Session {
        Session {
            id: id
        }
    }
}

pub trait WebDriverHandler<U: WebDriverExtensionRoute=VoidWebDriverExtensionRoute> : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: WebDriverMessage<U>) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler<U>,
                  U: WebDriverExtensionRoute> {
    handler: T,
    session: Option<Session>,
    extension_type: PhantomData<U>,
}

impl<T: WebDriverHandler<U>, U: WebDriverExtensionRoute> Dispatcher<T, U> {
    fn new(handler: T) -> Dispatcher<T, U> {
        Dispatcher {
            handler: handler,
            session: None,
            extension_type: PhantomData,
        }
    }

    fn run(&mut self, msg_chan: Receiver<DispatchMessage<U>>) {
        loop {
            match msg_chan.recv() {
                Ok(DispatchMessage::HandleWebDriver(msg, resp_chan)) => {
                    let resp = match self.check_session(&msg) {
                        Ok(_) => self.handler.handle_command(&self.session, msg),
                        Err(e) => Err(e),
                    };

                    match resp {
                        Ok(WebDriverResponse::NewSession(ref new_session)) => {
                            self.session = Some(Session::new(new_session.sessionId.clone()));
                        }
                        Ok(WebDriverResponse::CloseWindow(CloseWindowResponse { ref window_handles })) => {
                            if window_handles.len() == 0 {
                                debug!("Last window was closed, deleting session");
                                self.delete_session();
                            }
                        }
                        Ok(WebDriverResponse::DeleteSession) => self.delete_session(),
                        Err(ref x) if x.delete_session => self.delete_session(),
                        _ => {}
                    }

                    if resp_chan.send(resp).is_err() {
                        error!("Sending response to the main thread failed");
                    };
                }
                Ok(DispatchMessage::Quit) => break,
                Err(_) => panic!("Error receiving message in handler"),
            }
        }
    }

    fn delete_session(&mut self) {
        debug!("Deleting session");
        self.handler.delete_session(&self.session);
        self.session = None;
    }

    fn check_session(&self, msg: &WebDriverMessage<U>) -> WebDriverResult<()> {
        match msg.session_id {
            Some(ref msg_session_id) => {
                match self.session {
                    Some(ref existing_session) => {
                        if existing_session.id != *msg_session_id {
                            Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                format!("Got unexpected session id {} expected {}",
                                        msg_session_id,
                                        existing_session.id)))
                        } else {
                            Ok(())
                        }
                    },
                    None => Ok(())
                }
            },
            None => {
                match self.session {
                    Some(_) => {
                        match msg.command {
                            WebDriverCommand::Status => Ok(()),
                            WebDriverCommand::NewSession(_) => {
                                Err(WebDriverError::new(
                                    ErrorStatus::SessionNotCreated,
                                    "Session is already started"))
                            },
                            _ => {
                                //This should be impossible
                                error!("Got a message with no session id");
                                Err(WebDriverError::new(
                                    ErrorStatus::UnknownError,
                                    "Got a command with no session?!"))
                            }
                        }
                    },
                    None => {
                        match msg.command {
                            WebDriverCommand::NewSession(_) => Ok(()),
                            WebDriverCommand::Status => Ok(()),
                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

struct HttpHandler<U: WebDriverExtensionRoute> {
    chan: Mutex<Sender<DispatchMessage<U>>>,
    api: Mutex<WebDriverHttpApi<U>>
}

impl <U: WebDriverExtensionRoute> HttpHandler<U> {
    fn new(api: WebDriverHttpApi<U>, chan: Sender<DispatchMessage<U>>) -> HttpHandler<U> {
        HttpHandler {
            chan: Mutex::new(chan),
            api: Mutex::new(api)
        }
    }
}

impl<U: WebDriverExtensionRoute> Handler for HttpHandler<U> {
    fn handle(&self, req: Request, res: Response) {
        let mut req = req;
        let mut res = res;

        let mut body = String::new();
        if let Method::Post = req.method {
            req.read_to_string(&mut body).unwrap();
        }

        debug!("→ {} {} {}", req.method, req.uri, body);

        match req.uri {
            AbsolutePath(path) => {
                let msg_result = {
                    // The fact that this locks for basically the whole request doesn't
                    // matter as long as we are only handling one request at a time.
                    match self.api.lock() {
                        Ok(ref api) => api.decode_request(req.method, &path[..], &body[..]),
                        Err(_) => return,
                    }
                };
                let (status, resp_body) = match msg_result {
                    Ok(message) => {
                        let (send_res, recv_res) = channel();
                        match self.chan.lock() {
                            Ok(ref c) => {
                                let res =
                                    c.send(DispatchMessage::HandleWebDriver(message, send_res));
                                match res {
                                    Ok(x) => x,
                                    Err(_) => {
                                        error!("Something terrible happened");
                                        return;
                                    }
                                }
                            }
                            Err(_) => {
                                error!("Something terrible happened");
                                return;
                            }
                        }
                        match recv_res.recv() {
                            Ok(data) => {
                                match data {
                                    Ok(response) => (StatusCode::Ok, response.to_json_string()),
                                    Err(err) => (err.http_status(), err.to_json_string()),
                                }
                            }
                            Err(e) => panic!("Error reading response: {:?}", e),
                        }
                    }
                    Err(err) => (err.http_status(), err.to_json_string()),
                };

                debug!("← {} {}", status, resp_body);

                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut()
                    .set(ContentType(Mime(TopLevel::Application,
                                          SubLevel::Json,
                                          vec![(Attr::Charset, Value::Utf8)])));
                res.headers_mut()
                    .set(CacheControl(vec![CacheDirective::NoCache]));

                res.send(&resp_body.as_bytes()).unwrap();
            }
            _ => {}
        }
    }
}

pub fn start<T, U>(address: SocketAddr,
                   handler: T,
                   extension_routes: &[(Method, &str, U)])
                   -> Result<Listening>
    where T: 'static + WebDriverHandler<U>,
          U: 'static + WebDriverExtensionRoute
{
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new(extension_routes);
    let http_handler = HttpHandler::new(api, msg_send);
    let mut server = try!(Server::http(address));
    server.keep_alive(None);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    try!(builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv);
    }));

    server.handle(http_handler)
}
<|endoftext|>


<commit_before>//! Basic STUN servers.
//!
//! This module provides only a basic STUN servers.
//! If you want more elaborate one, please consider create your own server using [`Channel`] directly.
//!
//! [`Channel`]: ../channel/struct.Channel.html
use bytecodec::marker::Never;
use factory::DefaultFactory;
use factory::Factory;
use fibers::sync::mpsc;
use fibers::{BoxSpawn, Spawn};
use fibers_transport::{self, FixedPeerTransporter, TcpTransport, UdpTransport};
use futures::{Async, Future, Poll, Stream};
use std::fmt;
use std::net::SocketAddr;
use stun_codec::rfc5389;
use stun_codec::{Attribute, MessageDecoder, MessageEncoder};

use channel::{Channel, RecvMessage};
use message::{ErrorResponse, Indication, InvalidMessage, Request, Response, SuccessResponse};
use transport::{StunTcpTransporter, StunTransport, StunUdpTransporter};
use {Error, ErrorKind, Result};

/// The default TCP and UDP port for STUN.
pub const DEFAULT_PORT: u16 = 3478;

/// The default TLS port for STUN.
pub const DEFAULT_TLS_PORT: u16 = 5349;

type UdpTransporter<A> = fibers_transport::UdpTransporter<MessageEncoder<A>, MessageDecoder<A>>;

/// UDP based STUN server.
#[derive(Debug)]
#[must_use = "future do nothing unless polled"]
pub struct UdpServer<H: HandleMessage> {
    driver: HandlerDriver<H, StunUdpTransporter<H::Attribute, UdpTransporter<H::Attribute>>>,
}
impl<H: HandleMessage> UdpServer<H> {
    /// Starts the server.
    pub fn start<S>(
        spawner: S,
        bind_addr: SocketAddr,
        handler: H,
    ) -> impl Future<Item = Self, Error = Error>
    where
        S: Spawn + Send + 'static,
    {
        UdpTransporter::bind(bind_addr)
            .map_err(|e| track!(Error::from(e)))
            .map(move |transporter| {
                let channel = Channel::new(StunUdpTransporter::new(transporter));
                let driver = HandlerDriver::new(spawner.boxed(), handler, channel);
                UdpServer { driver }
            })
    }

    /// Returns the address to which the server is bound.
    pub fn local_addr(&self) -> SocketAddr {
        self.driver
            .channel
            .transporter_ref()
            .inner_ref()
            .local_addr()
    }
}
impl<H: HandleMessage> Future for UdpServer<H> {
    type Item = Never;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Async::Ready(()) = track!(self.driver.poll())? {
            track_panic!(ErrorKind::Other, "STUN UDP server unexpectedly terminated");
        }
        Ok(Async::NotReady)
    }
}

type TcpListener<A> = fibers_transport::TcpListener<
    DefaultFactory<MessageEncoder<A>>,
    DefaultFactory<MessageDecoder<A>>,
>;

/// TCP based STUN server.
#[must_use = "future do nothing unless polled"]
pub struct TcpServer<S, H>
where
    H: Factory,
    H::Item: HandleMessage,
{
    spawner: S,
    handler_factory: H,
    listener: TcpListener<<H::Item as HandleMessage>::Attribute>,
}
impl<S, H> TcpServer<S, H>
where
    S: Spawn + Clone + Send + 'static,
    H: Factory,
    H::Item: HandleMessage,
{
    /// Starts the server.
    pub fn start(
        spawner: S,
        bind_addr: SocketAddr,
        handler_factory: H,
    ) -> impl Future<Item = Self, Error = Error> {
        TcpListener::listen(bind_addr)
            .map_err(|e| track!(Error::from(e)))
            .map(move |listener| TcpServer {
                spawner,
                handler_factory,
                listener,
            })
    }

    /// Returns the address to which the server is bound.
    pub fn local_addr(&self) -> SocketAddr {
        self.listener.local_addr()
    }
}
impl<S, H> Future for TcpServer<S, H>
where
    S: Spawn + Clone + Send + 'static,
    H: Factory,
    H::Item: HandleMessage + Send + 'static,
    <<H::Item as HandleMessage>::Attribute as Attribute>::Decoder: Send + 'static,
    <<H::Item as HandleMessage>::Attribute as Attribute>::Encoder: Send + 'static,
{
    type Item = Never;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        while let Async::Ready(transporter) = track!(self.listener.poll())? {
            if let Some(transporter) = transporter {
                let peer_addr = transporter.peer_addr();
                let transporter =
                    FixedPeerTransporter::new(peer_addr, (), StunTcpTransporter::new(transporter));
                let channel = Channel::new(transporter);
                let handler = self.handler_factory.create();
                let future = HandlerDriver::new(self.spawner.clone().boxed(), handler, channel);
                self.spawner.spawn(future.map_err(|_| ()));
            } else {
                track_panic!(ErrorKind::Other, "STUN TCP server unexpectedly terminated");
            }
        }
        Ok(Async::NotReady)
    }
}
impl<S, H> fmt::Debug for TcpServer<S, H>
where
    H: Factory,
    H::Item: HandleMessage,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TcpServer {{ .. }}")
    }
}

/// Action instructed by an operation of a message handler.
pub enum Action<T> {
    /// Replies an response to the client immediately.
    Reply(T),

    /// Replies an response to the client in the future.
    FutureReply(Box<dyn Future<Item = T, Error = Never> + Send + 'static>),

    /// Does not reply to the client.
    NoReply,

    /// Does not reply to the client, but does something for handling the incoming message.
    FutureNoReply(Box<dyn Future<Item = (), Error = Never> + Send + 'static>),
}
impl<T: fmt::Debug> fmt::Debug for Action<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Action::Reply(t) => write!(f, "Reply({:?})", t),
            Action::FutureReply(_) => write!(f, "FutureReply(_)"),
            Action::NoReply => write!(f, "NoReply"),
            Action::FutureNoReply(_) => write!(f, "FutureNoReply(_)"),
        }
    }
}

/// This trait allows for handling messages sent by clients.
#[allow(unused_variables)]
pub trait HandleMessage {
    /// The attributes that the handler can recognize.
    type Attribute: Attribute + Send + 'static;

    /// Handles a request message.
    ///
    /// The default implementation always returns `Action::NoReply`.
    fn handle_call(
        &mut self,
        peer: SocketAddr,
        request: Request<Self::Attribute>,
    ) -> Action<Response<Self::Attribute>> {
        Action::NoReply
    }

    /// Handles an indication message.
    ///
    /// The default implementation always returns `Action::NoReply`.
    fn handle_cast(
        &mut self,
        peer: SocketAddr,
        indication: Indication<Self::Attribute>,
    ) -> Action<Never> {
        Action::NoReply
    }

    /// Handles an invalid incoming message.
    ///
    /// Note that this method should not return `Action::Reply(_)` or `Action::FutureReply(_)`
    /// if the class of `message` is not `MessageClass::Request`.
    ///
    /// The default implementation always returns `Action::NoReply`.
    fn handle_invalid_message(
        &mut self,
        peer: SocketAddr,
        message: InvalidMessage,
    ) -> Action<Response<Self::Attribute>> {
        Action::NoReply
    }

    /// Handles an error before the channel drops by the error.
    ///
    /// The default implementation does nothing.
    fn handle_channel_error(&mut self, error: &Error) {}
}

#[derive(Debug)]
struct HandlerDriver<H, T>
where
    H: HandleMessage,
    T: StunTransport<H::Attribute, PeerAddr = SocketAddr>,
{
    spawner: BoxSpawn,
    handler: H,
    channel: Channel<H::Attribute, T>,
    response_tx: mpsc::Sender<(SocketAddr, Response<H::Attribute>)>,
    response_rx: mpsc::Receiver<(SocketAddr, Response<H::Attribute>)>,
}
impl<H, T> HandlerDriver<H, T>
where
    H: HandleMessage,
    T: StunTransport<H::Attribute, PeerAddr = SocketAddr>,
{
    fn new(spawner: BoxSpawn, handler: H, channel: Channel<H::Attribute, T>) -> Self {
        let (response_tx, response_rx) = mpsc::channel();
        HandlerDriver {
            spawner,
            handler,
            channel,
            response_tx,
            response_rx,
        }
    }

    fn handle_message(
        &mut self,
        peer: SocketAddr,
        message: RecvMessage<H::Attribute>,
    ) -> Result<()> {
        match message {
            RecvMessage::Indication(m) => self.handle_indication(peer, m),
            RecvMessage::Request(m) => track!(self.handle_request(peer, m))?,
            RecvMessage::Invalid(m) => track!(self.handle_invalid_message(peer, m))?,
        }
        Ok(())
    }

    fn handle_indication(&mut self, peer: SocketAddr, indication: Indication<H::Attribute>) {
        match self.handler.handle_cast(peer, indication) {
            Action::NoReply => {}
            Action::FutureNoReply(future) => self.spawner.spawn(future.map_err(|_| unreachable!())),
            _ => unreachable!(),
        }
    }

    fn handle_request(&mut self, peer: SocketAddr, request: Request<H::Attribute>) -> Result<()> {
        match self.handler.handle_call(peer, request) {
            Action::NoReply => {}
            Action::FutureNoReply(future) => self.spawner.spawn(future.map_err(|_| unreachable!())),
            Action::Reply(m) => track!(self.channel.reply(peer, m))?,
            Action::FutureReply(future) => {
                let tx = self.response_tx.clone();
                self.spawner.spawn(
                    future
                        .map(move |response| {
                            let _ = tx.send((peer, response));
                        })
                        .map_err(|_| unreachable!()),
                );
            }
        }
        Ok(())
    }

    fn handle_invalid_message(&mut self, peer: SocketAddr, message: InvalidMessage) -> Result<()> {
        match self.handler.handle_invalid_message(peer, message) {
            Action::NoReply => {}
            Action::FutureNoReply(future) => self.spawner.spawn(future.map_err(|_| unreachable!())),
            Action::Reply(m) => track!(self.channel.reply(peer, m))?,
            Action::FutureReply(future) => {
                let tx = self.response_tx.clone();
                self.spawner.spawn(
                    future
                        .map(move |response| {
                            let _ = tx.send((peer, response));
                        })
                        .map_err(|_| unreachable!()),
                );
            }
        }
        Ok(())
    }
}
impl<H, T> Future for HandlerDriver<H, T>
where
    H: HandleMessage,
    T: StunTransport<H::Attribute, PeerAddr = SocketAddr>,
{
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut did_something = true;
        while did_something {
            did_something = false;

            match track!(self.channel.poll_recv()) {
                Err(e) => {
                    self.handler.handle_channel_error(&e);
                    return Err(e);
                }
                Ok(Async::NotReady) => {}
                Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
                Ok(Async::Ready(Some((peer, message)))) => {
                    track!(self.handle_message(peer, message))?;
                    did_something = true;
                }
            }
            if let Err(e) = track!(self.channel.poll_send()) {
                self.handler.handle_channel_error(&e);
                return Err(e);
            }
            if let Async::Ready(item) = self.response_rx.poll().expect("never fails") {
                let (peer, response) = item.expect("never fails");
                track!(self.channel.reply(peer, response))?;
                did_something = true;
            }
        }
        Ok(Async::NotReady)
    }
}

/// Example `BINDING` request handler.
///
/// Note that this is provided only for test and example purposes.
#[derive(Debug, Default, Clone)]
pub struct BindingHandler;
impl HandleMessage for BindingHandler {
    type Attribute = rfc5389::Attribute;

    fn handle_call(
        &mut self,
        peer: SocketAddr,
        request: Request<Self::Attribute>,
    ) -> Action<Response<Self::Attribute>> {
        if request.method() == rfc5389::methods::BINDING {
            let mut response = SuccessResponse::new(&request);
            response.add_attribute(rfc5389::attributes::XorMappedAddress::new(peer).into());
            Action::Reply(Ok(response))
        } else {
            let response = ErrorResponse::new(&request, rfc5389::errors::BadRequest.into());
            Action::Reply(Err(response))
        }
    }
}
<commit_msg>Stop aborting UdpServer when it encounters errors<commit_after>//! Basic STUN servers.
//!
//! This module provides only a basic STUN servers.
//! If you want more elaborate one, please consider create your own server using [`Channel`] directly.
//!
//! [`Channel`]: ../channel/struct.Channel.html
use bytecodec::marker::Never;
use factory::DefaultFactory;
use factory::Factory;
use fibers::sync::mpsc;
use fibers::{BoxSpawn, Spawn};
use fibers_transport::{self, FixedPeerTransporter, TcpTransport, UdpTransport};
use futures::{Async, Future, Poll, Stream};
use std::fmt;
use std::net::SocketAddr;
use stun_codec::rfc5389;
use stun_codec::{Attribute, MessageDecoder, MessageEncoder};

use channel::{Channel, RecvMessage};
use message::{ErrorResponse, Indication, InvalidMessage, Request, Response, SuccessResponse};
use transport::{StunTcpTransporter, StunTransport, StunUdpTransporter};
use {Error, ErrorKind, Result};

/// The default TCP and UDP port for STUN.
pub const DEFAULT_PORT: u16 = 3478;

/// The default TLS port for STUN.
pub const DEFAULT_TLS_PORT: u16 = 5349;

type UdpTransporter<A> = fibers_transport::UdpTransporter<MessageEncoder<A>, MessageDecoder<A>>;

/// UDP based STUN server.
#[derive(Debug)]
#[must_use = "future do nothing unless polled"]
pub struct UdpServer<H: HandleMessage> {
    driver: HandlerDriver<H, StunUdpTransporter<H::Attribute, UdpTransporter<H::Attribute>>>,
}
impl<H: HandleMessage> UdpServer<H> {
    /// Starts the server.
    pub fn start<S>(
        spawner: S,
        bind_addr: SocketAddr,
        handler: H,
    ) -> impl Future<Item = Self, Error = Error>
    where
        S: Spawn + Send + 'static,
    {
        UdpTransporter::bind(bind_addr)
            .map_err(|e| track!(Error::from(e)))
            .map(move |transporter| {
                let channel = Channel::new(StunUdpTransporter::new(transporter));
                let driver = HandlerDriver::new(spawner.boxed(), handler, channel, true);
                UdpServer { driver }
            })
    }

    /// Returns the address to which the server is bound.
    pub fn local_addr(&self) -> SocketAddr {
        self.driver
            .channel
            .transporter_ref()
            .inner_ref()
            .local_addr()
    }
}
impl<H: HandleMessage> Future for UdpServer<H> {
    type Item = Never;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        if let Async::Ready(()) = track!(self.driver.poll())? {
            track_panic!(ErrorKind::Other, "STUN UDP server unexpectedly terminated");
        }
        Ok(Async::NotReady)
    }
}

type TcpListener<A> = fibers_transport::TcpListener<
    DefaultFactory<MessageEncoder<A>>,
    DefaultFactory<MessageDecoder<A>>,
>;

/// TCP based STUN server.
#[must_use = "future do nothing unless polled"]
pub struct TcpServer<S, H>
where
    H: Factory,
    H::Item: HandleMessage,
{
    spawner: S,
    handler_factory: H,
    listener: TcpListener<<H::Item as HandleMessage>::Attribute>,
}
impl<S, H> TcpServer<S, H>
where
    S: Spawn + Clone + Send + 'static,
    H: Factory,
    H::Item: HandleMessage,
{
    /// Starts the server.
    pub fn start(
        spawner: S,
        bind_addr: SocketAddr,
        handler_factory: H,
    ) -> impl Future<Item = Self, Error = Error> {
        TcpListener::listen(bind_addr)
            .map_err(|e| track!(Error::from(e)))
            .map(move |listener| TcpServer {
                spawner,
                handler_factory,
                listener,
            })
    }

    /// Returns the address to which the server is bound.
    pub fn local_addr(&self) -> SocketAddr {
        self.listener.local_addr()
    }
}
impl<S, H> Future for TcpServer<S, H>
where
    S: Spawn + Clone + Send + 'static,
    H: Factory,
    H::Item: HandleMessage + Send + 'static,
    <<H::Item as HandleMessage>::Attribute as Attribute>::Decoder: Send + 'static,
    <<H::Item as HandleMessage>::Attribute as Attribute>::Encoder: Send + 'static,
{
    type Item = Never;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        while let Async::Ready(transporter) = track!(self.listener.poll())? {
            if let Some(transporter) = transporter {
                let peer_addr = transporter.peer_addr();
                let transporter =
                    FixedPeerTransporter::new(peer_addr, (), StunTcpTransporter::new(transporter));
                let channel = Channel::new(transporter);
                let handler = self.handler_factory.create();
                let future =
                    HandlerDriver::new(self.spawner.clone().boxed(), handler, channel, false);
                self.spawner.spawn(future.map_err(|_| ()));
            } else {
                track_panic!(ErrorKind::Other, "STUN TCP server unexpectedly terminated");
            }
        }
        Ok(Async::NotReady)
    }
}
impl<S, H> fmt::Debug for TcpServer<S, H>
where
    H: Factory,
    H::Item: HandleMessage,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TcpServer {{ .. }}")
    }
}

/// Action instructed by an operation of a message handler.
pub enum Action<T> {
    /// Replies an response to the client immediately.
    Reply(T),

    /// Replies an response to the client in the future.
    FutureReply(Box<dyn Future<Item = T, Error = Never> + Send + 'static>),

    /// Does not reply to the client.
    NoReply,

    /// Does not reply to the client, but does something for handling the incoming message.
    FutureNoReply(Box<dyn Future<Item = (), Error = Never> + Send + 'static>),
}
impl<T: fmt::Debug> fmt::Debug for Action<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Action::Reply(t) => write!(f, "Reply({:?})", t),
            Action::FutureReply(_) => write!(f, "FutureReply(_)"),
            Action::NoReply => write!(f, "NoReply"),
            Action::FutureNoReply(_) => write!(f, "FutureNoReply(_)"),
        }
    }
}

/// This trait allows for handling messages sent by clients.
#[allow(unused_variables)]
pub trait HandleMessage {
    /// The attributes that the handler can recognize.
    type Attribute: Attribute + Send + 'static;

    /// Handles a request message.
    ///
    /// The default implementation always returns `Action::NoReply`.
    fn handle_call(
        &mut self,
        peer: SocketAddr,
        request: Request<Self::Attribute>,
    ) -> Action<Response<Self::Attribute>> {
        Action::NoReply
    }

    /// Handles an indication message.
    ///
    /// The default implementation always returns `Action::NoReply`.
    fn handle_cast(
        &mut self,
        peer: SocketAddr,
        indication: Indication<Self::Attribute>,
    ) -> Action<Never> {
        Action::NoReply
    }

    /// Handles an invalid incoming message.
    ///
    /// Note that this method should not return `Action::Reply(_)` or `Action::FutureReply(_)`
    /// if the class of `message` is not `MessageClass::Request`.
    ///
    /// The default implementation always returns `Action::NoReply`.
    fn handle_invalid_message(
        &mut self,
        peer: SocketAddr,
        message: InvalidMessage,
    ) -> Action<Response<Self::Attribute>> {
        Action::NoReply
    }

    /// Handles an error before the channel drops by the error.
    ///
    /// The default implementation does nothing.
    fn handle_channel_error(&mut self, error: &Error) {}
}

#[derive(Debug)]
struct HandlerDriver<H, T>
where
    H: HandleMessage,
    T: StunTransport<H::Attribute, PeerAddr = SocketAddr>,
{
    spawner: BoxSpawn,
    handler: H,
    channel: Channel<H::Attribute, T>,
    response_tx: mpsc::Sender<(SocketAddr, Response<H::Attribute>)>,
    response_rx: mpsc::Receiver<(SocketAddr, Response<H::Attribute>)>,
    recoverable_channel: bool,
}
impl<H, T> HandlerDriver<H, T>
where
    H: HandleMessage,
    T: StunTransport<H::Attribute, PeerAddr = SocketAddr>,
{
    fn new(
        spawner: BoxSpawn,
        handler: H,
        channel: Channel<H::Attribute, T>,
        recoverable_channel: bool,
    ) -> Self {
        let (response_tx, response_rx) = mpsc::channel();
        HandlerDriver {
            spawner,
            handler,
            channel,
            response_tx,
            response_rx,
            recoverable_channel,
        }
    }

    fn handle_message(
        &mut self,
        peer: SocketAddr,
        message: RecvMessage<H::Attribute>,
    ) -> Result<()> {
        match message {
            RecvMessage::Indication(m) => self.handle_indication(peer, m),
            RecvMessage::Request(m) => track!(self.handle_request(peer, m))?,
            RecvMessage::Invalid(m) => track!(self.handle_invalid_message(peer, m))?,
        }
        Ok(())
    }

    fn handle_indication(&mut self, peer: SocketAddr, indication: Indication<H::Attribute>) {
        match self.handler.handle_cast(peer, indication) {
            Action::NoReply => {}
            Action::FutureNoReply(future) => self.spawner.spawn(future.map_err(|_| unreachable!())),
            _ => unreachable!(),
        }
    }

    fn handle_request(&mut self, peer: SocketAddr, request: Request<H::Attribute>) -> Result<()> {
        match self.handler.handle_call(peer, request) {
            Action::NoReply => {}
            Action::FutureNoReply(future) => self.spawner.spawn(future.map_err(|_| unreachable!())),
            Action::Reply(m) => track!(self.channel.reply(peer, m))?,
            Action::FutureReply(future) => {
                let tx = self.response_tx.clone();
                self.spawner.spawn(
                    future
                        .map(move |response| {
                            let _ = tx.send((peer, response));
                        })
                        .map_err(|_| unreachable!()),
                );
            }
        }
        Ok(())
    }

    fn handle_invalid_message(&mut self, peer: SocketAddr, message: InvalidMessage) -> Result<()> {
        match self.handler.handle_invalid_message(peer, message) {
            Action::NoReply => {}
            Action::FutureNoReply(future) => self.spawner.spawn(future.map_err(|_| unreachable!())),
            Action::Reply(m) => track!(self.channel.reply(peer, m))?,
            Action::FutureReply(future) => {
                let tx = self.response_tx.clone();
                self.spawner.spawn(
                    future
                        .map(move |response| {
                            let _ = tx.send((peer, response));
                        })
                        .map_err(|_| unreachable!()),
                );
            }
        }
        Ok(())
    }
}
impl<H, T> Future for HandlerDriver<H, T>
where
    H: HandleMessage,
    T: StunTransport<H::Attribute, PeerAddr = SocketAddr>,
{
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        let mut did_something = true;
        while did_something {
            did_something = false;

            match track!(self.channel.poll_recv()) {
                Err(e) => {
                    self.handler.handle_channel_error(&e);
                    if !self.recoverable_channel {
                        return Err(e);
                    }
                    did_something = true;
                }
                Ok(Async::NotReady) => {}
                Ok(Async::Ready(None)) => return Ok(Async::Ready(())),
                Ok(Async::Ready(Some((peer, message)))) => {
                    track!(self.handle_message(peer, message))?;
                    did_something = true;
                }
            }
            if let Err(e) = track!(self.channel.poll_send()) {
                self.handler.handle_channel_error(&e);
                return Err(e);
            }
            if let Async::Ready(item) = self.response_rx.poll().expect("never fails") {
                let (peer, response) = item.expect("never fails");
                track!(self.channel.reply(peer, response))?;
                did_something = true;
            }
        }
        Ok(Async::NotReady)
    }
}

/// Example `BINDING` request handler.
///
/// Note that this is provided only for test and example purposes.
#[derive(Debug, Default, Clone)]
pub struct BindingHandler;
impl HandleMessage for BindingHandler {
    type Attribute = rfc5389::Attribute;

    fn handle_call(
        &mut self,
        peer: SocketAddr,
        request: Request<Self::Attribute>,
    ) -> Action<Response<Self::Attribute>> {
        if request.method() == rfc5389::methods::BINDING {
            let mut response = SuccessResponse::new(&request);
            response.add_attribute(rfc5389::attributes::XorMappedAddress::new(peer).into());
            Action::Reply(Ok(response))
        } else {
            let response = ErrorResponse::new(&request, rfc5389::errors::BadRequest.into());
            Action::Reply(Err(response))
        }
    }

    fn handle_channel_error(&mut self, error: &Error) {
        eprintln!("[ERROR] {}", error);
    }
}
<|endoftext|>


<commit_before>use std::sync::Mutex;
use std::thread;
use stopwatch;
use time;

use common::block_position::BlockPosition;
use common::communicate::{ClientToServer, ServerToClient, TerrainBlockSend};
use common::interval_timer::IntervalTimer;
use common::serialize::Copyable;
use common::surroundings_loader::LODChange;

use client::Client;
use load_terrain::{load_terrain_block, lod_index};
use server_update::apply_server_update;
use view_update::ClientToView;

pub fn update_thread<RecvServer, RecvBlock, UpdateView, UpdateServer, QueueBlock>(
  quit: &Mutex<bool>,
  client: &Client,
  recv_server: &mut RecvServer,
  recv_block: &mut RecvBlock,
  update_view: &mut UpdateView,
  update_server: &mut UpdateServer,
  queue_block: &mut QueueBlock,
) where
  RecvServer: FnMut() -> Option<ServerToClient>,
  RecvBlock: FnMut() -> Option<TerrainBlockSend>,
  UpdateView: FnMut(ClientToView),
  UpdateServer: FnMut(ClientToServer),
  QueueBlock: FnMut(TerrainBlockSend),
{
  let mut surroundings_timer = IntervalTimer::new(500_000_000, time::precise_time_ns());

  'update_loop: loop {
    if *quit.lock().unwrap() == true {
      break 'update_loop;
    } else if let Some(up) = recv_server() {
      apply_server_update(
        client,
        update_view,
        update_server,
        queue_block,
        up,
      );
    } else {
      if surroundings_timer.update(time::precise_time_ns()) > 0 {
        stopwatch::time("update_surroundings", || {
          let position = *client.player_position.lock().unwrap();
          let position = BlockPosition::from_world_position(&position);
          let mut loaded_blocks = client.loaded_blocks.lock().unwrap();
          let mut surroundings_loader = client.surroundings_loader.lock().unwrap();
          let updates =
            surroundings_loader
            .updates(position)
            .take(1 << 16)
          ;
          for lod_change in updates {
            match lod_change {
              LODChange::Load(block_position, distance) => {
                stopwatch::time("update_thread.load_block", || {
                  let lod = lod_index(distance);
                  let loaded_lod =
                    loaded_blocks
                    .get(&block_position)
                    .map(|&(_, lod)| lod);
                  if loaded_lod != Some(lod) {
                    update_server(
                      ClientToServer::RequestBlock(
                        Copyable(client.id),
                        Copyable(block_position),
                        Copyable(lod),
                      )
                    );
                  } else {
                    trace!("Not re-loading {:?} at {:?}", block_position, lod);
                  }
                })
              },
              LODChange::Unload(block_position) => {
                stopwatch::time("update_thread.unload", || {
                  // The block removal code is duplicated elsewhere.

                  loaded_blocks
                    .remove(&block_position)
                    // If it wasn't loaded, don't unload anything.
                    .map(|(block, prev_lod)| {
                      for id in &block.ids {
                        update_view(ClientToView::RemoveTerrain(*id));
                      }
                      update_view(ClientToView::RemoveBlockData(block_position, prev_lod));
                    });
                })
              },
            };
          }
        });
      } else if let Some(block) = recv_block() {
        trace!("Got block: {:?} at {:?}", block.position, block.lod);
        load_terrain_block(
          client,
          update_view,
          block,
        );
      } else {
        thread::yield_now();
      }
    }
  }
}
<commit_msg>tweak surroundings loading<commit_after>use std::sync::Mutex;
use std::thread;
use stopwatch;
use time;

use common::block_position::BlockPosition;
use common::communicate::{ClientToServer, ServerToClient, TerrainBlockSend};
use common::interval_timer::IntervalTimer;
use common::serialize::Copyable;
use common::surroundings_loader::LODChange;

use client::Client;
use load_terrain::{load_terrain_block, lod_index};
use server_update::apply_server_update;
use view_update::ClientToView;

pub fn update_thread<RecvServer, RecvBlock, UpdateView, UpdateServer, QueueBlock>(
  quit: &Mutex<bool>,
  client: &Client,
  recv_server: &mut RecvServer,
  recv_block: &mut RecvBlock,
  update_view: &mut UpdateView,
  update_server: &mut UpdateServer,
  queue_block: &mut QueueBlock,
) where
  RecvServer: FnMut() -> Option<ServerToClient>,
  RecvBlock: FnMut() -> Option<TerrainBlockSend>,
  UpdateView: FnMut(ClientToView),
  UpdateServer: FnMut(ClientToServer),
  QueueBlock: FnMut(TerrainBlockSend),
{
  let mut surroundings_timer = IntervalTimer::new(1_000_000, time::precise_time_ns());

  'update_loop: loop {
    if *quit.lock().unwrap() == true {
      break 'update_loop;
    } else if let Some(up) = recv_server() {
      apply_server_update(
        client,
        update_view,
        update_server,
        queue_block,
        up,
      );
    } else {
      if surroundings_timer.update(time::precise_time_ns()) > 0 {
        stopwatch::time("update_surroundings", || {
          let position = *client.player_position.lock().unwrap();
          let position = BlockPosition::from_world_position(&position);
          let mut loaded_blocks = client.loaded_blocks.lock().unwrap();
          let mut surroundings_loader = client.surroundings_loader.lock().unwrap();
          let updates =
            surroundings_loader
            .updates(position)
            .take(1 << 7)
          ;
          for lod_change in updates {
            match lod_change {
              LODChange::Load(block_position, distance) => {
                stopwatch::time("update_thread.load_block", || {
                  let lod = lod_index(distance);
                  let loaded_lod =
                    loaded_blocks
                    .get(&block_position)
                    .map(|&(_, lod)| lod);
                  if loaded_lod != Some(lod) {
                    update_server(
                      ClientToServer::RequestBlock(
                        Copyable(client.id),
                        Copyable(block_position),
                        Copyable(lod),
                      )
                    );
                  } else {
                    trace!("Not re-loading {:?} at {:?}", block_position, lod);
                  }
                })
              },
              LODChange::Unload(block_position) => {
                stopwatch::time("update_thread.unload", || {
                  // The block removal code is duplicated elsewhere.

                  loaded_blocks
                    .remove(&block_position)
                    // If it wasn't loaded, don't unload anything.
                    .map(|(block, prev_lod)| {
                      for id in &block.ids {
                        update_view(ClientToView::RemoveTerrain(*id));
                      }
                      update_view(ClientToView::RemoveBlockData(block_position, prev_lod));
                    });
                })
              },
            };
          }
        });
      } else if let Some(block) = recv_block() {
        trace!("Got block: {:?} at {:?}", block.position, block.lod);
        load_terrain_block(
          client,
          update_view,
          block,
        );
      } else {
        thread::yield_now();
      }
    }
  }
}
<|endoftext|>


<commit_before>use rustc_serialize::json::Json;
use handlebars::Handlebars;
use sqlite::{State, Connection, open};
use std::fs::copy;
use utilities;

pub fn load() {
    let variables = match utilities::get_variables_json() {
        Some(c) => c,
        None => return,
    };

    let sqldbs = match utilities::load_from_toml("sqldbs") {
        Some(t) => t,
        None => return,
    };

    for (sqldb, tar_path) in sqldbs {
        let src_path = format!("{}/sqldbs/{}", utilities::get_app_dir(), &sqldb);
        let tar_path = match utilities::path_value_to_string(&tar_path) {
            Some(s) => s,
            None => {
                println!("Failed copying {}: {} is not a valid path String.",
                         &sqldb,
                         &tar_path);
                continue;
            }
        };

        let create_dirs_success = utilities::create_directories_for_file(&tar_path);
        if !create_dirs_success {
            println!("Failed copying {}: Could not create one or more directories required.",
                     &sqldb);
            continue;
        }

        let copy_success = copy(&src_path, &tar_path).is_ok();
        if !copy_success {
            println!("Failed copying {}: Could not copy file.", &sqldb);
            continue;
        }

        let render_success = render_db(&tar_path, &variables);
        if !render_success {
            println!("Failed copying {}: Unable to render DB.", &sqldb);
            continue;
        }
    }
}

fn render_db(db_path: &str, template_data: &Json) -> bool {
    let db_connection = match open(&db_path) {
        Ok(db) => db,
        Err(_) => {
            println!("Could not find {}.", db_path);
            return false;
        }
    };

    let tables = get_vec_from_db(&db_connection,
                                 "SELECT tbl_name FROM sqlite_master WHERE type = 'table';",
                                 0);

    for table in tables {
        let columns = get_vec_from_db(&db_connection, &format!("PRAGMA table_info({});", table), 1);

        for column in columns {
            let current_entries = get_vec_from_db(&db_connection,
                                                  &format!("SELECT {} FROM {};", column, table),
                                                  0);

            for current_entry in current_entries {
                let current_entry = current_entry.replace("'", "''");

                let mut new_entry = current_entry.clone();
                let handlebars = Handlebars::new();
                new_entry = match handlebars.template_render(&new_entry, template_data) {
                    Ok(rendered_str) => rendered_str,
                    Err(_) => {
                        println!("Error while rendering DB: Could not render {}",
                                 current_entry);
                        continue;
                    }
                };

                db_connection.execute(&format!("UPDATE {} SET {} = '{}' WHERE {} = '{}';",
                                      table,
                                      column,
                                      new_entry,
                                      column,
                                      current_entry))
                    .unwrap();
            }
        }
    }
    true
}

fn get_vec_from_db(db_conn: &Connection, query: &str, index: usize) -> Vec<String> {
    let mut tables = Vec::new();
    let mut statement = match db_conn.prepare(query) {
        Ok(s) => s,
        Err(_) => return Vec::new(),
    };

    while let State::Row = match statement.next() {
        Ok(o) => o,
        Err(_) => return Vec::new(),
    } {
        match statement.read::<String>(index) {
            Ok(s) => tables.push(s),
            Err(_) => continue,
        };
    }

    tables
}
<commit_msg>Removed unsafe unwrap.<commit_after>use rustc_serialize::json::Json;
use handlebars::Handlebars;
use sqlite::{State, Connection, open};
use std::fs::copy;
use utilities;

pub fn load() {
    let variables = match utilities::get_variables_json() {
        Some(c) => c,
        None => return,
    };

    let sqldbs = match utilities::load_from_toml("sqldbs") {
        Some(t) => t,
        None => return,
    };

    for (sqldb, tar_path) in sqldbs {
        let src_path = format!("{}/sqldbs/{}", utilities::get_app_dir(), &sqldb);
        let tar_path = match utilities::path_value_to_string(&tar_path) {
            Some(s) => s,
            None => {
                println!("Failed copying {}: {} is not a valid path String.",
                         &sqldb,
                         &tar_path);
                continue;
            }
        };

        let create_dirs_success = utilities::create_directories_for_file(&tar_path);
        if !create_dirs_success {
            println!("Failed copying {}: Could not create one or more directories required.",
                     &sqldb);
            continue;
        }

        let copy_success = copy(&src_path, &tar_path).is_ok();
        if !copy_success {
            println!("Failed copying {}: Could not copy file.", &sqldb);
            continue;
        }

        let render_success = render_db(&tar_path, &variables);
        if !render_success {
            println!("Failed copying {}: Unable to render DB.", &sqldb);
            continue;
        }
    }
}

fn render_db(db_path: &str, template_data: &Json) -> bool {
    let db_connection = match open(&db_path) {
        Ok(db) => db,
        Err(_) => {
            println!("Could not find {}.", db_path);
            return false;
        }
    };

    let tables = get_vec_from_db(&db_connection,
                                 "SELECT tbl_name FROM sqlite_master WHERE type = 'table';",
                                 0);

    for table in tables {
        let columns = get_vec_from_db(&db_connection, &format!("PRAGMA table_info({});", table), 1);

        for column in columns {
            let current_entries = get_vec_from_db(&db_connection,
                                                  &format!("SELECT {} FROM {};", column, table),
                                                  0);

            for current_entry in current_entries {
                let current_entry = current_entry.replace("'", "''");

                let mut new_entry = current_entry.clone();
                let handlebars = Handlebars::new();
                new_entry = match handlebars.template_render(&new_entry, template_data) {
                    Ok(rendered_str) => rendered_str,
                    Err(_) => {
                        println!("Error while rendering DB: Could not render {}",
                                 current_entry);
                        continue;
                    }
                };

                let _ = db_connection.execute(&format!("UPDATE {} SET {} = '{}' WHERE {} = '{}';",
                                                       &table,
                                                       &column,
                                                       &new_entry,
                                                       &column,
                                                       &current_entry));
            }
        }
    }
    true
}

fn get_vec_from_db(db_conn: &Connection, query: &str, index: usize) -> Vec<String> {
    let mut tables = Vec::new();
    let mut statement = match db_conn.prepare(query) {
        Ok(s) => s,
        Err(_) => return Vec::new(),
    };

    while let State::Row = match statement.next() {
        Ok(o) => o,
        Err(_) => return Vec::new(),
    } {
        match statement.read::<String>(index) {
            Ok(s) => tables.push(s),
            Err(_) => continue,
        };
    }

    tables
}
<|endoftext|>