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

use hex;
use std::io::ErrorKind;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use time;

use byteorder::{LittleEndian, WriteBytesExt};

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

use config::ServerConfig;
use key::{LongTermKey, OnlineKey};
use kms;
use merkle::MerkleTree;
use MIN_REQUEST_LENGTH;
use {Error, RtMessage, Tag};

macro_rules! check_ctrlc {
    ($keep_running:expr) => {
        if !$keep_running.load(Ordering::Acquire) {
            warn!("Ctrl-C caught, exiting...");
            return true;
        }
    };
}

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

/// The main server instance.
/// A Server is initialiezd from a Server Config
/// and processes incoming messages in
/// 'process_events'
pub struct Server {
    config: Box<ServerConfig>,
    online_key: OnlineKey,
    cert_bytes: Vec<u8>,

    response_counter: AtomicUsize,
    num_bad_requests: u64,

    socket: UdpSocket,
    keep_running: Arc<AtomicBool>,
    poll_duration: Option<Duration>,
    timer: Timer<()>,
    poll: Poll,
    events: Events,
    merkle: MerkleTree,
    requests: Vec<(Vec<u8>, SocketAddr)>,
    buf: [u8; 65_536],

    public_key: String,

    // Used to send requests to outselves in fuzing mode
    #[cfg(fuzzing)]
    fake_client_socket: UdpSocket,
}

impl Server {
    pub fn new(config: Box<ServerConfig>) -> Server {
        let online_key = OnlineKey::new();
        let public_key: String;

        let cert_bytes = {
            let seed = kms::load_seed(&config).unwrap();
            let mut long_term_key = LongTermKey::new(&seed);
            public_key = hex::encode(long_term_key.public_key());

            long_term_key.make_cert(&online_key).encode().unwrap()
        };

        let response_counter = AtomicUsize::new(0);
        let keep_running = Arc::new(AtomicBool::new(true));

        let sock_addr = config.socket_addr().expect("");
        let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");

        let poll_duration = Some(Duration::from_millis(100));

        let mut timer: Timer<()> = Timer::default();
        timer.set_timeout(config.status_interval(), ());

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

        let merkle = MerkleTree::new();
        let requests = Vec::with_capacity(config.batch_size() as usize);

        Server {
            config,
            online_key,
            cert_bytes,

            response_counter,
            num_bad_requests: 0,
            socket,
            keep_running,
            poll_duration,
            timer,
            poll,
            events: Events::with_capacity(32),
            merkle,
            requests,
            buf: [0u8; 65_536],

            public_key,

            #[cfg(fuzzing)]
            fake_client_socket: UdpSocket::bind(&"127.0.0.1:0".parse().unwrap()).unwrap(),
        }
    }

    pub fn get_keep_running(&self) -> Arc<AtomicBool> {
        return self.keep_running.clone();
    }

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

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

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

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

    fn make_response(
        &self,
        srep: &RtMessage,
        cert_bytes: &[u8],
        path: &[u8],
        idx: u32,
    ) -> RtMessage {
        let mut index = [0; 4];
        (&mut index as &mut [u8])
            .write_u32::<LittleEndian>(idx)
            .unwrap();

        let sig_bytes = srep.get_field(Tag::SIG).unwrap();
        let srep_bytes = srep.get_field(Tag::SREP).unwrap();

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

        response
    }

    /// The main processing function for incoming connections.
    /// This method should be called repeatedly in a loop
    /// to process requests. It returns 'true' when the server
    /// has shutdown (due to keep_running being set to 'false')
    pub fn process_events(&mut self) -> bool {
        self.poll
            .poll(&mut self.events, self.poll_duration)
            .expect("poll failed");

        for event in self.events.iter() {
            match event.token() {
                MESSAGE => {
                    let mut done = false;

                    'process_batch: loop {
                        check_ctrlc!(self.keep_running);

                        let resp_start = self.response_counter.load(Ordering::SeqCst);

                        for i in 0..self.config.batch_size() {
                            match self.socket.recv_from(&mut self.buf) {
                                Ok((num_bytes, src_addr)) => {
                                    match self.nonce_from_request(&self.buf, num_bytes) {
                                        Ok(nonce) => {
                                            self.requests.push((Vec::from(nonce), src_addr));
                                            self.merkle.push_leaf(nonce);
                                        }
                                        Err(e) => {
                                            self.num_bad_requests += 1;

                                            info!(
                                                "Invalid request: '{:?}' ({} bytes) from {} (#{} in batch, resp #{})",
                                                e, num_bytes, src_addr, i, resp_start + i as usize
                                            );
                                        }
                                    }
                                }
                                Err(e) => match e.kind() {
                                    ErrorKind::WouldBlock => {
                                        done = true;
                                        break;
                                    }
                                    _ => {
                                        error!(
                                            "Error receiving from socket: {:?}: {:?}",
                                            e.kind(),
                                            e
                                        );
                                        break;
                                    }
                                },
                            };
                        }

                        if self.requests.is_empty() {
                            break 'process_batch;
                        }

                        let merkle_root = self.merkle.compute_root();
                        let srep = self.online_key.make_srep(time::get_time(), &merkle_root);

                        for (i, &(ref nonce, ref src_addr)) in self.requests.iter().enumerate() {
                            let paths = self.merkle.get_paths(i);

                            let resp =
                                self.make_response(&srep, &self.cert_bytes, &paths, i as u32);
                            let resp_bytes = resp.encode().unwrap();

                            let bytes_sent = self
                                .socket
                                .send_to(&resp_bytes, &src_addr)
                                .expect("send_to failed");
                            let num_responses =
                                self.response_counter.fetch_add(1, Ordering::SeqCst);

                            info!(
                                "Responded {} bytes to {} for '{}..' (#{} in batch, resp #{})",
                                bytes_sent,
                                src_addr,
                                hex::encode(&nonce[0..4]),
                                i,
                                num_responses
                            );
                        }

                        self.merkle.reset();
                        self.requests.clear();

                        if done {
                            break 'process_batch;
                        }
                    }
                }

                STATUS => {
                    info!(
                        "responses {}, invalid requests {}",
                        self.response_counter.load(Ordering::SeqCst),
                        self.num_bad_requests
                    );

                    self.timer.set_timeout(self.config.status_interval(), ());
                }

                _ => unreachable!(),
            }
        }
        false
    }

    #[cfg(fuzzing)]
    pub fn send_to_self(&mut self, data: &[u8]) {
        self.response_counter.store(0, Ordering::SeqCst);;
        self.num_bad_requests = 0;
        let res = self
            .fake_client_socket
            .send_to(data, &self.socket.local_addr().unwrap());
        info!("Sent to self: {:?}", res);
    }

    pub fn get_public_key(&self) -> &str {
        return &self.public_key;
    }

    pub fn get_online_key(&self) -> &OnlineKey {
        return &self.online_key;
    }

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

use hex;
use std::io::ErrorKind;
use std::net::SocketAddr;
use std::process;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::time::Duration;
use time;

use byteorder::{LittleEndian, WriteBytesExt};

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

use config::ServerConfig;
use key::{LongTermKey, OnlineKey};
use kms;
use merkle::MerkleTree;
use MIN_REQUEST_LENGTH;
use {Error, RtMessage, Tag};

macro_rules! check_ctrlc {
    ($keep_running:expr) => {
        if !$keep_running.load(Ordering::Acquire) {
            warn!("Ctrl-C caught, exiting...");
            return true;
        }
    };
}

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

/// The main server instance.
/// A Server is initialiezd from a Server Config
/// and processes incoming messages in
/// 'process_events'
pub struct Server {
    config: Box<ServerConfig>,
    online_key: OnlineKey,
    cert_bytes: Vec<u8>,

    response_counter: AtomicUsize,
    num_bad_requests: u64,

    socket: UdpSocket,
    keep_running: Arc<AtomicBool>,
    poll_duration: Option<Duration>,
    timer: Timer<()>,
    poll: Poll,
    events: Events,
    merkle: MerkleTree,
    requests: Vec<(Vec<u8>, SocketAddr)>,
    buf: [u8; 65_536],

    public_key: String,

    // Used to send requests to outselves in fuzing mode
    #[cfg(fuzzing)]
    fake_client_socket: UdpSocket,
}

impl Server {
    pub fn new(config: Box<ServerConfig>) -> Server {
        let online_key = OnlineKey::new();
        let public_key: String;

        let cert_bytes = {
            let seed = match kms::load_seed(&config) {
                Ok(seed) => seed,
                Err(e) => {
                    error!("Failed to load seed: {:#?}", e);
                    process::exit(1);
                }
            };
            let mut long_term_key = LongTermKey::new(&seed);
            public_key = hex::encode(long_term_key.public_key());

            long_term_key.make_cert(&online_key).encode().unwrap()
        };

        let response_counter = AtomicUsize::new(0);
        let keep_running = Arc::new(AtomicBool::new(true));

        let sock_addr = config.socket_addr().expect("");
        let socket = UdpSocket::bind(&sock_addr).expect("failed to bind to socket");

        let poll_duration = Some(Duration::from_millis(100));

        let mut timer: Timer<()> = Timer::default();
        timer.set_timeout(config.status_interval(), ());

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

        let merkle = MerkleTree::new();
        let requests = Vec::with_capacity(config.batch_size() as usize);

        Server {
            config,
            online_key,
            cert_bytes,

            response_counter,
            num_bad_requests: 0,
            socket,
            keep_running,
            poll_duration,
            timer,
            poll,
            events: Events::with_capacity(32),
            merkle,
            requests,
            buf: [0u8; 65_536],

            public_key,

            #[cfg(fuzzing)]
            fake_client_socket: UdpSocket::bind(&"127.0.0.1:0".parse().unwrap()).unwrap(),
        }
    }

    pub fn get_keep_running(&self) -> Arc<AtomicBool> {
        return self.keep_running.clone();
    }

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

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

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

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

    fn make_response(
        &self,
        srep: &RtMessage,
        cert_bytes: &[u8],
        path: &[u8],
        idx: u32,
    ) -> RtMessage {
        let mut index = [0; 4];
        (&mut index as &mut [u8])
            .write_u32::<LittleEndian>(idx)
            .unwrap();

        let sig_bytes = srep.get_field(Tag::SIG).unwrap();
        let srep_bytes = srep.get_field(Tag::SREP).unwrap();

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

        response
    }

    /// The main processing function for incoming connections.
    /// This method should be called repeatedly in a loop
    /// to process requests. It returns 'true' when the server
    /// has shutdown (due to keep_running being set to 'false')
    pub fn process_events(&mut self) -> bool {
        self.poll
            .poll(&mut self.events, self.poll_duration)
            .expect("poll failed");

        for event in self.events.iter() {
            match event.token() {
                MESSAGE => {
                    let mut done = false;

                    'process_batch: loop {
                        check_ctrlc!(self.keep_running);

                        let resp_start = self.response_counter.load(Ordering::SeqCst);

                        for i in 0..self.config.batch_size() {
                            match self.socket.recv_from(&mut self.buf) {
                                Ok((num_bytes, src_addr)) => {
                                    match self.nonce_from_request(&self.buf, num_bytes) {
                                        Ok(nonce) => {
                                            self.requests.push((Vec::from(nonce), src_addr));
                                            self.merkle.push_leaf(nonce);
                                        }
                                        Err(e) => {
                                            self.num_bad_requests += 1;

                                            info!(
                                                "Invalid request: '{:?}' ({} bytes) from {} (#{} in batch, resp #{})",
                                                e, num_bytes, src_addr, i, resp_start + i as usize
                                            );
                                        }
                                    }
                                }
                                Err(e) => match e.kind() {
                                    ErrorKind::WouldBlock => {
                                        done = true;
                                        break;
                                    }
                                    _ => {
                                        error!(
                                            "Error receiving from socket: {:?}: {:?}",
                                            e.kind(),
                                            e
                                        );
                                        break;
                                    }
                                },
                            };
                        }

                        if self.requests.is_empty() {
                            break 'process_batch;
                        }

                        let merkle_root = self.merkle.compute_root();
                        let srep = self.online_key.make_srep(time::get_time(), &merkle_root);

                        for (i, &(ref nonce, ref src_addr)) in self.requests.iter().enumerate() {
                            let paths = self.merkle.get_paths(i);

                            let resp =
                                self.make_response(&srep, &self.cert_bytes, &paths, i as u32);
                            let resp_bytes = resp.encode().unwrap();

                            let bytes_sent = self
                                .socket
                                .send_to(&resp_bytes, &src_addr)
                                .expect("send_to failed");
                            let num_responses =
                                self.response_counter.fetch_add(1, Ordering::SeqCst);

                            info!(
                                "Responded {} bytes to {} for '{}..' (#{} in batch, resp #{})",
                                bytes_sent,
                                src_addr,
                                hex::encode(&nonce[0..4]),
                                i,
                                num_responses
                            );
                        }

                        self.merkle.reset();
                        self.requests.clear();

                        if done {
                            break 'process_batch;
                        }
                    }
                }

                STATUS => {
                    info!(
                        "responses {}, invalid requests {}",
                        self.response_counter.load(Ordering::SeqCst),
                        self.num_bad_requests
                    );

                    self.timer.set_timeout(self.config.status_interval(), ());
                }

                _ => unreachable!(),
            }
        }
        false
    }

    #[cfg(fuzzing)]
    pub fn send_to_self(&mut self, data: &[u8]) {
        self.response_counter.store(0, Ordering::SeqCst);;
        self.num_bad_requests = 0;
        let res = self
            .fake_client_socket
            .send_to(data, &self.socket.local_addr().unwrap());
        info!("Sent to self: {:?}", res);
    }

    pub fn get_public_key(&self) -> &str {
        return &self.public_key;
    }

    pub fn get_online_key(&self) -> &OnlineKey {
        return &self.online_key;
    }

    pub fn get_config(&self) -> &Box<ServerConfig> {
        return &self.config;
    }
}
<|endoftext|>


<commit_before>use std;
use std::thread;
use std::time::Duration;
use termion::color;
use termion::clear;
use termion::cursor;
use rand;

use websocket::{WebSocketStream, Server};
use websocket::Message as WebMessage;
use websocket::Sender as WebSender;
use websocket::client::Sender as WebClientSender;
use websocket::Receiver as WebReceiver;
use websocket::message::Type as WebMessageType;
use websocket::server::Connection;
use websocket::header::WebSocketProtocol;

use state::generate;
use state::State;

extern crate fsevent;
use self::fsevent::{ITEM_MODIFIED, ITEM_CREATED, ITEM_REMOVED};
use self::fsevent::Event as FsEvent;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;

use git2::Repository;

use serde_xml as xml;

const HEARTBEAT: u64 = 250;

#[derive(Debug)]
enum NotifierMessage<'a> {
    WebMessage(WebMessage<'a>),
    FsEvent(FsEvent)
}

pub fn start(port: i32) -> Result<Server<'static>, std::io::Error> {
    let host = format!("127.0.0.1:{}", port);
    Server::bind(host)
}

pub fn connect(connection: Connection<WebSocketStream, WebSocketStream>) {
    let request = connection.read_request().unwrap();
    let headers = request.headers.clone();
    request.validate().unwrap();

    let mut response = request.accept();
    println!("Connected");

    if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
        if protocols.contains(&("superconductor".to_string())) {
            response.headers.set(WebSocketProtocol(vec!["superconductor".to_string()]));
        }
    }

    let mut client = response.send().unwrap();
    let message = WebMessage::text(generate(None));
    client.send_message(&message).unwrap();

    let (tx, rx) = channel::<NotifierMessage>();
    let (sender, mut receiver) = client.split();
    let notifier = thread::spawn(move || start_notifier(rx, sender));
    let monitor_tx = tx.clone();
    let monitor = thread::spawn(move || start_monitor(monitor_tx));
    let updater_tx = tx.clone();
    let updater = thread::spawn(move || start_updater(updater_tx));
    for message in receiver.incoming_messages() {
        let message: WebMessage = message.unwrap_or(WebMessage::close());
        match message.opcode {
            WebMessageType::Close => {
                tx.send(NotifierMessage::WebMessage(message)).unwrap();
                break;
            },
            _ => tx.send(NotifierMessage::WebMessage(message))
        }.unwrap();
    }
    monitor.join().unwrap();
    notifier.join().unwrap();
    updater.join().unwrap();
}

fn start_monitor(tx: Sender<NotifierMessage>) {
    let (ftx, rx) = channel();
    let observer = thread::spawn(move || {
        println!("Monitoring");
        let fsevent = fsevent::FsEvent::new(ftx);
        fsevent.append_path(".");
        fsevent.observe();
    });
    loop {
        let event = rx.recv().unwrap();
        thread::sleep(Duration::from_millis(HEARTBEAT));
        let mut changes = vec![event];
        loop {
            if let Ok(event) = rx.try_recv() {
                if (event.flag.contains(ITEM_MODIFIED) || event.flag.contains(ITEM_CREATED) || event.flag.contains(ITEM_REMOVED)) && (!event.path.contains(".git") || !event.path.contains(".lock")) {
                    changes.push(event);
                }
            } else {
                break;
            }
        }
        if !changes.is_empty() {
            if tx.send(NotifierMessage::FsEvent(changes.pop().unwrap())).is_err() {
                break;
            };
        }
    }
    observer.join().unwrap();
}

fn start_notifier(rx: Receiver<NotifierMessage>, mut sender: WebClientSender<WebSocketStream>) {
    let mut last_state: Option<State> = None;
    let mut rng = rand::thread_rng();
    loop {
        let event = rx.recv().unwrap();
        match event {
            NotifierMessage::WebMessage(message) => {
                match message.opcode {
                    WebMessageType::Close => {
                        break;
                    },
                    WebMessageType::Ping => {
                        let message = WebMessage::pong(message.payload);
                        sender.send_message(&message).unwrap();
                    },
                    _ => {
                        let payload = String::from_utf8_lossy(message.payload.as_ref());
                        //println!("\n\n{}{}{}{}{}", clear::All, cursor::Goto(1, 1), color::Fg(color::White), payload, color::Fg(color::Reset));
                        let mut state: State = xml::from_str(&payload).unwrap_or(last_state.clone().unwrap_or(State::blank()));

                        last_state = state.apply(last_state, &mut rng).unwrap();
                        let message = WebMessage::text(generate(Some(state)));
                        sender.send_message(&message).unwrap();

                        thread::sleep(Duration::from_millis(HEARTBEAT));
                        flush(&rx);
                    }
                }
            },
            NotifierMessage::FsEvent(_event) => {
                //let message = WebMessage::text("submit");
                //sender.send_message(&message).unwrap();
            }
        }
    }
}

fn start_updater(tx: Sender<NotifierMessage>) {
    loop {
        thread::sleep(Duration::from_secs(300));
        let repo = Repository::open_from_env().unwrap_or(Repository::init(".").unwrap());
        if let Ok(mut origin) = repo.find_remote("origin") {
            println!("Updating from remote...");
            origin.fetch(&["master"], None, None);
        };
    }
}

fn flush<T>(channel: &Receiver<T>) {
    let mut flushed: i32 = 0;
    while channel.try_recv().is_ok() {
        flushed += 1;
    }
    let plural = if flushed != 1 { 's' } else { ' ' };
    println!("  {}Flushed {} event{}{}", color::Fg(color::Yellow), flushed, plural, color::Fg(color::Reset));
}
<commit_msg>Sends initial state through the notifier to persist last state<commit_after>use std;
use std::thread;
use std::time::Duration;
use termion::color;
use termion::clear;
use termion::cursor;
use rand;

use websocket::{WebSocketStream, Server};
use websocket::Message as WebMessage;
use websocket::Sender as WebSender;
use websocket::client::Sender as WebClientSender;
use websocket::Receiver as WebReceiver;
use websocket::message::Type as WebMessageType;
use websocket::server::Connection;
use websocket::header::WebSocketProtocol;

use state::generate;
use state::State;

extern crate fsevent;
use self::fsevent::{ITEM_MODIFIED, ITEM_CREATED, ITEM_REMOVED};
use self::fsevent::Event as FsEvent;
use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;

use git2::Repository;

use serde_xml as xml;

const HEARTBEAT: u64 = 250;

#[derive(Debug)]
enum NotifierMessage<'a> {
    WebMessage(WebMessage<'a>),
    FsEvent(FsEvent)
}

pub fn start(port: i32) -> Result<Server<'static>, std::io::Error> {
    let host = format!("127.0.0.1:{}", port);
    Server::bind(host)
}

pub fn connect(connection: Connection<WebSocketStream, WebSocketStream>) {
    let request = connection.read_request().unwrap();
    let headers = request.headers.clone();
    request.validate().unwrap();

    let mut response = request.accept();
    println!("Connected");

    if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
        if protocols.contains(&("superconductor".to_string())) {
            response.headers.set(WebSocketProtocol(vec!["superconductor".to_string()]));
        }
    }

    let mut client = response.send().unwrap();

    let (tx, rx) = channel::<NotifierMessage>();
    let (sender, mut receiver) = client.split();
    let notifier = thread::spawn(move || start_notifier(rx, sender));

    let message = WebMessage::text(generate(None));
    tx.send(NotifierMessage::WebMessage(message)).unwrap();

    let monitor_tx = tx.clone();
    let monitor = thread::spawn(move || start_monitor(monitor_tx));

    let updater_tx = tx.clone();
    let updater = thread::spawn(move || start_updater(updater_tx));

    for message in receiver.incoming_messages() {
        let message: WebMessage = message.unwrap_or(WebMessage::close());
        match message.opcode {
            WebMessageType::Close => {
                tx.send(NotifierMessage::WebMessage(message)).unwrap();
                break;
            },
            _ => tx.send(NotifierMessage::WebMessage(message))
        }.unwrap();
    }

    monitor.join().unwrap();
    notifier.join().unwrap();
    updater.join().unwrap();
}

fn start_monitor(tx: Sender<NotifierMessage>) {
    let (ftx, rx) = channel();
    let observer = thread::spawn(move || {
        println!("Monitoring");
        let fsevent = fsevent::FsEvent::new(ftx);
        fsevent.append_path(".");
        fsevent.observe();
    });
    loop {
        let event = rx.recv().unwrap();
        thread::sleep(Duration::from_millis(HEARTBEAT));
        let mut changes = vec![event];
        loop {
            if let Ok(event) = rx.try_recv() {
                if (event.flag.contains(ITEM_MODIFIED) || event.flag.contains(ITEM_CREATED) || event.flag.contains(ITEM_REMOVED)) && (!event.path.contains(".git") || !event.path.contains(".lock")) {
                    changes.push(event);
                }
            } else {
                break;
            }
        }
        if !changes.is_empty() {
            if tx.send(NotifierMessage::FsEvent(changes.pop().unwrap())).is_err() {
                break;
            };
        }
    }
    observer.join().unwrap();
}

fn start_notifier(rx: Receiver<NotifierMessage>, mut sender: WebClientSender<WebSocketStream>) {
    let mut last_state: Option<State> = None;
    let mut rng = rand::thread_rng();
    loop {
        let event = rx.recv().unwrap();
        match event {
            NotifierMessage::WebMessage(message) => {
                match message.opcode {
                    WebMessageType::Close => {
                        break;
                    },
                    WebMessageType::Ping => {
                        let message = WebMessage::pong(message.payload);
                        sender.send_message(&message).unwrap();
                    },
                    _ => {
                        let payload = String::from_utf8_lossy(message.payload.as_ref());
                        //println!("\n\n{}{}{}{}{}", clear::All, cursor::Goto(1, 1), color::Fg(color::White), payload, color::Fg(color::Reset));
                        let mut state: State = xml::from_str(&payload).unwrap_or(last_state.clone().unwrap_or(State::blank()));

                        last_state = state.apply(last_state, &mut rng).unwrap();
                        let message = WebMessage::text(generate(Some(state)));
                        sender.send_message(&message).unwrap();

                        thread::sleep(Duration::from_millis(HEARTBEAT));
                        flush(&rx);
                    }
                }
            },
            NotifierMessage::FsEvent(_event) => {
                //let message = WebMessage::text("submit");
                //sender.send_message(&message).unwrap();
            }
        }
    }
}

fn start_updater(tx: Sender<NotifierMessage>) {
    loop {
        thread::sleep(Duration::from_secs(300));
        let repo = Repository::open_from_env().unwrap_or(Repository::init(".").unwrap());
        if let Ok(mut origin) = repo.find_remote("origin") {
            println!("Updating from remote...");
            origin.fetch(&["master"], None, None);
        };
    }
}

fn flush<T>(channel: &Receiver<T>) {
    let mut flushed: i32 = 0;
    while channel.try_recv().is_ok() {
        flushed += 1;
    }
    let plural = if flushed != 1 { 's' } else { ' ' };
    println!("  {}Flushed {} event{}{}", color::Fg(color::Yellow), flushed, plural, color::Fg(color::Reset));
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;
use std::net::{SocketAddr};
use std::io;

use mio::deprecated::{EventLoop, Handler, TryWrite};
use mio::*;
use mio::tcp::*;
use bytes::buf::{Buf, ByteBuf};

use packet::{Packet, EofError};
use queues::QueueHolder;
use worker::Worker;

struct GearmanRemote {
    socket: TcpStream,
    addr: SocketAddr,
    packet: Packet,
    queues: QueueHolder,
    worker: Worker,
    sendqueue: Vec<ByteBuf>,
    interest: Ready,
    token: Token,
}

pub struct GearmanServer {
    pub socket: TcpListener,
    remotes: HashMap<Token, GearmanRemote>,
    token_counter: usize,
    queues: QueueHolder,
}

const SERVER_TOKEN: Token = Token(0);

impl GearmanRemote {
    pub fn new(socket: TcpStream, addr: SocketAddr, queues: QueueHolder, token: Token) -> GearmanRemote {
        GearmanRemote {
            socket: socket,
            addr: addr,
            packet: Packet::new(token),
            queues: queues,
            worker: Worker::new(),
            sendqueue: Vec::with_capacity(2), // Don't need many bufs
            interest: Ready::readable(),
            token: token,
        }
    }

    pub fn read(&mut self) -> Result<(), EofError> {
        match self.packet.from_socket(&mut self.socket, &mut self.worker, self.queues.clone(), self.token)? {
            None => debug!("Done reading"),
            Some(p) => {
                info!("Queueing {:?}", &p);
                self.sendqueue.push(ByteBuf::from_slice(&p.to_byteslice()));
                self.interest.remove(Ready::readable());
                self.interest.insert(Ready::writable());
            }
        }
        // Packet is consumed, reset
        self.packet = Packet::new(self.token);
        Ok(())
    }

    pub fn write(&mut self) -> Result<(), io::Error> {
        while !self.sendqueue.is_empty() {
            if !self.sendqueue.first().unwrap().has_remaining() {
                self.sendqueue.pop();
                continue;
            }
            let buf = self.sendqueue.first_mut().unwrap();
            match self.socket.try_write(buf.bytes())? {
                None => break,
                Some(n) => {
                    buf.advance(n);
                    continue
                }
            };
        }
        if self.sendqueue.is_empty() {
            self.interest.remove(Ready::writable());
            self.interest.insert(Ready::readable());
        };
        Ok(())
    }

    pub fn shutdown(self) {
        match self.worker.job {
            Some(j) => {
                self.queues.clone().add_job(j)
            },
            None => {},
        }
        self.socket.shutdown(Shutdown::Both).unwrap();
    }
}

impl fmt::Display for GearmanRemote {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Remote {{ addr: {:?} }}", self.addr)
    }
}

impl GearmanServer {
    pub fn new(server_socket: TcpListener, queues: QueueHolder) -> GearmanServer {
        GearmanServer {
            token_counter: 1,
            remotes: HashMap::new(),
            socket: server_socket,
            queues: queues,
        }
    }

}

impl Handler for GearmanServer {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<GearmanServer>,
             token: Token, events: Ready)
    {
        if events.is_readable() {
            match token {
                SERVER_TOKEN => {
                    let (remote_socket, remote_addr) = match self.socket.accept() {
                        Err(e) => {
                            error!("Accept error: {}", e);
                            return;
                        },
                        Ok((sock, addr)) => (sock, addr),
                    };

                    self.token_counter += 1;
                    let new_token = Token(self.token_counter);

                    self.remotes.insert(new_token, GearmanRemote::new(remote_socket, remote_addr, self.queues.clone(), new_token));

                    event_loop.register(&self.remotes[&new_token].socket,
                                        new_token, Ready::readable(),
                                        PollOpt::edge() | PollOpt::oneshot()).unwrap();
                },
                token => {
                    let mut shutdown = false;
                    {
                        let mut remote = self.remotes.get_mut(&token).unwrap();
                        match remote.read() {
                            Ok(_) => event_loop.reregister(&remote.socket, token, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap(),
                            Err(e) => {
                                info!("remote({}) hung up: {:?}", &remote, e);
                                shutdown = true;
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }

        if events.is_writable() {
            match token {
                SERVER_TOKEN => panic!("Received writable event for server socket."),
                token => {
                    let mut shutdown = false;
                    {
                        let mut remote = self.remotes.get_mut(&token).unwrap();
                        match remote.write() {
                            Ok(_) => event_loop.reregister(&remote.socket, token, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap(),
                            Err(e) => {
                                info!("remote({}) hung up: {}", &remote, e);
                                shutdown = true;
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }
    }
}
<commit_msg>Return WORK_COMPLETE to clients<commit_after>use std::collections::HashMap;
use std::fmt;
use std::net::{SocketAddr};
use std::io;

use mio::deprecated::{EventLoop, Handler, TryWrite};
use mio::*;
use mio::tcp::*;
use bytes::buf::{Buf, ByteBuf};

use packet::{Packet, EofError};
use queues::QueueHolder;
use worker::Worker;

struct GearmanRemote {
    socket: TcpStream,
    addr: SocketAddr,
    packet: Packet,
    queues: QueueHolder,
    worker: Worker,
    sendqueue: Vec<ByteBuf>,
    interest: Ready,
    token: Token,
}

pub struct GearmanServer {
    pub socket: TcpListener,
    remotes: HashMap<Token, GearmanRemote>,
    token_counter: usize,
    queues: QueueHolder,
}

const SERVER_TOKEN: Token = Token(0);

impl GearmanRemote {
    pub fn new(socket: TcpStream, addr: SocketAddr, queues: QueueHolder, token: Token) -> GearmanRemote {
        GearmanRemote {
            socket: socket,
            addr: addr,
            packet: Packet::new(token),
            queues: queues,
            worker: Worker::new(),
            sendqueue: Vec::with_capacity(2), // Don't need many bufs
            interest: Ready::readable(),
            token: token,
        }
    }

    pub fn queue_packet(&mut self, packet: &Packet) {
        info!("{} Queueing {:?}", self, &packet);
        self.sendqueue.push(ByteBuf::from_slice(&packet.to_byteslice()));
        self.interest.remove(Ready::readable());
        self.interest.insert(Ready::writable());
    }

    pub fn read(&mut self) -> Result<Option<Packet>, EofError> {
        let mut ret = Ok(None);
        match self.packet.from_socket(&mut self.socket, &mut self.worker, self.queues.clone(), self.token)? {
            None => debug!("{} Done reading", self),
            Some(p) => {
                ret = Ok(Some(p));
            }
        }
        // Packet is consumed, reset
        self.packet = Packet::new(self.token);
        ret
    }

    pub fn write(&mut self) -> Result<(), io::Error> {
        while !self.sendqueue.is_empty() {
            if !self.sendqueue.first().unwrap().has_remaining() {
                self.sendqueue.pop();
                continue;
            }
            let buf = self.sendqueue.first_mut().unwrap();
            match self.socket.try_write(buf.bytes())? {
                None => break,
                Some(n) => {
                    buf.advance(n);
                    continue
                }
            };
        }
        if self.sendqueue.is_empty() {
            self.interest.remove(Ready::writable());
            self.interest.insert(Ready::readable());
        };
        Ok(())
    }

    pub fn shutdown(self) {
        match self.worker.job {
            Some(j) => {
                self.queues.clone().add_job(j)
            },
            None => {},
        }
        self.socket.shutdown(Shutdown::Both).unwrap();
    }
}

impl fmt::Display for GearmanRemote {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Remote {{ addr: {:?} }}", self.addr)
    }
}

impl GearmanServer {
    pub fn new(server_socket: TcpListener, queues: QueueHolder) -> GearmanServer {
        GearmanServer {
            token_counter: 1,
            remotes: HashMap::new(),
            socket: server_socket,
            queues: queues,
        }
    }

}

impl Handler for GearmanServer {
    type Timeout = usize;
    type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<GearmanServer>,
             token: Token, events: Ready)
    {
        if events.is_readable() {
            match token {
                SERVER_TOKEN => {
                    let (remote_socket, remote_addr) = match self.socket.accept() {
                        Err(e) => {
                            error!("Accept error: {}", e);
                            return;
                        },
                        Ok((sock, addr)) => (sock, addr),
                    };

                    self.token_counter += 1;
                    let new_token = Token(self.token_counter);

                    self.remotes.insert(new_token, GearmanRemote::new(remote_socket, remote_addr, self.queues.clone(), new_token));

                    event_loop.register(&self.remotes[&new_token].socket,
                                        new_token, Ready::readable(),
                                        PollOpt::edge() | PollOpt::oneshot()).unwrap();
                },
                token => {
                    let mut shutdown = false;
                    {
                        let mut other_packet = None;
                        {
                            let mut remote = self.remotes.get_mut(&token).unwrap();
                            match remote.read() {
                                Ok(sp) => {
                                    match sp {
                                        Some(p) => {
                                            match p.remote {
                                                None => remote.queue_packet(&p), // Packet is for us
                                                Some(t) => {
                                                    if t == token {
                                                        // Packet is also meant for us
                                                        remote.queue_packet(&p);
                                                    } else {
                                                        // Packet is for a different remote
                                                        other_packet = Some(p);
                                                    }
                                                },
                                            };
                                        },
                                        None => {},
                                    }
                                    event_loop.reregister(&remote.socket, token, remote.interest,
                                                      PollOpt::edge() | PollOpt::oneshot()).unwrap();
                                },
                                Err(e) => {
                                    info!("remote({}) hung up: {:?}", &remote, e);
                                    shutdown = true;
                                }
                            }
                        }
                        match other_packet {
                            None => {},
                            Some(p) => {
                                let t = p.remote.unwrap();
                                let mut remote = self.remotes.get_mut(&t).unwrap(); // XXX
                                remote.queue_packet(&p);
                                event_loop.reregister(&remote.socket, t, remote.interest,
                                                      PollOpt::edge() | PollOpt::oneshot()).unwrap();
                            },
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }

        if events.is_writable() {
            match token {
                SERVER_TOKEN => panic!("Received writable event for server socket."),
                token => {
                    let mut shutdown = false;
                    {
                        let mut remote = self.remotes.get_mut(&token).unwrap();
                        match remote.write() {
                            Ok(_) => event_loop.reregister(&remote.socket, token, remote.interest,
                                                          PollOpt::edge() | PollOpt::oneshot()).unwrap(),
                            Err(e) => {
                                info!("remote({}) hung up: {}", &remote, e);
                                shutdown = true;
                            }
                        }
                    }
                    if shutdown {
                        let remote = self.remotes.remove(&token).unwrap();
                        remote.shutdown();
                    }
                },
            }
        }
    }
}
<|endoftext|>


<commit_before>
extern crate slog_scope;

extern crate futures;
extern crate hyper;

use self::futures::task::Task;

use self::futures::Stream;
use self::futures::Future;

use hyper::header::{ContentLength, ContentType};
use hyper::server::{Service, Request, Response};
use hyper::mime::{Mime, TopLevel, SubLevel};

use std::sync::{Arc, Mutex, mpsc};
use std::collections::HashMap;

use device::Device;
use weectrl::State;
use weectrl::StateNotification;
use error;
use xml;
use rpc;

#[derive(Clone)]
pub struct IncomingNotification {
	pub tx: Arc<Mutex<mpsc::Sender<Option<StateNotification>>>>,
    pub devices: Arc<Mutex<HashMap<String, Device>>>,
	pub task: Arc<Mutex<Option<Task>>>,
}

impl Service for IncomingNotification {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    // type Future = FutureResult<Response, hyper::Error>;
    type Future = Box<Future<Item = Response, Error = hyper::Error>>;

    fn call(&self, req: Request) -> Self::Future {

        info!(slog_scope::logger(), "MESSAGE: {:?}", req.method());

		let notification_sid = match rpc::extract_sid(req.headers()) {
			Some(sid) => sid,
			None => String::new()
		};

		let devices = self.devices.clone();
		let tx = self.tx.clone();
		let task = self.task.clone();

        req.body()
            .for_each(move |chunk| {
                let data = String::from_utf8(Vec::from(&chunk[..])).unwrap();

				let mut state = State::Unknown;
 				if let Some(s) = xml::get_binary_state(&data) {
					state = State::from(s);
				}

				if state!=State::Unknown && !notification_sid.is_empty() {

					for (unique_id, dev) in devices.lock().expect(error::FATAL_LOCK).iter() {
						if let Some(device_sid) = dev.sid() {

							// Found a match, send notification to the client
							if notification_sid == device_sid {
								info!(slog_scope::logger(),
									  "Got switch update for {:?}. sid: {:?}. State: {:?}.",
									  unique_id,
									  notification_sid,
									  state);

								let n = Some(StateNotification {
									unique_id: unique_id.to_owned(),
									state: state,
								});

								let r = tx.lock().expect(error::FATAL_LOCK).send(n);

								use std::ops::Deref;
								// If channel/future closed, forget Task.
								match r {
									Ok(_) => {
										let mtx = task.lock().expect(error::FATAL_LOCK);
										match mtx.deref() {
											&Some(ref s) => s.unpark(),
											&None => (),
										}
									}
									Err(e) => {
										let mut task = task.lock().expect(error::FATAL_LOCK);
										*task = None;
										info!(slog_scope::logger(),
											  "Future cancelled. {:?}",
											  e);
									}
								}
								break; // Found match
							}
						}
					}
					return Ok(());
				}
				Err(hyper::Error::Incomplete)
            })
            .map(move |_| {
                let body: &[u8] = b"
200 OK
";
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])))
                    .with_body(body)

            })
            .boxed()
    }
}
<commit_msg>Minor cleanups in server code.<commit_after>
extern crate slog_scope;

extern crate futures;
extern crate hyper;

use self::futures::task::Task;

use self::futures::Stream;
use self::futures::Future;
use self::futures::future;

use hyper::header::{ContentLength, ContentType};
use hyper::server::{Service, Request, Response};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::server;
use hyper::status::StatusCode;

use std::sync::{Arc, Mutex, mpsc};
use std::collections::HashMap;

use device::Device;
use weectrl::State;
use weectrl::StateNotification;
use error;
use xml;
use rpc;

#[derive(Clone)]
pub struct IncomingNotification {
    pub tx: Arc<Mutex<mpsc::Sender<Option<StateNotification>>>>,
    pub devices: Arc<Mutex<HashMap<String, Device>>>,
    pub task: Arc<Mutex<Option<Task>>>,
}

fn bad_request() -> Box<Future<Error = hyper::Error, Item = server::Response>> {
    let mut res = server::Response::new();
    res.set_status(StatusCode::BadRequest);
    future::ok(res).boxed()
}

impl Service for IncomingNotification {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    // type Future = FutureResult<Response, hyper::Error>;
    type Future = Box<Future<Item = Response, Error = hyper::Error>>;

    fn call(&self, req: Request) -> Self::Future {

        let (method, _, _, headers, body) = req.deconstruct();

        info!(slog_scope::logger(), "MESSAGE: {:?}", method);

        let notification_sid = match rpc::extract_sid(&headers) {
            Some(sid) => sid,
            None => return bad_request(),
        };

        let devices = self.devices.clone();
        let tx = self.tx.clone();
        let task = self.task.clone();

        body.fold(Vec::new(), |mut v, chunk| {
                v.extend(&chunk[..]);
                future::ok::<_, hyper::Error>(v)
            })
            .map(move |buffer| {

                let data = String::from_utf8(Vec::from(&buffer[..])).unwrap();
                if let Some(state) = xml::get_binary_state(&data) {

                    for (unique_id, dev) in devices.lock().expect(error::FATAL_LOCK).iter() {
                        if let Some(device_sid) = dev.sid() {
                            // Found a match, send notification to the client
                            if notification_sid == device_sid {
                                info!(slog_scope::logger(),
                                      "Got switch update for {:?}. sid: {:?}. State: {:?}.",
                                      unique_id,
                                      notification_sid,
                                      State::from(state));

                                let n = Some(StateNotification {
                                    unique_id: unique_id.to_owned(),
                                    state: State::from(state),
                                });

                                let r = tx.lock().expect(error::FATAL_LOCK).send(n);

                                use std::ops::Deref;
                                // If channel/future closed, forget Task.
                                match r {
                                    Ok(_) => {
                                        let mtx = task.lock().expect(error::FATAL_LOCK);
                                        match mtx.deref() {
                                            &Some(ref s) => s.unpark(),
                                            &None => (),
                                        }
                                    }
                                    Err(e) => {
                                        let mut task = task.lock().expect(error::FATAL_LOCK);
                                        *task = None;
                                        info!(slog_scope::logger(), "Future cancelled. {:?}", e);
                                    }
                                }
                                break; // Found match
                            }
                        }
                    }
                }
                let body: &[u8] = b"
200 OK
";
                Response::new()
                    .with_header(ContentLength(body.len() as u64))
                    .with_header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])))
                    .with_body(body)
            })
            .boxed()
    }
}
<|endoftext|>


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

use hyper::header::ContentLength;
use hyper::method::Method;
use hyper::server::{Server, Handler, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode;

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

enum DispatchMessage {
    HandleWebDriver(WebDriverMessage, 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 : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler> {
    handler: T,
    session: Option<Session>
}

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

    fn run(&mut self, msg_chan: Receiver<DispatchMessage>) {
        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::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) -> 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::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(()),

                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

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

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

impl Handler for HttpHandler {
    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())
                    }
                };
                error!("Returning status {:?}", status);
                error!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(ContentLength(resp_body.len() as u64));
                let mut stream = res.start().unwrap();
                stream.write_all(&resp_body.as_bytes()).unwrap();
                stream.end().unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T: 'static+WebDriverHandler>(address: SocketAddr, handler: T) {
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new();
    let http_handler = HttpHandler::new(api, msg_send);
    let server = Server::http(http_handler);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv)
    }).unwrap();
    server.listen(&address).unwrap();
}
<commit_msg>Fix error code for the case where a session is already created<commit_after>use std::io::{Write, Read};
use std::sync::Mutex;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::net::SocketAddr;

use hyper::header::ContentLength;
use hyper::method::Method;
use hyper::server::{Server, Handler, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;
use hyper::status::StatusCode;

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

enum DispatchMessage {
    HandleWebDriver(WebDriverMessage, 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 : Send {
    fn handle_command(&mut self, session: &Option<Session>, msg: &WebDriverMessage) -> WebDriverResult<WebDriverResponse>;
    fn delete_session(&mut self, session: &Option<Session>);
}

struct Dispatcher<T: WebDriverHandler> {
    handler: T,
    session: Option<Session>
}

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

    fn run(&mut self, msg_chan: Receiver<DispatchMessage>) {
        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::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) -> 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::NewSession => {
                                Err(WebDriverError::new(
                                    ErrorStatus::UnsupportedOperation,
                                    "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(()),

                            _ => Err(WebDriverError::new(
                                ErrorStatus::InvalidSessionId,
                                "Tried to run a command before creating a session"))
                        }
                    }
                }
            }
        }
    }
}

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

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

impl Handler for HttpHandler {
    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())
                    }
                };
                error!("Returning status {:?}", status);
                error!("Returning body {}", resp_body);
                {
                    let resp_status = res.status_mut();
                    *resp_status = status;
                }
                res.headers_mut().set(ContentLength(resp_body.len() as u64));
                let mut stream = res.start().unwrap();
                stream.write_all(&resp_body.as_bytes()).unwrap();
                stream.end().unwrap();
            },
            _ => {}
        }
    }
}

pub fn start<T: 'static+WebDriverHandler>(address: SocketAddr, handler: T) {
    let (msg_send, msg_recv) = channel();

    let api = WebDriverHttpApi::new();
    let http_handler = HttpHandler::new(api, msg_send);
    let server = Server::http(http_handler);

    let builder = thread::Builder::new().name("webdriver dispatcher".to_string());
    builder.spawn(move || {
        let mut dispatcher = Dispatcher::new(handler);
        dispatcher.run(msg_recv)
    }).unwrap();
    server.listen(&address).unwrap();
}
<|endoftext|>


<commit_before>use luminance::{FragmentShader, GeometryShader, StageError, ShaderTypeable,
                TessellationControlShader, TessellationEvaluationShader, VertexShader};
use luminance_gl::gl33::{ProgramProxy, Stage};
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::path::Path;

pub use luminance::{ProgramError, Uniformable, UniformUpdate};
pub use luminance::shader::program::UniformWarning;
pub use luminance_gl::gl33::{self, Uniform};
pub use luminance_gl::gl33::token::*;

use resource::{Load, LoadError, Reload};

#[derive(Debug)]
pub enum ShaderError {
  StageError(StageError),
  ProgramError(ProgramError)
}

/// Build a shader program from the shader sources and a uniform builder function.
pub fn new_program<GetUni, T>(tcs_src: &str, tes_src: &str, vs_src: &str, gs_src: &str, fs_src: &str, get_uni: GetUni) -> Result<gl33::Program<T>, ProgramError> where GetUni: Fn(ProgramProxy) -> Result<T, UniformWarning> {
  let stages = compile_stages(tcs_src, tes_src, vs_src, gs_src, fs_src);

  match stages {
    Ok((tess, vs, gs, fs)) => {
      if let Some((tcs, tes)) = tess {
        if let Some(gs) = gs {
          gl33::Program::new(Some((&tcs, &tes)), &vs, Some(&gs), &fs, get_uni)
        } else {
          gl33::Program::new(Some((&tcs, &tes)), &vs, None, &fs, get_uni)
        }
      } else if let Some(gs) = gs {
        gl33::Program::new(None, &vs, Some(&gs), &fs, get_uni)
      } else {
        gl33::Program::new(None, &vs, None, &fs, get_uni)
      }
    },
    Err(stage_error) => {
      Err(ProgramError::LinkFailed(format!("{:?}", stage_error)))
    }
  }
}

// Take raw shader sources and turn them into stages.
fn compile_stages(tcs_src: &str, tes_src: &str, vs_src: &str, gs_src: &str, fs_src: &str) -> Result<(Option<(Stage<TessellationControlShader>, Stage<TessellationEvaluationShader>)>, Stage<VertexShader>, Option<Stage<GeometryShader>>, Stage<FragmentShader>), StageError> {
  let tess = if !tcs_src.is_empty() && !tes_src.is_empty() { Some((try!(Stage::new(tcs_src)), try!(Stage::new(tes_src)))) } else { None };
  let vs = try!(Stage::new(vs_src));
  let gs = if !gs_src.is_empty() { Some(try!(Stage::new(gs_src))) } else { None };
  let fs = try!(Stage::new(fs_src));

  Ok((tess, vs, gs, fs))
}

/// Shader program.
///
/// If the program is retrieved from the cache, the path must point to a file containing all the
/// stages. A stage begins with a stage pragma indicating which kind of stage the following source
/// is. Here’s a list of all pragma for each kind of stage:
///
/// - `#tcs`: *tessellation control stage*
/// - `#tes`: *tessellation evaluation stage*
/// - `#vs`: *vertex stage*
/// - `#gs`: *geometry stage*
/// - `#fs`: *fragment stage*
///
/// A stage starts at such a pragma listed above and ends at the next, different pragma. You cannot
/// use twice the same pragma in a file.
///
/// At the top of the file, if you don’t put a pragma, you can use `//` to add comments, or die.
pub struct Program<T> {
  program: gl33::Program<T>,
  get_uni: Box<Fn(ProgramProxy) -> Result<T, UniformWarning>>,
}

impl<T> Load for Program<T> {
  type Args = Box<Fn(ProgramProxy) -> Result<T, UniformWarning>>;

  fn load<P>(path: P, args: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    enum CurrentStage {
      VS,
      FS,
      GS,
      TCS,
      TES
    }

    fn add_line_to_src(src: &mut String, line: &String, line_nb: usize) {
      if src.is_empty() {
        *src += &format!("#line {}\n{}\n", line_nb, line);
      }
    }

    match File::open(path.as_ref()) {
      Ok(fh) => {
        let buffered = BufReader::new(fh);
        let mut tcs_src = String::new();
        let mut tes_src = String::new();
        let mut vs_src = String::new();
        let mut gs_src = String::new();
        let mut fs_src = String::new();
        let mut current_stage: Option<CurrentStage> = None;

        for (line_nb, line) in buffered.lines().enumerate() {
          let line_nb = line_nb + 1;
          let line = line.unwrap();
          let trimmed = line.trim();

          if trimmed.starts_with("#vs") {
            if !vs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #vs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::VS);
          } else if trimmed.starts_with("#fs") {
            if !fs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #fs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::FS);
          } else if trimmed.starts_with("#gs") {
            if !gs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #gs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::GS);
          } else if trimmed.starts_with("#tcs") {
            if !tcs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #tcs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::TCS);
          } else if trimmed.starts_with("#tes") {
            if !tes_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #tes sections", line_nb)));
            }

            current_stage = Some(CurrentStage::TES);
          } else if current_stage.is_none() && !trimmed.starts_with("//") {
            return Err(LoadError::ParseFailed(format!("(line {}) not in a shader stage nor a comment", line_nb)));
          }

          match current_stage {
            Some(CurrentStage::VS) => {
              add_line_to_src(&mut vs_src, &line, line_nb);
            },
            Some(CurrentStage::FS) => {
              add_line_to_src(&mut fs_src, &line, line_nb);
            },
            Some(CurrentStage::GS) => {
              add_line_to_src(&mut gs_src, &line, line_nb);
            },
            Some(CurrentStage::TCS) => {
              add_line_to_src(&mut tcs_src, &line, line_nb);
            },
            Some(CurrentStage::TES) => {
              add_line_to_src(&mut tes_src, &line, line_nb);
            },
            None => {}
          }
        }

        let program = try!(new_program(&tcs_src, &tes_src, &vs_src, &gs_src, &fs_src, &*args)
          .map_err(|e| LoadError::ConversionFailed(format!("{:?}", e))));

        Ok(Program {
          program: program,
          get_uni: args
        })
      },
      Err(e) => {
        Err(LoadError::FileNotFound(path.as_ref().to_owned(), format!("{:?}", e)))
      }
    }
  }
}

/// A helper function used to make uniforms optionable. If there’s a warning, it’s printed out.
pub fn opt_uni<T>(uni: (Uniform<T>, Option<UniformWarning>)) -> Uniform<T> where T: Uniformable<GL33> {
  if let Some(warning) = uni.1 {
    warn!("{:?}", warning);
  }

  uni.0
}
<commit_msg>impl<T> Reload for Program<T>.<commit_after>use luminance::{FragmentShader, GeometryShader, StageError, ShaderTypeable,
                TessellationControlShader, TessellationEvaluationShader, VertexShader};
use luminance_gl::gl33::{ProgramProxy, Stage};
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::path::Path;

pub use luminance::{ProgramError, Uniformable, UniformUpdate};
pub use luminance::shader::program::UniformWarning;
pub use luminance_gl::gl33::{self, Uniform};
pub use luminance_gl::gl33::token::*;

use resource::{Load, LoadError, Reload};

#[derive(Debug)]
pub enum ShaderError {
  StageError(StageError),
  ProgramError(ProgramError)
}

/// Build a shader program from the shader sources and a uniform builder function.
pub fn new_program<T>(tcs_src: &str, tes_src: &str, vs_src: &str, gs_src: &str, fs_src: &str, get_uni: &'static Fn(ProgramProxy) -> Result<T, UniformWarning>) -> Result<gl33::Program<T>, ProgramError> {
  let stages = compile_stages(tcs_src, tes_src, vs_src, gs_src, fs_src);

  match stages {
    Ok((tess, vs, gs, fs)) => {
      if let Some((tcs, tes)) = tess {
        if let Some(gs) = gs {
          gl33::Program::new(Some((&tcs, &tes)), &vs, Some(&gs), &fs, get_uni)
        } else {
          gl33::Program::new(Some((&tcs, &tes)), &vs, None, &fs, get_uni)
        }
      } else if let Some(gs) = gs {
        gl33::Program::new(None, &vs, Some(&gs), &fs, get_uni)
      } else {
        gl33::Program::new(None, &vs, None, &fs, get_uni)
      }
    },
    Err(stage_error) => {
      Err(ProgramError::LinkFailed(format!("{:?}", stage_error)))
    }
  }
}

// Take raw shader sources and turn them into stages.
fn compile_stages(tcs_src: &str, tes_src: &str, vs_src: &str, gs_src: &str, fs_src: &str) -> Result<(Option<(Stage<TessellationControlShader>, Stage<TessellationEvaluationShader>)>, Stage<VertexShader>, Option<Stage<GeometryShader>>, Stage<FragmentShader>), StageError> {
  let tess = if !tcs_src.is_empty() && !tes_src.is_empty() { Some((try!(Stage::new(tcs_src)), try!(Stage::new(tes_src)))) } else { None };
  let vs = try!(Stage::new(vs_src));
  let gs = if !gs_src.is_empty() { Some(try!(Stage::new(gs_src))) } else { None };
  let fs = try!(Stage::new(fs_src));

  Ok((tess, vs, gs, fs))
}

/// Shader program.
///
/// If the program is retrieved from the cache, the path must point to a file containing all the
/// stages. A stage begins with a stage pragma indicating which kind of stage the following source
/// is. Here’s a list of all pragma for each kind of stage:
///
/// - `#tcs`: *tessellation control stage*
/// - `#tes`: *tessellation evaluation stage*
/// - `#vs`: *vertex stage*
/// - `#gs`: *geometry stage*
/// - `#fs`: *fragment stage*
///
/// A stage starts at such a pragma listed above and ends at the next, different pragma. You cannot
/// use twice the same pragma in a file.
///
/// At the top of the file, if you don’t put a pragma, you can use `//` to add comments, or die.
pub struct Program<T> where T: 'static {
  program: gl33::Program<T>,
  get_uni: &'static Fn(ProgramProxy) -> Result<T, UniformWarning>,
}

impl<T> Load for Program<T> where T: 'static {
  type Args = &'static Fn(ProgramProxy) -> Result<T, UniformWarning>;

  fn load<P>(path: P, args: Self::Args) -> Result<Self, LoadError> where P: AsRef<Path> {
    enum CurrentStage {
      VS,
      FS,
      GS,
      TCS,
      TES
    }

    fn add_line_to_src(src: &mut String, line: &String, line_nb: usize) {
      if src.is_empty() {
        *src += &format!("#line {}\n{}\n", line_nb, line);
      }
    }

    match File::open(path.as_ref()) {
      Ok(fh) => {
        let buffered = BufReader::new(fh);
        let mut tcs_src = String::new();
        let mut tes_src = String::new();
        let mut vs_src = String::new();
        let mut gs_src = String::new();
        let mut fs_src = String::new();
        let mut current_stage: Option<CurrentStage> = None;

        for (line_nb, line) in buffered.lines().enumerate() {
          let line_nb = line_nb + 1;
          let line = line.unwrap();
          let trimmed = line.trim();

          if trimmed.starts_with("#vs") {
            if !vs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #vs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::VS);
          } else if trimmed.starts_with("#fs") {
            if !fs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #fs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::FS);
          } else if trimmed.starts_with("#gs") {
            if !gs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #gs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::GS);
          } else if trimmed.starts_with("#tcs") {
            if !tcs_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #tcs sections", line_nb)));
            }

            current_stage = Some(CurrentStage::TCS);
          } else if trimmed.starts_with("#tes") {
            if !tes_src.is_empty() {
              return Err(LoadError::ParseFailed(format!("(line {}) several #tes sections", line_nb)));
            }

            current_stage = Some(CurrentStage::TES);
          } else if current_stage.is_none() && !trimmed.starts_with("//") {
            return Err(LoadError::ParseFailed(format!("(line {}) not in a shader stage nor a comment", line_nb)));
          }

          match current_stage {
            Some(CurrentStage::VS) => {
              add_line_to_src(&mut vs_src, &line, line_nb);
            },
            Some(CurrentStage::FS) => {
              add_line_to_src(&mut fs_src, &line, line_nb);
            },
            Some(CurrentStage::GS) => {
              add_line_to_src(&mut gs_src, &line, line_nb);
            },
            Some(CurrentStage::TCS) => {
              add_line_to_src(&mut tcs_src, &line, line_nb);
            },
            Some(CurrentStage::TES) => {
              add_line_to_src(&mut tes_src, &line, line_nb);
            },
            None => {}
          }
        }

        let program = try!(new_program(&tcs_src, &tes_src, &vs_src, &gs_src, &fs_src, args)
          .map_err(|e| LoadError::ConversionFailed(format!("{:?}", e))));

        Ok(Program {
          program: program,
          get_uni: args
        })
      },
      Err(e) => {
        Err(LoadError::FileNotFound(path.as_ref().to_owned(), format!("{:?}", e)))
      }
    }
  }
}

impl<T> Reload for Program<T> where T: 'static {
  fn reload<P>(&self, path :P) -> Result<Self, LoadError> where P: AsRef<Path> {
    Self::load(path, self.get_uni)
  }
}

/// A helper function used to make uniforms optionable. If there’s a warning, it’s printed out.
pub fn opt_uni<T>(uni: (Uniform<T>, Option<UniformWarning>)) -> Uniform<T> where T: Uniformable<GL33> {
  if let Some(warning) = uni.1 {
    warn!("{:?}", warning);
  }

  uni.0
}
<|endoftext|>


<commit_before>use libc::*;

pub type ENetSocket = c_int;
<commit_msg>Added socket functions<commit_after>use libc::*;
use address::ENetAddress;
use ::ENetBuffer;

pub type ENetSocket = c_int;

#[repr(C)]
pub enum ENetSocketType {
    ENET_SOCKET_TYPE_STREAM = 1,
    ENET_SOCKET_TYPE_DATAGRAM = 2,
}

#[repr(C)]
pub enum ENetSocketOption {
    ENET_SOCKOPT_NONBLOCK = 1,
    ENET_SOCKOPT_BROADCAST = 2,
    ENET_SOCKOPT_RCVBUF = 3,
    ENET_SOCKOPT_SNDBUF = 4,
    ENET_SOCKOPT_REUSEADDR = 5,
    ENET_SOCKOPT_RCVTIMEO = 6,
    ENET_SOCKOPT_SNDTIMEO = 7,
    ENET_SOCKOPT_ERROR = 8,
    ENET_SOCKOPT_NODELAY = 9,
}

#[repr(C)]
pub enum ENetSocketShutdown {
    ENET_SOCKET_SHUTDOWN_READ = 0,
    ENET_SOCKET_SHUTDOWN_WRITE = 1,
    ENET_SOCKET_SHUTDOWN_READ_WRITE = 2,
}

extern {
    pub fn enet_socket_accept(socket: ENetSocket, address: *mut ENetAddress) -> ENetSocket;
    pub fn enet_socket_bind(socket: ENetSocket, address: *const ENetAddress) -> c_int;
    pub fn enet_socket_connect(socket: ENetSocket, address: *const ENetAddress) -> c_int;
    pub fn enet_socket_create(socketType: ENetSocketType) -> ENetSocket;
    pub fn enet_socket_destroy(socket: ENetSocket);
    pub fn enet_socket_get_address(socket: ENetSocket, address: *mut ENetAddress) -> c_int;
    pub fn enet_socket_get_option(socket: ENetSocket, socketOption: ENetSocketOption,
            _unknown: *mut c_int) -> c_int;
    pub fn enet_socket_listen(socket: ENetSocket, _unknown: c_int) -> c_int;
    pub fn enet_socket_receive(socket: ENetSocket, address: *mut ENetAddress, buffer: *mut ENetBuffer,
            bufferSize: size_t) -> c_int;
    pub fn enet_socket_send(socket: ENetSocket, address: *const ENetAddress, buffer: *const ENetBuffer,
            bufferSize: size_t) -> c_int;
    pub fn enet_socket_set_option(socket: ENetSocket, socketOption: ENetSocketOption, _unknown: c_int)
            -> c_int;
    pub fn enet_socket_shutdown(socket: ENetSocket, socketShutdown: ENetSocketShutdown) -> c_int;
    pub fn enet_socket_wait(socket: ENetSocket, _unknownA: *mut uint32_t, _unknownB: uint32_t) -> c_int;
}
<|endoftext|>