<commit_before>//! SQLite support for the `r2d2` connection pool.
#![warn(missing_docs)]
extern crate r2d2;
extern crate rusqlite;

use std::convert::Into;
use std::path::PathBuf;

/// An `r2d2::ManageConnection` for `rusqlite::SqliteConnection`s.
///
/// ## Example
///
/// ```rust
/// extern crate r2d2;
/// extern crate r2d2_sqlite;
/// extern crate rusqlite;
///
/// use std::sync::Arc;
/// use std::default::Default;
/// use std::thread;
/// use r2d2_sqlite::SQLiteConnectionManager;
/// use rusqlite::OpenFlags;
///
/// fn main() {
///     let manager = SQLiteConnectionManager::new(
///             "file:dummy.db?mode=memory&cache=shared",
///             OpenFlags::SQLITE_OPEN_URI | OpenFlags::SQLITE_OPEN_CREATE | OpenFlags::SQLITE_OPEN_READ_WRITE);
///     let pool = Arc::new(r2d2::Pool::new(manager).unwrap());
///
///     for i in 0..10i32 {
///         let pool = pool.clone();
///         thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             conn.execute("PRAGMA user_version=?1", &[&i]).unwrap();
///         });
///     }
/// }
/// ```
pub struct SQLiteConnectionManager {
    path: PathBuf,
    flags: rusqlite::OpenFlags,
}

impl SQLiteConnectionManager {
    /// Creates a new `SQLiteConnectionManager`.
    ///
    /// See `rusqlite::SqliteConnection::open_with_flags` for a description of
    /// the parameter types.
    pub fn new<T>(path: T, flags: rusqlite::OpenFlags) -> SQLiteConnectionManager
    where
        T: Into<PathBuf>,
    {
        SQLiteConnectionManager {
            path: path.into(),
            flags,
        }
    }
}

impl r2d2::ManageConnection for SQLiteConnectionManager {
    type Connection = rusqlite::Connection;
    type Error = rusqlite::Error;

    fn connect(&self) -> Result<rusqlite::Connection, rusqlite::Error> {
        rusqlite::Connection::open_with_flags(&self.path, self.flags)
    }

    fn is_valid(&self, conn: &mut rusqlite::Connection) -> Result<(), rusqlite::Error> {
        // http://sqlite.org/pragma.html#pragma_schema_version
        conn.execute_batch("PRAGMA schema_version")
    }

    fn has_broken(&self, conn: &mut rusqlite::Connection) -> bool {
        // pending transaction or at least one statement busy
        !conn.is_autocommit() || conn.is_busy()
    }
}

// http://sqlite.org/c3ref/db_release_memory.html
// http://sqlite.org/c3ref/interrupt.html
<commit_msg>Rustfmt<commit_after>//! SQLite support for the `r2d2` connection pool.
#![warn(missing_docs)]
extern crate r2d2;
extern crate rusqlite;

use std::convert::Into;
use std::path::PathBuf;

/// An `r2d2::ManageConnection` for `rusqlite::SqliteConnection`s.
///
/// ## Example
///
/// ```rust
/// extern crate r2d2;
/// extern crate r2d2_sqlite;
/// extern crate rusqlite;
///
/// use r2d2_sqlite::SQLiteConnectionManager;
/// use rusqlite::OpenFlags;
/// use std::default::Default;
/// use std::sync::Arc;
/// use std::thread;
///
/// fn main() {
///     let manager = SQLiteConnectionManager::new(
///         "file:dummy.db?mode=memory&cache=shared",
///         OpenFlags::SQLITE_OPEN_URI
///             | OpenFlags::SQLITE_OPEN_CREATE
///             | OpenFlags::SQLITE_OPEN_READ_WRITE,
///     );
///     let pool = Arc::new(r2d2::Pool::new(manager).unwrap());
///
///     for i in 0..10i32 {
///         let pool = pool.clone();
///         thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             conn.execute("PRAGMA user_version=?1", &[&i]).unwrap();
///         });
///     }
/// }
/// ```
pub struct SQLiteConnectionManager {
    path: PathBuf,
    flags: rusqlite::OpenFlags,
}

impl SQLiteConnectionManager {
    /// Creates a new `SQLiteConnectionManager`.
    ///
    /// See `rusqlite::SqliteConnection::open_with_flags` for a description of
    /// the parameter types.
    pub fn new<T>(path: T, flags: rusqlite::OpenFlags) -> SQLiteConnectionManager
    where
        T: Into<PathBuf>,
    {
        SQLiteConnectionManager {
            path: path.into(),
            flags,
        }
    }
}

impl r2d2::ManageConnection for SQLiteConnectionManager {
    type Connection = rusqlite::Connection;
    type Error = rusqlite::Error;

    fn connect(&self) -> Result<rusqlite::Connection, rusqlite::Error> {
        rusqlite::Connection::open_with_flags(&self.path, self.flags)
    }

    fn is_valid(&self, conn: &mut rusqlite::Connection) -> Result<(), rusqlite::Error> {
        // http://sqlite.org/pragma.html#pragma_schema_version
        conn.execute_batch("PRAGMA schema_version")
    }

    fn has_broken(&self, conn: &mut rusqlite::Connection) -> bool {
        // pending transaction or at least one statement busy
        !conn.is_autocommit() || conn.is_busy()
    }
}

// http://sqlite.org/c3ref/db_release_memory.html
// http://sqlite.org/c3ref/interrupt.html
<|endoftext|>


<commit_before>#![cfg_attr(test, deny(warnings))]
#![warn(rust_2018_idioms)]

extern crate conduit;
extern crate conduit_middleware;
extern crate time;

use conduit::{header, Body, HeaderMap, Method, RequestExt, Response, StatusCode};
use conduit_middleware::{AfterResult, Middleware};
use std::borrow::Cow;
use time::{ParseError, Tm};

#[allow(missing_copy_implementations)]
pub struct ConditionalGet;

impl Middleware for ConditionalGet {
    fn after(&self, req: &mut dyn RequestExt, res: AfterResult) -> AfterResult {
        let res = res?;

        match *req.method() {
            Method::GET | Method::HEAD => {
                if is_ok(&res) && is_fresh(req, &res) {
                    let (mut parts, _) = res.into_parts();
                    parts.status = StatusCode::NOT_MODIFIED;
                    parts.headers.remove(header::CONTENT_TYPE);
                    parts.headers.remove(header::CONTENT_LENGTH);
                    return Ok(Response::from_parts(parts, Body::empty()));
                }
            }
            _ => (),
        }

        Ok(res)
    }
}

fn is_ok(response: &Response<Body>) -> bool {
    response.status() == 200
}

fn is_fresh(req: &dyn RequestExt, res: &Response<Body>) -> bool {
    let modified_since = get_and_concat_header(req.headers(), header::IF_MODIFIED_SINCE);
    let none_match = get_and_concat_header(req.headers(), header::IF_NONE_MATCH);

    if modified_since.is_empty() && none_match.is_empty() {
        return false;
    }

    let is_modified_since = match std::str::from_utf8(&modified_since) {
        Err(_) => true,
        Ok(string) if string.is_empty() => true,
        Ok(modified_since) => {
            let modified_since = parse_http_date(modified_since);
            match modified_since {
                Err(_) => return false, // Preserve existing behavior
                Ok(parsed) => is_modified_since(parsed, res),
            }
        }
    };

    is_modified_since && etag_matches(&none_match, res)
}

fn etag_matches(none_match: &[u8], res: &Response<Body>) -> bool {
    let value = get_and_concat_header(res.headers(), header::ETAG);
    value == none_match
}

fn is_modified_since(modified_since: Tm, res: &Response<Body>) -> bool {
    let last_modified = get_and_concat_header(res.headers(), header::LAST_MODIFIED);

    match std::str::from_utf8(&last_modified) {
        Err(_) => false,
        Ok(last_modified) => match parse_http_date(last_modified) {
            Err(_) => false,
            Ok(last_modified) => modified_since.to_timespec() >= last_modified.to_timespec(),
        },
    }
}

fn get_and_concat_header<'a>(headers: &'a HeaderMap, name: header::HeaderName) -> Cow<'a, [u8]> {
    let mut values = headers.get_all(name).iter();
    if values.size_hint() == (1, Some(1)) {
        // Exactly 1 value, allocation is unnecessary
        // Unwrap will not panic, because there is a value
        Cow::Borrowed(values.next().unwrap().as_bytes())
    } else {
        let values: Vec<_> = values.map(|val| val.as_bytes()).collect();
        Cow::Owned(values.concat())
    }
}

fn parse_http_date(string: &str) -> Result<Tm, ()> {
    parse_rfc1123(string)
        .or_else(|_| parse_rfc850(string))
        .or_else(|_| parse_asctime(string))
        .map_err(|_| ())
}

fn parse_rfc1123(string: &str) -> Result<Tm, ParseError> {
    time::strptime(string, "%a, %d %b %Y %T GMT")
}

fn parse_rfc850(string: &str) -> Result<Tm, ParseError> {
    time::strptime(string, "%a, %d-%m-%y %T GMT")
}

fn parse_asctime(string: &str) -> Result<Tm, ParseError> {
    time::strptime(string, "%a %m%t%d %T %Y")
}

#[cfg(test)]
mod tests {
    extern crate conduit_test;

    use self::conduit_test::{MockRequest, ResponseExt};
    use conduit::{
        box_error, header, Body, Handler, HandlerResult, HeaderMap, Method, RequestExt, Response,
        StatusCode,
    };
    use conduit_middleware::MiddlewareBuilder;
    use time;
    use time::Tm;

    use super::ConditionalGet;

    macro_rules! returning {
        ($status:expr, $($header:expr => $value:expr),+) => ({
            use std::convert::TryInto;
            let mut headers = HeaderMap::new();
            $(headers.append($header, $value.try_into().unwrap());)+
            let handler = SimpleHandler::new(headers, $status, "hello");
            let mut stack = MiddlewareBuilder::new(handler);
            stack.add(ConditionalGet);
            stack
        });
        ($($header:expr => $value:expr),+) => ({
            returning!(StatusCode::OK, $($header => $value),+)
        })
    }

    macro_rules! request {
        ($($header:expr => $value:expr),+) => ({
            let mut req = MockRequest::new(Method::GET, "/");
            $(req.header($header, &$value.to_string());)+
            req
        })
    }

    #[test]
    fn test_sends_304() {
        let handler = returning!(header::LAST_MODIFIED => httpdate(time::now()));
        expect_304(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => httpdate(time::now())
        )));
    }

    #[test]
    fn test_sends_304_if_older_than_now() {
        let handler = returning!(header::LAST_MODIFIED => before_now());
        expect_304(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => httpdate(time::now())
        )));
    }

    #[test]
    fn test_sends_304_with_etag() {
        let handler = returning!(header::ETAG => "1234");
        expect_304(handler.call(&mut request!(
            header::IF_NONE_MATCH => "1234"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_time_but_not_etag() {
        let handler = returning!(header::LAST_MODIFIED => before_now(), header::ETAG => "1234");
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => now(),
            header::IF_NONE_MATCH => "4321"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_etag_but_not_time() {
        let handler = returning!(header::LAST_MODIFIED => now(), header::ETAG => "1234");
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => before_now(),
            header::IF_NONE_MATCH => "1234"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_etag() {
        let handler = returning!(header::ETAG => "1234");
        expect_200(handler.call(&mut request!(
            header::IF_NONE_MATCH => "4321"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_time() {
        let handler = returning!(header::LAST_MODIFIED => now());
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => before_now()
        )));
    }

    #[test]
    fn test_sends_304_with_fresh_time_and_etag() {
        let handler = returning!(header::LAST_MODIFIED => before_now(), header::ETAG => "1234");
        expect_304(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => now(),
            header::IF_NONE_MATCH => "1234"
        )));
    }

    #[test]
    fn test_does_not_affect_non_200() {
        let handler = returning!(StatusCode::FOUND, header::LAST_MODIFIED => before_now(), header::ETAG => "1234");
        expect(
            StatusCode::FOUND,
            handler.call(&mut request!(
                header::IF_MODIFIED_SINCE => now(),
                header::IF_NONE_MATCH => "1234"
            )),
        );
    }

    #[test]
    fn test_does_not_affect_malformed_timestamp() {
        let bad_stamp = time::now()
            .strftime("%Y-%m-%d %H:%M:%S %z")
            .unwrap()
            .to_string();
        let handler = returning!(header::LAST_MODIFIED => before_now());
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => bad_stamp
        )));
    }

    fn expect_304(response: HandlerResult) {
        let response = response.expect("No response");
        assert_eq!(response.status(), StatusCode::NOT_MODIFIED);
        assert_eq!(response.into_cow(), "".as_bytes());
    }

    fn expect_200(response: HandlerResult) {
        expect(StatusCode::OK, response);
    }

    fn expect(status: StatusCode, response: HandlerResult) {
        let response = response.expect("No response");
        assert_eq!(response.status(), status);
        assert_eq!(response.into_cow(), "hello".as_bytes());
    }

    struct SimpleHandler {
        headers: HeaderMap,
        status: StatusCode,
        body: &'static str,
    }

    impl SimpleHandler {
        fn new(headers: HeaderMap, status: StatusCode, body: &'static str) -> SimpleHandler {
            SimpleHandler {
                headers,
                status,
                body,
            }
        }
    }

    impl Handler for SimpleHandler {
        fn call(&self, _: &mut dyn RequestExt) -> HandlerResult {
            let mut builder = Response::builder().status(self.status);
            builder.headers_mut().unwrap().extend(self.headers.clone());
            builder
                .body(Body::from_static(self.body.as_bytes()))
                .map_err(box_error)
        }
    }

    fn before_now() -> String {
        let mut now = time::now();
        now.tm_year -= 1;
        httpdate(now)
    }

    fn now() -> String {
        httpdate(time::now())
    }

    fn httpdate(time: Tm) -> String {
        time.strftime("%a, %d-%m-%y %T GMT").unwrap().to_string()
    }
}
<commit_msg>Fix clippy lints<commit_after>#![cfg_attr(test, deny(warnings))]
#![warn(rust_2018_idioms)]

extern crate conduit;
extern crate conduit_middleware;
extern crate time;

use conduit::{header, Body, HeaderMap, Method, RequestExt, Response, StatusCode};
use conduit_middleware::{AfterResult, Middleware};
use std::borrow::Cow;
use time::{ParseError, Tm};

#[allow(missing_copy_implementations)]
pub struct ConditionalGet;

impl Middleware for ConditionalGet {
    fn after(&self, req: &mut dyn RequestExt, res: AfterResult) -> AfterResult {
        let res = res?;

        match *req.method() {
            Method::GET | Method::HEAD => {
                if is_ok(&res) && is_fresh(req, &res) {
                    let (mut parts, _) = res.into_parts();
                    parts.status = StatusCode::NOT_MODIFIED;
                    parts.headers.remove(header::CONTENT_TYPE);
                    parts.headers.remove(header::CONTENT_LENGTH);
                    return Ok(Response::from_parts(parts, Body::empty()));
                }
            }
            _ => (),
        }

        Ok(res)
    }
}

fn is_ok(response: &Response<Body>) -> bool {
    response.status() == 200
}

fn is_fresh(req: &dyn RequestExt, res: &Response<Body>) -> bool {
    let modified_since = get_and_concat_header(req.headers(), header::IF_MODIFIED_SINCE);
    let none_match = get_and_concat_header(req.headers(), header::IF_NONE_MATCH);

    if modified_since.is_empty() && none_match.is_empty() {
        return false;
    }

    let is_modified_since = match std::str::from_utf8(&modified_since) {
        Err(_) => true,
        Ok(string) if string.is_empty() => true,
        Ok(modified_since) => {
            let modified_since = parse_http_date(modified_since);
            match modified_since {
                Err(_) => return false, // Preserve existing behavior
                Ok(parsed) => is_modified_since(parsed, res),
            }
        }
    };

    is_modified_since && etag_matches(&none_match, res)
}

fn etag_matches(none_match: &[u8], res: &Response<Body>) -> bool {
    let value = get_and_concat_header(res.headers(), header::ETAG);
    value == none_match
}

fn is_modified_since(modified_since: Tm, res: &Response<Body>) -> bool {
    let last_modified = get_and_concat_header(res.headers(), header::LAST_MODIFIED);

    match std::str::from_utf8(&last_modified) {
        Err(_) => false,
        Ok(last_modified) => match parse_http_date(last_modified) {
            Err(_) => false,
            Ok(last_modified) => modified_since.to_timespec() >= last_modified.to_timespec(),
        },
    }
}

fn get_and_concat_header(headers: &HeaderMap, name: header::HeaderName) -> Cow<'_, [u8]> {
    let mut values = headers.get_all(name).iter();
    if values.size_hint() == (1, Some(1)) {
        // Exactly 1 value, allocation is unnecessary
        // Unwrap will not panic, because there is a value
        Cow::Borrowed(values.next().unwrap().as_bytes())
    } else {
        let values: Vec<_> = values.map(|val| val.as_bytes()).collect();
        Cow::Owned(values.concat())
    }
}

fn parse_http_date(string: &str) -> Result<Tm, ()> {
    parse_rfc1123(string)
        .or_else(|_| parse_rfc850(string))
        .or_else(|_| parse_asctime(string))
        .map_err(|_| ())
}

fn parse_rfc1123(string: &str) -> Result<Tm, ParseError> {
    time::strptime(string, "%a, %d %b %Y %T GMT")
}

fn parse_rfc850(string: &str) -> Result<Tm, ParseError> {
    time::strptime(string, "%a, %d-%m-%y %T GMT")
}

fn parse_asctime(string: &str) -> Result<Tm, ParseError> {
    time::strptime(string, "%a %m%t%d %T %Y")
}

#[cfg(test)]
mod tests {
    extern crate conduit_test;

    use self::conduit_test::{MockRequest, ResponseExt};
    use conduit::{
        box_error, header, Body, Handler, HandlerResult, HeaderMap, Method, RequestExt, Response,
        StatusCode,
    };
    use conduit_middleware::MiddlewareBuilder;
    use time;
    use time::Tm;

    use super::ConditionalGet;

    macro_rules! returning {
        ($status:expr, $($header:expr => $value:expr),+) => ({
            use std::convert::TryInto;
            let mut headers = HeaderMap::new();
            $(headers.append($header, $value.try_into().unwrap());)+
            let handler = SimpleHandler::new(headers, $status, "hello");
            let mut stack = MiddlewareBuilder::new(handler);
            stack.add(ConditionalGet);
            stack
        });
        ($($header:expr => $value:expr),+) => ({
            returning!(StatusCode::OK, $($header => $value),+)
        })
    }

    macro_rules! request {
        ($($header:expr => $value:expr),+) => ({
            let mut req = MockRequest::new(Method::GET, "/");
            $(req.header($header, &$value.to_string());)+
            req
        })
    }

    #[test]
    fn test_sends_304() {
        let handler = returning!(header::LAST_MODIFIED => httpdate(time::now()));
        expect_304(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => httpdate(time::now())
        )));
    }

    #[test]
    fn test_sends_304_if_older_than_now() {
        let handler = returning!(header::LAST_MODIFIED => before_now());
        expect_304(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => httpdate(time::now())
        )));
    }

    #[test]
    fn test_sends_304_with_etag() {
        let handler = returning!(header::ETAG => "1234");
        expect_304(handler.call(&mut request!(
            header::IF_NONE_MATCH => "1234"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_time_but_not_etag() {
        let handler = returning!(header::LAST_MODIFIED => before_now(), header::ETAG => "1234");
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => now(),
            header::IF_NONE_MATCH => "4321"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_etag_but_not_time() {
        let handler = returning!(header::LAST_MODIFIED => now(), header::ETAG => "1234");
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => before_now(),
            header::IF_NONE_MATCH => "1234"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_etag() {
        let handler = returning!(header::ETAG => "1234");
        expect_200(handler.call(&mut request!(
            header::IF_NONE_MATCH => "4321"
        )));
    }

    #[test]
    fn test_sends_200_with_fresh_time() {
        let handler = returning!(header::LAST_MODIFIED => now());
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => before_now()
        )));
    }

    #[test]
    fn test_sends_304_with_fresh_time_and_etag() {
        let handler = returning!(header::LAST_MODIFIED => before_now(), header::ETAG => "1234");
        expect_304(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => now(),
            header::IF_NONE_MATCH => "1234"
        )));
    }

    #[test]
    fn test_does_not_affect_non_200() {
        let handler = returning!(StatusCode::FOUND, header::LAST_MODIFIED => before_now(), header::ETAG => "1234");
        expect(
            StatusCode::FOUND,
            handler.call(&mut request!(
                header::IF_MODIFIED_SINCE => now(),
                header::IF_NONE_MATCH => "1234"
            )),
        );
    }

    #[test]
    fn test_does_not_affect_malformed_timestamp() {
        let bad_stamp = time::now()
            .strftime("%Y-%m-%d %H:%M:%S %z")
            .unwrap()
            .to_string();
        let handler = returning!(header::LAST_MODIFIED => before_now());
        expect_200(handler.call(&mut request!(
            header::IF_MODIFIED_SINCE => bad_stamp
        )));
    }

    fn expect_304(response: HandlerResult) {
        let response = response.expect("No response");
        assert_eq!(response.status(), StatusCode::NOT_MODIFIED);
        assert_eq!(*response.into_cow(), b""[..]);
    }

    fn expect_200(response: HandlerResult) {
        expect(StatusCode::OK, response);
    }

    fn expect(status: StatusCode, response: HandlerResult) {
        let response = response.expect("No response");
        assert_eq!(response.status(), status);
        assert_eq!(*response.into_cow(), b"hello"[..]);
    }

    struct SimpleHandler {
        headers: HeaderMap,
        status: StatusCode,
        body: &'static str,
    }

    impl SimpleHandler {
        fn new(headers: HeaderMap, status: StatusCode, body: &'static str) -> SimpleHandler {
            SimpleHandler {
                headers,
                status,
                body,
            }
        }
    }

    impl Handler for SimpleHandler {
        fn call(&self, _: &mut dyn RequestExt) -> HandlerResult {
            let mut builder = Response::builder().status(self.status);
            builder.headers_mut().unwrap().extend(self.headers.clone());
            builder
                .body(Body::from_static(self.body.as_bytes()))
                .map_err(box_error)
        }
    }

    fn before_now() -> String {
        let mut now = time::now();
        now.tm_year -= 1;
        httpdate(now)
    }

    fn now() -> String {
        httpdate(time::now())
    }

    fn httpdate(time: Tm) -> String {
        time.strftime("%a, %d-%m-%y %T GMT").unwrap().to_string()
    }
}
<|endoftext|>


<commit_before>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::io::{ErrorKind, Result};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

#[derive(Debug)]
/// `Discover` type
///
/// Used for discovering sonos devices in the local network via the simple service discovery protocol (ssdp).
/// The ssd-protocol works via udp sockets. First a certain search-message is sent to the multicast address (239.255.255.250:1900).
///
/// All answer from upnp (universal plug and play) ready devices are processed and filtered ("Sonos" is in the reply).
pub struct Discover {
    /// Multicast address in the local network
    multicast_addr: SocketAddr,
    /// Socket implementation
    /// INFO: The socket type will likely change in the future due to cross platform compatability
    socket: Arc<Socket>
}

impl Discover {
    /// Creates a new `Discovery`. Uses the default socket on the default ipv4 multicast address (239.255.255.250:1900).
    ///
    /// # Examples
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let discovery: Discovery = Discovery::new();
    /// ```
    pub fn new() -> Result<Self> {
        let multicast_address = match SocketAddr::from_str("239.255.255.250:1900") {
            Ok(address) => address,
            Err(_) => return ErrorKind::InvalidData
        };

        Discover::with_address(multicast_address)
    }

    /// Creates a new `Discovery` with a custom multicast address.
    pub fn with_address(address: SocketAddr) -> Result<Self> {
        let socket = Discover::create_default_socket()?;
        Ok(Discover {
            multicast_addr: address,
            socket: socket
        })
    }

    /// Create a default socket
    /// socket option: AF_INET - SOCK_DGRAM - 0 // Automatically discover the protocol (IPPROTO_UDP)
    /// socket option: IPPROTO_IP - IP_MULTICAST_TTL - 4 // UPnP 1.0 needs a TTL of 4
    fn create_default_socket() -> Result<Arc<Socket>> {
        let socket_family = AF_INET;
        let socket_level = SOCK_DGRAM;
        let protocol = 0; // auto discover
        let socket_options = vec![(IPPROTO_IP, IP_MULTICAST_TTL, 4)];

        Discover::create_socket(socket_family, socket_level, protocol, &socket_options)
    }

    fn create_socket<T: Clone>(socket_family: i32, socket_type: i32, protocol: i32, socket_options: &Vec<(i32, i32, T)>) -> Result<Arc<Socket>> {
        let socket = Socket::new(socket_family, socket_type, protocol)?;
        for socket_option in socket_options {
            // TODO: Use result, allow to fail, panic or return a result?
            let _ = socket.setsockopt(socket_option.0, socket_option.1, socket_option.2.clone());
        }

        Ok(Arc::new(socket))
    }

    /// Sends the search message to the defined socket.
    /// Message can't have leading/trailing whitespaces (\s).
    ///
    /// # Message
    /// ```
    /// M-SEARCH * HTTP/1.1
    /// HOST: 239.255.255.250:1900
    /// MAN: "ssdp:discover"
    /// MX: 1
    /// ST: urn:schemas-upnp-org:device:ZonePlayer:1```
    fn send_search(&self) -> Result<usize> {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();

        self.socket.sendto(player_search, 0, &self.multicast_addr)
    }

    /// Start discovering devices.
    ///
    /// # Examples
    /// In this example the search will stop if3 devices have been discovered or the default timeout (5s) is reached.
    /// This is useful if you know the amount of speakers you have and want to reduce the search time.
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let devices: HashSet<IpAddr> = Discovery::new().start(None, Some(3));
    /// ```
    pub fn start(&self, timeout: Option<u32>, device_count: Option<usize>) -> Result<HashSet<IpAddr>> {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search()?;
        // There's probably a better way than a double clone
        let socket = self.socket.clone();
        let mut devices: HashSet<IpAddr> = HashSet::new();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            thread::spawn(move ||
                {
                    // TODO: Add logging
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            // TODO: Add logging, fail on multiple send errors?
                            match sender.send((__addr, _data)) {
                                Ok(_) => {}
                                Err(_) => {}
                            };
                        }
                        Err(_) => {}
                    }
                }
            );

            // TODO: Add logging, change
            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };

            // Skip from_utf8_lossy
            // Due to the usual small size of `devices`, this is faster than decoding a potentially large response
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }

        Ok(devices)
    }
}

/// Drop internal socket on going out of scope
impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        // Log failure for debugging
        let _ = self.socket.close();
    }
}
<commit_msg>Create valid io::Error<commit_after>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::io::{Error, ErrorKind, Result};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

#[derive(Debug)]
/// `Discover` type
///
/// Used for discovering sonos devices in the local network via the simple service discovery protocol (ssdp).
/// The ssd-protocol works via udp sockets. First a certain search-message is sent to the multicast address (239.255.255.250:1900).
///
/// All answer from upnp (universal plug and play) ready devices are processed and filtered ("Sonos" is in the reply).
pub struct Discover {
    /// Multicast address in the local network
    multicast_addr: SocketAddr,
    /// Socket implementation
    /// INFO: The socket type will likely change in the future due to cross platform compatability
    socket: Arc<Socket>
}

impl Discover {
    /// Creates a new `Discovery`. Uses the default socket on the default ipv4 multicast address (239.255.255.250:1900).
    ///
    /// # Examples
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let discovery: Discovery = Discovery::new();
    /// ```
    pub fn new() -> Result<Self> {
        let multicast_address = match SocketAddr::from_str("239.255.255.250:1900") {
            Ok(address) => address,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Couldn't parse socket address"))
        };

        Discover::with_address(multicast_address)
    }

    /// Creates a new `Discovery` with a custom multicast address.
    pub fn with_address(address: SocketAddr) -> Result<Self> {
        let socket = Discover::create_default_socket()?;
        Ok(Discover {
            multicast_addr: address,
            socket: socket
        })
    }

    /// Create a default socket
    /// socket option: AF_INET - SOCK_DGRAM - 0 // Automatically discover the protocol (IPPROTO_UDP)
    /// socket option: IPPROTO_IP - IP_MULTICAST_TTL - 4 // UPnP 1.0 needs a TTL of 4
    fn create_default_socket() -> Result<Arc<Socket>> {
        let socket_family = AF_INET;
        let socket_level = SOCK_DGRAM;
        let protocol = 0; // auto discover
        let socket_options = vec![(IPPROTO_IP, IP_MULTICAST_TTL, 4)];

        Discover::create_socket(socket_family, socket_level, protocol, &socket_options)
    }

    fn create_socket<T: Clone>(socket_family: i32, socket_type: i32, protocol: i32, socket_options: &Vec<(i32, i32, T)>) -> Result<Arc<Socket>> {
        let socket = Socket::new(socket_family, socket_type, protocol)?;
        for socket_option in socket_options {
            // TODO: Use result, allow to fail, panic or return a result?
            let _ = socket.setsockopt(socket_option.0, socket_option.1, socket_option.2.clone());
        }

        Ok(Arc::new(socket))
    }

    /// Sends the search message to the defined socket.
    /// Message can't have leading/trailing whitespaces (\s).
    ///
    /// # Message
    /// ```
    /// M-SEARCH * HTTP/1.1
    /// HOST: 239.255.255.250:1900
    /// MAN: "ssdp:discover"
    /// MX: 1
    /// ST: urn:schemas-upnp-org:device:ZonePlayer:1```
    fn send_search(&self) -> Result<usize> {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();

        self.socket.sendto(player_search, 0, &self.multicast_addr)
    }

    /// Start discovering devices.
    ///
    /// # Examples
    /// In this example the search will stop if3 devices have been discovered or the default timeout (5s) is reached.
    /// This is useful if you know the amount of speakers you have and want to reduce the search time.
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let devices: HashSet<IpAddr> = Discovery::new().start(None, Some(3));
    /// ```
    pub fn start(&self, timeout: Option<u32>, device_count: Option<usize>) -> Result<HashSet<IpAddr>> {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search()?;
        // There's probably a better way than a double clone
        let socket = self.socket.clone();
        let mut devices: HashSet<IpAddr> = HashSet::new();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            thread::spawn(move ||
                {
                    // TODO: Add logging
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            // TODO: Add logging, fail on multiple send errors?
                            match sender.send((__addr, _data)) {
                                Ok(_) => {}
                                Err(_) => {}
                            };
                        }
                        Err(_) => {}
                    }
                }
            );

            // TODO: Add logging, change
            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };

            // Skip from_utf8_lossy
            // Due to the usual small size of `devices`, this is faster than decoding a potentially large response
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }

        Ok(devices)
    }
}

/// Drop internal socket on going out of scope
impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        // Log failure for debugging
        let _ = self.socket.close();
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate serde_derive;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate log;
extern crate encoding;
extern crate seek_bufread;
extern crate byteorder;
extern crate serde;
extern crate rwinstructs;
extern crate rshellitems;
pub mod lnkpkg;
<commit_msg>added trace create to lib<commit_after>#[macro_use] extern crate serde_derive;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate trace_error;
#[macro_use] extern crate log;
extern crate encoding;
extern crate seek_bufread;
extern crate byteorder;
extern crate serde;
extern crate rwinstructs;
extern crate rshellitems;
pub mod lnkpkg;
<|endoftext|>


<commit_before>pub fn init(args: &crate::args::Args) {
    let mut logger = MultiLog::new();
    if args.log_to_stdout {
        logger.push(WriterLog::new(std::io::stdout()));
    }
    if let Some(ref path) = args.log_to_file {
        let file = std::fs::OpenOptions::new()
            .append(true)
            .open(path)
            .expect("failed to open the log file");

        logger.push(WriterLog::new(file));
    }

    log::set_boxed_logger(Box::new(logger))
        .expect("failed to initialize logger");

    log::set_max_level(args.verbosity);
}

struct MultiLog {
    loggers: Vec<Box<dyn log::Log>>,
}

impl MultiLog {

    fn new() -> MultiLog {
        MultiLog {
            loggers: Vec::new(),
        }
    }

    fn push<L: log::Log + 'static>(&mut self, logger: L) {
        self.loggers.push(Box::new(logger));
    }
}

impl log::Log for MultiLog {

    fn enabled(&self, metadata: &log::Metadata) -> bool {
        self.loggers.iter().any(|logger| logger.enabled(metadata))
    }

    fn log(&self, record: &log::Record) {
        for log in &self.loggers {
            log.log(record);
        }
    }

    fn flush(&self) {
        for logger in &self.loggers {
            logger.flush();
        }
    }
}

struct WriterLog<W: std::io::Write + Send + Sync> {
    writer: std::sync::Mutex<W>,
}

impl<W: std::io::Write + Send + Sync> WriterLog<W> {

    fn new(writer: W) -> WriterLog<W> {
        WriterLog { writer: std::sync::Mutex::new(writer) }
    }
}

impl<W: std::io::Write + Send + Sync> log::Log for WriterLog<W> {

    fn enabled(&self, _metadata: &log::Metadata) -> bool {
        true
    }

    fn log(&self, record: &log::Record) {
        if !self.enabled(record.metadata()) {
            return;
        }

        let now = std::time::SystemTime::now();

        // We consider failures to write to the log stream critical. Otherwise,
        // if there is some other issue with the system it is not possible to
        // properly communicate it. Thus, we panic on all write errors.
        let mut writer = self.writer.lock()
            .expect("failed to acquire log output stream lock");

        || -> Result<(), std::io::Error> {
            write! {
                writer,
                "[{level} {timestamp} ",
                level = record.level(),
                timestamp = humantime::format_rfc3339_nanos(now)
            }?;
            match record.file() {
                Some(file) => write!(writer, "{file}")?,
                None => write!(writer, "<unknown>")?,
            }
            match record.line() {
                Some(line) => write!(writer, ":{line}]")?,
                None => write!(writer, ":<unknown>]")?,
            }

            write!(writer, " {}\n", record.args())?;

            Ok(())
        }().expect("failed to write to the log output stream")
    }

    fn flush(&self) {
        // Similarly to write errors, we also panic on flush errors as there is
        // nothing we can do otherwise.
        self.writer
            .lock()
            .expect("failed to acquire log output stream lock")
            .flush()
            .expect("failed to flush the log output stream");
    }
}
<commit_msg>Add docs for the `log` module.<commit_after>/// Initializes the logging submodule.
///
/// This function should be called only once at the beginning of the process
/// startup.
pub fn init(args: &crate::args::Args) {
    let mut logger = MultiLog::new();
    if args.log_to_stdout {
        logger.push(WriterLog::new(std::io::stdout()));
    }
    if let Some(ref path) = args.log_to_file {
        let file = std::fs::OpenOptions::new()
            .append(true)
            .open(path)
            .expect("failed to open the log file");

        logger.push(WriterLog::new(file));
    }

    log::set_boxed_logger(Box::new(logger))
        .expect("failed to initialize logger");

    log::set_max_level(args.verbosity);
}

/// A wrapper for logging to multiple destinations.
struct MultiLog {
    /// A list of all registered loggers.
    loggers: Vec<Box<dyn log::Log>>,
}

impl MultiLog {

    /// Creates a new wrapper with no registered loggers.
    fn new() -> MultiLog {
        MultiLog {
            loggers: Vec::new(),
        }
    }

    /// Registers a new destination to log to.
    fn push<L: log::Log + 'static>(&mut self, logger: L) {
        self.loggers.push(Box::new(logger));
    }
}

impl log::Log for MultiLog {

    fn enabled(&self, metadata: &log::Metadata) -> bool {
        self.loggers.iter().any(|logger| logger.enabled(metadata))
    }

    fn log(&self, record: &log::Record) {
        for log in &self.loggers {
            log.log(record);
        }
    }

    fn flush(&self) {
        for logger in &self.loggers {
            logger.flush();
        }
    }
}

/// A simple logger implementation for logging to writable streams (e.g. files).
struct WriterLog<W: std::io::Write + Send + Sync> {
    writer: std::sync::Mutex<W>,
}

impl<W: std::io::Write + Send + Sync> WriterLog<W> {

    /// Create a new logger for the given writable stream.
    fn new(writer: W) -> WriterLog<W> {
        WriterLog { writer: std::sync::Mutex::new(writer) }
    }
}

impl<W: std::io::Write + Send + Sync> log::Log for WriterLog<W> {

    fn enabled(&self, _metadata: &log::Metadata) -> bool {
        true
    }

    fn log(&self, record: &log::Record) {
        if !self.enabled(record.metadata()) {
            return;
        }

        let now = std::time::SystemTime::now();

        // We consider failures to write to the log stream critical. Otherwise,
        // if there is some other issue with the system it is not possible to
        // properly communicate it. Thus, we panic on all write errors.
        let mut writer = self.writer.lock()
            .expect("failed to acquire log output stream lock");

        || -> Result<(), std::io::Error> {
            write! {
                writer,
                "[{level} {timestamp} ",
                level = record.level(),
                timestamp = humantime::format_rfc3339_nanos(now)
            }?;
            match record.file() {
                Some(file) => write!(writer, "{file}")?,
                None => write!(writer, "<unknown>")?,
            }
            match record.line() {
                Some(line) => write!(writer, ":{line}]")?,
                None => write!(writer, ":<unknown>]")?,
            }

            write!(writer, " {}\n", record.args())?;

            Ok(())
        }().expect("failed to write to the log output stream")
    }

    fn flush(&self) {
        // Similarly to write errors, we also panic on flush errors as there is
        // nothing we can do otherwise.
        self.writer
            .lock()
            .expect("failed to acquire log output stream lock")
            .flush()
            .expect("failed to flush the log output stream");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over unix sockets
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//! extern crate rand;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

use mio::*;
use mio::unix::*;
use bytes::{Buf, ByteBuf, MutByteBuf};
use std::io;
use jsonrpc_core::IoHandler;
use std::sync::*;
use std::sync::atomic::*;
use std;
use slab;
use validator;
#[cfg(test)]
use tests;
use std::collections::VecDeque;

const SERVER: Token = Token(0);
const MAX_CONCURRENT_CONNECTIONS: usize = 16;
const MAX_WRITE_LENGTH: usize = 8192;

struct SocketConnection {
    socket: UnixStream,
    buf: Option<ByteBuf>,
    mut_buf: Option<MutByteBuf>,
    token: Option<Token>,
    interest: EventSet,
}

type Slab<T> = slab::Slab<T, Token>;

impl SocketConnection {
    fn new(sock: UnixStream) -> Self {
        SocketConnection {
            socket: sock,
            buf: None,
            mut_buf: Some(ByteBuf::mut_with_capacity(4096)),
            token: None,
            interest: EventSet::hup(),
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<RpcServer>, _handler: &IoHandler) -> io::Result<()> {
        use std::io::Write;
        if let Some(buf) = self.buf.take() {
			if buf.remaining() < MAX_WRITE_LENGTH {
	            try!(self.socket.write_all(&buf.bytes()));
				self.interest.remove(EventSet::writable());
				self.interest.insert(EventSet::readable());
			}
			else {
				try!(self.socket.write_all(&buf.bytes()[0..MAX_WRITE_LENGTH]));
				self.buf = Some(ByteBuf::from_slice(&buf.bytes()[MAX_WRITE_LENGTH..]));
			}
        }

        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn readable(&mut self, event_loop: &mut EventLoop<RpcServer>, handler: &IoHandler) -> io::Result<()> {
        let mut buf = self.mut_buf.take().unwrap_or_else(|| panic!("unwrapping mutable buffer which is None"));

        match self.socket.try_read_buf(&mut buf) {
            Ok(None) => {
				trace!(target: "ipc", "Empty read ({:?})", self.token);
                self.mut_buf = Some(buf);
				return Ok(());
            }
            Ok(Some(_)) => {
                let (requests, last_index) = validator::extract_requests(buf.bytes());
                if requests.len() > 0 {
                    let mut response_bytes = Vec::new();
                    for rpc_msg in requests {
                        trace!(target: "ipc", "Request: {}", rpc_msg);
                        let response: Option<String> = handler.handle_request(&rpc_msg);
                        if let Some(response_str) = response {
                            trace!(target: "ipc", "Response: {}", &response_str);
                            response_bytes.extend(response_str.into_bytes());
                        }
                    }
                    self.buf = Some(ByteBuf::from_slice(&response_bytes[..]));

                    let mut new_buf = ByteBuf::mut_with_capacity(4096);
                    new_buf.write_slice(&buf.bytes()[last_index+1..]);
                    self.mut_buf = Some(new_buf);

                    self.interest.remove(EventSet::readable());
                    self.interest.insert(EventSet::writable());
                }
                else {
                    self.mut_buf = Some(buf);
                }
            }
            Err(e) => {
                trace!(target: "ipc", "Error receiving data ({:?}): {:?}", self.token, e);
                self.interest.remove(EventSet::readable());
            }

        };
        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }
}

struct RpcServer {
    socket: UnixListener,
    connections: Slab<SocketConnection>,
    io_handler: Arc<IoHandler>,
	tokens: VecDeque<Token>,
}

pub struct Server {
    rpc_server: Arc<RwLock<RpcServer>>,
    event_loop: Arc<RwLock<EventLoop<RpcServer>>>,
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server, Error> {
        let (server, event_loop) = try!(RpcServer::start(socket_addr, io_handler));
        Ok(Server {
            rpc_server: Arc::new(RwLock::new(server)),
            event_loop: Arc::new(RwLock::new(event_loop)),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in current thread)
    pub fn run(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();
        event_loop.run(&mut server).unwrap();
    }

    /// Poll server requests (for manual async scenarios)
    pub fn poll(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();

        event_loop.run_once(&mut server, Some(100)).unwrap();
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<(), Error> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        self.is_stopped.store(false, Ordering::Relaxed);

        let event_loop = self.event_loop.clone();
        let server = self.rpc_server.clone();
        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        std::thread::spawn(move || {
            let mut event_loop = event_loop.write().unwrap();
            let mut server = server.write().unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
                event_loop.run_once(&mut server, Some(100)).unwrap();
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });
        Ok(())
    }

    pub fn stop_async(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::sleep(std::time::Duration::new(0, 10)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        ::std::fs::remove_file(&self.addr).unwrap_or_else(|_| {}); // ignoer error - server could have never been started
    }
}

impl RpcServer {

    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<(RpcServer, EventLoop<RpcServer>), Error> {
        let mut event_loop = try!(EventLoop::new());
        ::std::fs::remove_file(addr).unwrap_or_else(|_| {} ); // ignore error (if no file)
        let socket = try!(UnixListener::bind(&addr));
        event_loop.register(&socket, SERVER, EventSet::readable(), PollOpt::edge()).unwrap();
        let server = RpcServer {
            socket: socket,
            connections: Slab::new_starting_at(Token(1), MAX_CONCURRENT_CONNECTIONS),
            io_handler: io_handler.clone(),
			tokens: VecDeque::new(),
        };
        Ok((server, event_loop))
    }

    fn accept(&mut self, event_loop: &mut EventLoop<RpcServer>) -> io::Result<()> {
        let new_client_socket = self.socket.accept().unwrap().unwrap();
        let connection = SocketConnection::new(new_client_socket);
        if self.connections.count() >= MAX_CONCURRENT_CONNECTIONS {
            let oldest_token = self.tokens.pop_front()
                .expect("fatal: impossible since count > MAX_CONCURRENT_CONNECTIONS and we request the oldest one")
                .clone();

            let oldest_connection = self.connections.remove(oldest_token).expect("There is max connections here");
			trace!(target: "ipc", "Recycled old socket {:?}", oldest_token);
        }
        let token = self.connections.insert(connection).ok().expect("fatal: Could not add connection to slab (memory issue?)");
		self.tokens.push_back(token);

		trace!(target: "ipc", "Accepted connection with token {:?}", token);

        self.connections[token].token = Some(token);
        event_loop.register(
            &self.connections[token].socket,
            token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).ok().expect("fatal: could not register socket with event loop (memory issue?)");

        Ok(())
    }

    fn connection_readable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).readable(event_loop, &io_handler)
    }

    fn connection_writable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).writable(event_loop, &io_handler)
    }

    fn connection<'a>(&'a mut self, tok: Token) -> &'a mut SocketConnection {
        &mut self.connections[tok]
    }
}

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

    fn ready(&mut self, event_loop: &mut EventLoop<RpcServer>, token: Token, events: EventSet) {
        if events.is_readable() {
            match token {
                SERVER => self.accept(event_loop).unwrap(),
                _ => self.connection_readable(event_loop, token).unwrap()
            };
        }

        if events.is_writable() {
            match token {
                SERVER => { },
                _ => self.connection_writable(event_loop, token).unwrap_or_else(|_| {}), // todo: disqualify connection from list on error
            };
        }
    }
}

#[test]
pub fn test_reqrep_poll() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    let server = Server::new(&addr, &io).unwrap();
    std::thread::spawn(move || {
        loop {
            server.poll();
        }
    });

    let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
    let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
    assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());

    std::thread::sleep(std::time::Duration::from_millis(500));
}

#[test]
pub fn test_file_removed() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    {
        let server = Server::new(&addr, &io).unwrap();
        server.run_async().unwrap();
        std::thread::sleep(std::time::Duration::from_millis(50));

        let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
        let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
        assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());
    }
    assert!(::std::fs::metadata(addr).is_err()); // err is file not exists
}
<commit_msg>fix warning<commit_after>// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! jsonrpc server over unix sockets
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate json_ipc_server;
//! extern crate rand;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use json_ipc_server::Server;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let server = Server::new("/tmp/json-ipc-test.ipc", &Arc::new(io)).unwrap();
//!     ::std::thread::spawn(move || server.run());
//! }
//! ```

use mio::*;
use mio::unix::*;
use bytes::{Buf, ByteBuf, MutByteBuf};
use std::io;
use jsonrpc_core::IoHandler;
use std::sync::*;
use std::sync::atomic::*;
use std;
use slab;
use validator;
#[cfg(test)]
use tests;
use std::collections::VecDeque;

const SERVER: Token = Token(0);
const MAX_CONCURRENT_CONNECTIONS: usize = 16;
const MAX_WRITE_LENGTH: usize = 8192;

struct SocketConnection {
    socket: UnixStream,
    buf: Option<ByteBuf>,
    mut_buf: Option<MutByteBuf>,
    token: Option<Token>,
    interest: EventSet,
}

type Slab<T> = slab::Slab<T, Token>;

impl SocketConnection {
    fn new(sock: UnixStream) -> Self {
        SocketConnection {
            socket: sock,
            buf: None,
            mut_buf: Some(ByteBuf::mut_with_capacity(4096)),
            token: None,
            interest: EventSet::hup(),
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<RpcServer>, _handler: &IoHandler) -> io::Result<()> {
        use std::io::Write;
        if let Some(buf) = self.buf.take() {
			if buf.remaining() < MAX_WRITE_LENGTH {
	            try!(self.socket.write_all(&buf.bytes()));
				self.interest.remove(EventSet::writable());
				self.interest.insert(EventSet::readable());
			}
			else {
				try!(self.socket.write_all(&buf.bytes()[0..MAX_WRITE_LENGTH]));
				self.buf = Some(ByteBuf::from_slice(&buf.bytes()[MAX_WRITE_LENGTH..]));
			}
        }

        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }

    fn readable(&mut self, event_loop: &mut EventLoop<RpcServer>, handler: &IoHandler) -> io::Result<()> {
        let mut buf = self.mut_buf.take().unwrap_or_else(|| panic!("unwrapping mutable buffer which is None"));

        match self.socket.try_read_buf(&mut buf) {
            Ok(None) => {
				trace!(target: "ipc", "Empty read ({:?})", self.token);
                self.mut_buf = Some(buf);
				return Ok(());
            }
            Ok(Some(_)) => {
                let (requests, last_index) = validator::extract_requests(buf.bytes());
                if requests.len() > 0 {
                    let mut response_bytes = Vec::new();
                    for rpc_msg in requests {
                        trace!(target: "ipc", "Request: {}", rpc_msg);
                        let response: Option<String> = handler.handle_request(&rpc_msg);
                        if let Some(response_str) = response {
                            trace!(target: "ipc", "Response: {}", &response_str);
                            response_bytes.extend(response_str.into_bytes());
                        }
                    }
                    self.buf = Some(ByteBuf::from_slice(&response_bytes[..]));

                    let mut new_buf = ByteBuf::mut_with_capacity(4096);
                    new_buf.write_slice(&buf.bytes()[last_index+1..]);
                    self.mut_buf = Some(new_buf);

                    self.interest.remove(EventSet::readable());
                    self.interest.insert(EventSet::writable());
                }
                else {
                    self.mut_buf = Some(buf);
                }
            }
            Err(e) => {
                trace!(target: "ipc", "Error receiving data ({:?}): {:?}", self.token, e);
                self.interest.remove(EventSet::readable());
            }

        };
        event_loop.reregister(&self.socket, self.token.unwrap(), self.interest, PollOpt::edge() | PollOpt::oneshot())
    }
}

struct RpcServer {
    socket: UnixListener,
    connections: Slab<SocketConnection>,
    io_handler: Arc<IoHandler>,
	tokens: VecDeque<Token>,
}

pub struct Server {
    rpc_server: Arc<RwLock<RpcServer>>,
    event_loop: Arc<RwLock<EventLoop<RpcServer>>>,
    is_stopping: Arc<AtomicBool>,
    is_stopped: Arc<AtomicBool>,
    addr: String,
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    NotStarted,
    AlreadyStopping,
    NotStopped,
    IsStopping,
}

impl std::convert::From<std::io::Error> for Error {
    fn from(io_error: std::io::Error) -> Error {
        Error::Io(io_error)
    }
}

impl Server {
    /// New server
    pub fn new(socket_addr: &str, io_handler: &Arc<IoHandler>) -> Result<Server, Error> {
        let (server, event_loop) = try!(RpcServer::start(socket_addr, io_handler));
        Ok(Server {
            rpc_server: Arc::new(RwLock::new(server)),
            event_loop: Arc::new(RwLock::new(event_loop)),
            is_stopping: Arc::new(AtomicBool::new(false)),
            is_stopped: Arc::new(AtomicBool::new(true)),
            addr: socket_addr.to_owned(),
        })
    }

    /// Run server (in current thread)
    pub fn run(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();
        event_loop.run(&mut server).unwrap();
    }

    /// Poll server requests (for manual async scenarios)
    pub fn poll(&self) {
        let mut event_loop = self.event_loop.write().unwrap();
        let mut server = self.rpc_server.write().unwrap();

        event_loop.run_once(&mut server, Some(100)).unwrap();
    }

    /// Run server (in separate thread)
    pub fn run_async(&self) -> Result<(), Error> {
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::IsStopping) }
        if !self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStopped) }

        self.is_stopped.store(false, Ordering::Relaxed);

        let event_loop = self.event_loop.clone();
        let server = self.rpc_server.clone();
        let thread_stopping = self.is_stopping.clone();
        let thread_stopped = self.is_stopped.clone();
        std::thread::spawn(move || {
            let mut event_loop = event_loop.write().unwrap();
            let mut server = server.write().unwrap();
            while !thread_stopping.load(Ordering::Relaxed) {
                event_loop.run_once(&mut server, Some(100)).unwrap();
            }
            thread_stopped.store(true, Ordering::Relaxed);
        });
        Ok(())
    }

    pub fn stop_async(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        Ok(())
    }

    pub fn stop(&self) -> Result<(), Error> {
        if self.is_stopped.load(Ordering::Relaxed) { return Err(Error::NotStarted) }
        if self.is_stopping.load(Ordering::Relaxed) { return Err(Error::AlreadyStopping)}
        self.is_stopping.store(true, Ordering::Relaxed);
        while !self.is_stopped.load(Ordering::Relaxed) { std::thread::sleep(std::time::Duration::new(0, 10)); }
        Ok(())
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        self.stop().unwrap_or_else(|_| {}); // ignore error - can be stopped already
        ::std::fs::remove_file(&self.addr).unwrap_or_else(|_| {}); // ignoer error - server could have never been started
    }
}

impl RpcServer {

    /// start ipc rpc server (blocking)
    pub fn start(addr: &str, io_handler: &Arc<IoHandler>) -> Result<(RpcServer, EventLoop<RpcServer>), Error> {
        let mut event_loop = try!(EventLoop::new());
        ::std::fs::remove_file(addr).unwrap_or_else(|_| {} ); // ignore error (if no file)
        let socket = try!(UnixListener::bind(&addr));
        event_loop.register(&socket, SERVER, EventSet::readable(), PollOpt::edge()).unwrap();
        let server = RpcServer {
            socket: socket,
            connections: Slab::new_starting_at(Token(1), MAX_CONCURRENT_CONNECTIONS),
            io_handler: io_handler.clone(),
			tokens: VecDeque::new(),
        };
        Ok((server, event_loop))
    }

    fn accept(&mut self, event_loop: &mut EventLoop<RpcServer>) -> io::Result<()> {
        let new_client_socket = self.socket.accept().unwrap().unwrap();
        let connection = SocketConnection::new(new_client_socket);
        if self.connections.count() >= MAX_CONCURRENT_CONNECTIONS {
            let oldest_token = self.tokens.pop_front()
                .expect("fatal: impossible since count > MAX_CONCURRENT_CONNECTIONS and we request the oldest one")
                .clone();

			trace!(target: "ipc", "Reusing the most old token {:?}", oldest_token);
        }
        let token = self.connections.insert(connection).ok().expect("fatal: Could not add connection to slab (memory issue?)");
		self.tokens.push_back(token);

		trace!(target: "ipc", "Accepted connection with token {:?}", token);

        self.connections[token].token = Some(token);
        event_loop.register(
            &self.connections[token].socket,
            token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).ok().expect("fatal: could not register socket with event loop (memory issue?)");

        Ok(())
    }

    fn connection_readable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).readable(event_loop, &io_handler)
    }

    fn connection_writable(&mut self, event_loop: &mut EventLoop<RpcServer>, tok: Token) -> io::Result<()> {
        let io_handler = self.io_handler.clone();
        self.connection(tok).writable(event_loop, &io_handler)
    }

    fn connection<'a>(&'a mut self, tok: Token) -> &'a mut SocketConnection {
        &mut self.connections[tok]
    }
}

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

    fn ready(&mut self, event_loop: &mut EventLoop<RpcServer>, token: Token, events: EventSet) {
        if events.is_readable() {
            match token {
                SERVER => self.accept(event_loop).unwrap(),
                _ => self.connection_readable(event_loop, token).unwrap()
            };
        }

        if events.is_writable() {
            match token {
                SERVER => { },
                _ => self.connection_writable(event_loop, token).unwrap_or_else(|_| {}), // todo: disqualify connection from list on error
            };
        }
    }
}

#[test]
pub fn test_reqrep_poll() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    let server = Server::new(&addr, &io).unwrap();
    std::thread::spawn(move || {
        loop {
            server.poll();
        }
    });

    let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
    let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
    assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());

    std::thread::sleep(std::time::Duration::from_millis(500));
}

#[test]
pub fn test_file_removed() {
    let addr = tests::random_ipc_endpoint();
    let io = tests::dummy_io_handler();
    {
        let server = Server::new(&addr, &io).unwrap();
        server.run_async().unwrap();
        std::thread::sleep(std::time::Duration::from_millis(50));

        let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
        let response = r#"{"jsonrpc":"2.0","result":"hello 42! you sent 23","id":1}"#;
        assert_eq!(String::from_utf8(tests::dummy_request(&addr, request.as_bytes())).unwrap(), response.to_string());
    }
    assert!(::std::fs::metadata(addr).is_err()); // err is file not exists
}
<|endoftext|>


<commit_before>//! A module for common example logic, in an attempt to keep the example
//! source files as concise as possible.
extern crate cgmath;
extern crate glium;

use self::cgmath::*;
use self::glium::*;
use self::glium::uniforms::*;
use self::glium::backend::glutin_backend::GlutinFacade;

/// Shared data used in the examples.
pub struct ExampleData<'a> {

    /// The shader program used to render the shapes.
    pub program: glium::Program,

    /// The draw parameter state used to render the shapes.
    pub draw_params: glium::DrawParameters<'a>
}

/// A type to represent the frame-varying uniforms in the examples. At
/// the moment, this just holds the camera (view * projection) matrix.
pub type FrameUniforms<'a> = UniformsStorage<'a, [[f32; 4]; 4], EmptyUniforms>;

/// Setup the glium display and example data and return them both in a tuple.
pub fn setup<'a>() -> (GlutinFacade, ExampleData<'a>) {

    let display = glium::glutin::WindowBuilder::new()
        .with_dimensions(600, 600)
        .with_depth_buffer(16)
        .with_title("Example Viewer".into())
        .build_glium()
        .expect("Failed to build glium display");

    let data = ExampleData {
        program: program!(&display,
            140 => {
                vertex: "
                    #version 140

                    in vec3 position;
                    in vec3 normal;
                    in vec2 texcoord;

                    out vec3 v_normal;
                    out vec2 v_texcoord;

                    uniform mat4 matrix;

                    void main() {
                        gl_Position = matrix * vec4( position, 1.0 );
                        v_normal = normal;
                    }
                ",
                fragment: "
                    #version 140

                    in vec3 v_normal;
                    in vec2 v_texcoord;

                    out vec4 fragColor;

                    void main() {
                        fragColor = vec4( ( v_normal + 1 ) / 2, 1.0 );
                    }
                ",
            }
        ).expect("Failed to compile shader program"),
        draw_params: glium::DrawParameters {
            backface_culling: BackfaceCullingMode::CullClockwise,
            depth: glium::Depth {
                test: glium::draw_parameters::DepthTest::IfLess,
                write: true,
                .. Default::default()
            },
            .. Default::default()
        }
    };
    return (display, data);
}

/// Process any pending events in the glium display. Return true if the
/// display is still open, or false if the user has closed the display.
pub fn process_events(display: &GlutinFacade) -> bool {
    for event in display.poll_events() {
        match event {
            glium::glutin::Event::Closed => return false,
            _ => continue
        }
    }
    return true;
}

/// Called before rendering a frame. Returns the glium frame and the
/// uniforms that should be used for this frame.
pub fn begin_frame<'a>(display: &GlutinFacade) -> (glium::Frame, FrameUniforms<'a>) {
    let mut frame = display.draw();
    frame.clear_color(0.1, 0.1, 0.1, 1.0);
    frame.clear_depth(1.0);
    let uniforms = build_frame_uniforms(&frame);
    return (frame, uniforms);
}

/// Called after rendering a frame. Swaps the display buffers.
pub fn end_frame(frame: glium::Frame) {
    frame.finish().expect("Failed to draw frame");
}

/// Build the frame-varying uniforms. At the moment, this just
/// consists of the camera (view * projection) matrix.
fn build_frame_uniforms<'a>(frame: &glium::Frame) -> FrameUniforms<'a> {
    let (width, height) = frame.get_dimensions();

    let projection = cgmath::PerspectiveFov::<f32> {
        fovy: cgmath::Rad::<f32>::from( cgmath::Deg::<f32>::new( 90.0 ) ),
        aspect: width as f32 / height as f32,
        near: 1.0,
        far: 1000.0
    };

    let view = cgmath::Matrix4::<f32>::from_translation(
        cgmath::Vector3::<f32>::new(0.0, 0.0, -10.0)
    );

    let uniforms = uniform! {
        matrix: (cgmath::Matrix4::<f32>::from(projection) * view).into()
    };

    return uniforms;
}
<commit_msg>Minor formatting fixes in common examples module<commit_after>//! A module for common example logic, in an attempt to keep the example
//! source files as concise as possible.
extern crate cgmath;
extern crate glium;

use self::cgmath::*;
use self::glium::*;
use self::glium::uniforms::*;
use self::glium::backend::glutin_backend::GlutinFacade;

/// Shared data used in the examples.
pub struct ExampleData<'a> {

    /// The shader program used to render the shapes.
    pub program: glium::Program,

    /// The draw parameter state used to render the shapes.
    pub draw_params: glium::DrawParameters<'a>
}

/// A type to represent the frame-varying uniforms in the examples. At
/// the moment, this just holds the camera (view * projection) matrix.
pub type FrameUniforms<'a> = UniformsStorage<'a, [[f32; 4]; 4], EmptyUniforms>;

/// Setup the glium display and example data and return them both in a tuple.
pub fn setup<'a>() -> (GlutinFacade, ExampleData<'a>) {

    let display = glium::glutin::WindowBuilder::new()
        .with_dimensions(600, 600)
        .with_depth_buffer(16)
        .with_title("Example Viewer".into())
        .build_glium()
        .expect("Failed to build glium display");

    let data = ExampleData {
        program: program!(&display,
            140 => {
                vertex: "
                    #version 140

                    in vec3 position;
                    in vec3 normal;
                    in vec2 texcoord;

                    out vec3 v_normal;
                    out vec2 v_texcoord;

                    uniform mat4 matrix;

                    void main() {
                        gl_Position = matrix * vec4(position, 1.0);
                        v_normal = normal;
                    }
                ",
                fragment: "
                    #version 140

                    in vec3 v_normal;
                    in vec2 v_texcoord;

                    out vec4 fragColor;

                    void main() {
                        fragColor = vec4((v_normal + 1) / 2, 1.0);
                    }
                ",
            }
        ).expect("Failed to compile shader program"),
        draw_params: glium::DrawParameters {
            backface_culling: BackfaceCullingMode::CullClockwise,
            depth: glium::Depth {
                test: glium::draw_parameters::DepthTest::IfLess,
                write: true,
                .. Default::default()
            },
            .. Default::default()
        }
    };
    return (display, data);
}

/// Process any pending events in the glium display. Return true if the
/// display is still open, or false if the user has closed the display.
pub fn process_events(display: &GlutinFacade) -> bool {
    for event in display.poll_events() {
        match event {
            glium::glutin::Event::Closed => return false,
            _ => continue
        }
    }
    return true;
}

/// Called before rendering a frame. Returns the glium frame and the
/// uniforms that should be used for this frame.
pub fn begin_frame<'a>(display: &GlutinFacade) -> (glium::Frame, FrameUniforms<'a>) {
    let mut frame = display.draw();
    frame.clear_color(0.1, 0.1, 0.1, 1.0);
    frame.clear_depth(1.0);
    let uniforms = build_frame_uniforms(&frame);
    return (frame, uniforms);
}

/// Called after rendering a frame. Swaps the display buffers.
pub fn end_frame(frame: glium::Frame) {
    frame.finish().expect("Failed to draw frame");
}

/// Build the frame-varying uniforms. At the moment, this just
/// consists of the camera (view * projection) matrix.
fn build_frame_uniforms<'a>(frame: &glium::Frame) -> FrameUniforms<'a> {
    let (width, height) = frame.get_dimensions();

    let projection = cgmath::PerspectiveFov::<f32> {
        fovy: cgmath::Rad::<f32>::from(cgmath::Deg::<f32>::new(90.0)),
        aspect: width as f32 / height as f32,
        near: 1.0,
        far: 1000.0
    };

    let view = cgmath::Matrix4::<f32>::from_translation(
        cgmath::Vector3::<f32>::new(0.0, 0.0, -10.0)
    );

    let uniforms = uniform! {
        matrix: (cgmath::Matrix4::<f32>::from(projection) * view).into()
    };

    return uniforms;
}
<|endoftext|>


<commit_before>
//! # Program Specific Information (PSI)

use super::base::*;

bit_struct!(
    #[derive(Debug,Clone)]
    pub struct ProgramAssociationTable {
        pub transport_stream_id: u16,
        pub version_number: u8,
        pub current_next_indicator: bool,
        pub section_number: u8,
        pub last_section_number: u8,
        pub associations: Vec<ProgramAssociation>
    }
    deserialize(reader) {
        expect: { bits: 8, reference: 0 }, // table_id
        expect: { bits: 1, reference: 1 }, // section_syntax_indicator
        expect: { bits: 1, reference: 0 }, // just a constant zero bit
        reserved: { 2 },
        section_length: { 12, type: u16 },
        transport_stream_id: { 16 },
        reserved: { 2 },
        version_number: { 5 },
        current_next_indicator: { 1, map: |b: u8| b == 1 },
        section_number: { 8 },
        last_section_number: { 8 },
        associations: { value: {
            let fixed_bytes = 12; // How many bytes for header and CRC field
            let association_size = 4; // How many bytes for single program association
            let data_bytes = section_length - fixed_bytes;
            let num_associations = data_bytes / association_size;

            let mut associations = vec![];
            for _ in 0..num_associations {
                associations.push(try!(Deserialize::deserialize(reader)));
            }
            associations
        } },
        crc: { 32 }
    }
);

#[derive(Debug,Copy,Clone)]
pub enum ProgramAssociation {
    NetworkPid(u16),
    ProgramMapPid{
        program_number: u16,
        program_map_pid: u16,
    },
}

impl Deserialize for ProgramAssociation {
    fn deserialize(reader: &mut ::bitreader::BitReader) -> DeserializationResult<Self> {
        let program_number = try!(reader.read_u16(16));
        try!(reserved(reader, 3));
        let pid = try!(reader.read_u16(13));
        let association = if program_number == 0 {
            ProgramAssociation::NetworkPid(pid)
        } else {
            ProgramAssociation::ProgramMapPid {
                program_number: program_number,
                program_map_pid: pid,
            }
        };
        Ok(association)
    }
}
<commit_msg>Rename ProgramAssociationTable to -Section.<commit_after>
//! # Program Specific Information (PSI)

use super::base::*;

bit_struct!(
    #[derive(Debug,Clone)]
    pub struct ProgramAssociationSection {
        pub transport_stream_id: u16,
        pub version_number: u8,
        pub current_next_indicator: bool,
        pub section_number: u8,
        pub last_section_number: u8,
        pub associations: Vec<ProgramAssociation>
    }
    deserialize(reader) {
        expect: { bits: 8, reference: 0 }, // table_id
        expect: { bits: 1, reference: 1 }, // section_syntax_indicator
        expect: { bits: 1, reference: 0 }, // just a constant zero bit
        reserved: { 2 },
        section_length: { 12, type: u16 },
        transport_stream_id: { 16 },
        reserved: { 2 },
        version_number: { 5 },
        current_next_indicator: { 1, map: |b: u8| b == 1 },
        section_number: { 8 },
        last_section_number: { 8 },
        associations: { value: {
            let fixed_bytes = 12; // How many bytes for header and CRC field
            let association_size = 4; // How many bytes for single program association
            let data_bytes = section_length - fixed_bytes;
            let num_associations = data_bytes / association_size;

            let mut associations = vec![];
            for _ in 0..num_associations {
                associations.push(try!(Deserialize::deserialize(reader)));
            }
            associations
        } },
        crc: { 32 }
    }
);

#[derive(Debug,Copy,Clone)]
pub enum ProgramAssociation {
    NetworkPid(u16),
    ProgramMapPid{
        program_number: u16,
        program_map_pid: u16,
    },
}

impl Deserialize for ProgramAssociation {
    fn deserialize(reader: &mut ::bitreader::BitReader) -> DeserializationResult<Self> {
        let program_number = try!(reader.read_u16(16));
        try!(reserved(reader, 3));
        let pid = try!(reader.read_u16(13));
        let association = if program_number == 0 {
            ProgramAssociation::NetworkPid(pid)
        } else {
            ProgramAssociation::ProgramMapPid {
                program_number: program_number,
                program_map_pid: pid,
            }
        };
        Ok(association)
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io;
use std::io::Write;
#[cfg(windows)]
use std::io::{Seek, SeekFrom};
use std::path::Path;
#[cfg(unix)]
use std::os::unix::fs::FileExt;
#[cfg(windows)]
use std::os::windows::fs::FileExt;

use super::{ReadAt, WriteAt};

/// A wrapper for `File` that provides optimized random access through
/// `ReadAt` and `WriteAt`.
///
/// * On Unix the operating system is advised that reads will be in random
///   order (`FADV_RANDOM`).
/// * On Windows the implementation is orders of magnitude faster than `ReadAt`
///   directly on `File`.
///
/// # Examples
///
/// Read the fifth 512-byte sector of a file:
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use positioned_io::{RandomAccessFile, ReadAt};
///
/// // open a file (note: binding does not need to be mut)
/// let raf = RandomAccessFile::open("tests/pi.txt")?;
///
/// // read up to 512 bytes
/// let mut buf = [0; 512];
/// let bytes_read = raf.read_at(2048, &mut buf)?;
/// #     assert!(buf.starts_with(b"4"));
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
#[derive(Debug)]
pub struct RandomAccessFile {
    file: File,
    #[cfg(not(unix))]
    pos: u64,
}

impl RandomAccessFile {
    /// [Opens](https://doc.rust-lang.org/std/fs/struct.File.html#method.open)
    /// a file for random access.
    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new(File::open(path)?)
    }

    /// Creates a `RandomAccessFile` wrapper around a `File`.
    pub fn try_new(file: File) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new_impl(file)
    }

    #[cfg(all(unix, target_os = "linux"))]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        unsafe {
            use std::os::unix::io::AsRawFd;
            #[cfg(target_pointer_width = "32")]
            libc::posix_fadvise(file.as_raw_fd(), 0, file.metadata()?.len() as i32, libc::POSIX_FADV_RANDOM);
            #[cfg(target_pointer_width = "64")]
            libc::posix_fadvise(file.as_raw_fd(), 0, file.metadata()?.len() as i64, libc::POSIX_FADV_RANDOM);
        }

        Ok(RandomAccessFile { file })
    }

    #[cfg(all(unix, not(target_os = "linux")))]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        Ok(RandomAccessFile { file })
    }

    #[cfg(not(unix))]
    fn try_new_impl(mut file: File) -> io::Result<RandomAccessFile> {
        let pos = file.seek(SeekFrom::Current(0))?;
        Ok(RandomAccessFile { file, pos })
    }

    /// Tries to unwrap the inner `File`.
    pub fn try_into_inner(self) -> Result<File, (RandomAccessFile, io::Error)> {
        RandomAccessFile::try_into_inner_impl(self)
    }

    #[cfg(unix)]
    fn try_into_inner_impl(self) -> Result<File, (RandomAccessFile, io::Error)> {
        Ok(self.file)
    }

    #[cfg(not(unix))]
    fn try_into_inner_impl(mut self) -> Result<File, (RandomAccessFile, io::Error)> {
        match self.file.seek(SeekFrom::Start(self.pos)) {
            Ok(_) => Ok(self.file),
            Err(err) => Err((self, err)),
        }
    }
}

#[cfg(unix)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::read_at(&self.file, buf, pos)
    }
}

#[cfg(unix)]
impl WriteAt for &RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::write_at(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut &self.file)
    }
}

#[cfg(windows)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::seek_read(&self.file, buf, pos)
    }
}

#[cfg(windows)]
impl WriteAt for &RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::seek_write(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut &self.file)
    }
}

impl WriteAt for RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        WriteAt::write_at(&mut &*self, pos, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        WriteAt::flush(&mut &*self)
    }
}
<commit_msg>Use libc::off_t for width to be arch independent<commit_after>use std::fs::File;
use std::io;
use std::io::Write;
#[cfg(windows)]
use std::io::{Seek, SeekFrom};
use std::path::Path;
#[cfg(unix)]
use std::os::unix::fs::FileExt;
#[cfg(windows)]
use std::os::windows::fs::FileExt;

use super::{ReadAt, WriteAt};

/// A wrapper for `File` that provides optimized random access through
/// `ReadAt` and `WriteAt`.
///
/// * On Unix the operating system is advised that reads will be in random
///   order (`FADV_RANDOM`).
/// * On Windows the implementation is orders of magnitude faster than `ReadAt`
///   directly on `File`.
///
/// # Examples
///
/// Read the fifth 512-byte sector of a file:
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use positioned_io::{RandomAccessFile, ReadAt};
///
/// // open a file (note: binding does not need to be mut)
/// let raf = RandomAccessFile::open("tests/pi.txt")?;
///
/// // read up to 512 bytes
/// let mut buf = [0; 512];
/// let bytes_read = raf.read_at(2048, &mut buf)?;
/// #     assert!(buf.starts_with(b"4"));
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
#[derive(Debug)]
pub struct RandomAccessFile {
    file: File,
    #[cfg(not(unix))]
    pos: u64,
}

impl RandomAccessFile {
    /// [Opens](https://doc.rust-lang.org/std/fs/struct.File.html#method.open)
    /// a file for random access.
    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new(File::open(path)?)
    }

    /// Creates a `RandomAccessFile` wrapper around a `File`.
    pub fn try_new(file: File) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new_impl(file)
    }

    #[cfg(all(unix, target_os = "linux"))]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        unsafe {
            use std::os::unix::io::AsRawFd;
            libc::posix_fadvise(file.as_raw_fd(), 0, file.metadata()?.len() as libc::off_t, libc::POSIX_FADV_RANDOM);
        }

        Ok(RandomAccessFile { file })
    }

    #[cfg(all(unix, not(target_os = "linux")))]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        Ok(RandomAccessFile { file })
    }

    #[cfg(not(unix))]
    fn try_new_impl(mut file: File) -> io::Result<RandomAccessFile> {
        let pos = file.seek(SeekFrom::Current(0))?;
        Ok(RandomAccessFile { file, pos })
    }

    /// Tries to unwrap the inner `File`.
    pub fn try_into_inner(self) -> Result<File, (RandomAccessFile, io::Error)> {
        RandomAccessFile::try_into_inner_impl(self)
    }

    #[cfg(unix)]
    fn try_into_inner_impl(self) -> Result<File, (RandomAccessFile, io::Error)> {
        Ok(self.file)
    }

    #[cfg(not(unix))]
    fn try_into_inner_impl(mut self) -> Result<File, (RandomAccessFile, io::Error)> {
        match self.file.seek(SeekFrom::Start(self.pos)) {
            Ok(_) => Ok(self.file),
            Err(err) => Err((self, err)),
        }
    }
}

#[cfg(unix)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::read_at(&self.file, buf, pos)
    }
}

#[cfg(unix)]
impl WriteAt for &RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::write_at(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut &self.file)
    }
}

#[cfg(windows)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::seek_read(&self.file, buf, pos)
    }
}

#[cfg(windows)]
impl WriteAt for &RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::seek_write(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut &self.file)
    }
}

impl WriteAt for RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        WriteAt::write_at(&mut &*self, pos, buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        WriteAt::flush(&mut &*self)
    }
}
<|endoftext|>


<commit_before>extern crate time;

use std::ops::Deref;

use ::expr::{Expr, Type, Error as E, Result};
use ::eval::funcall;
use ::env::Env;
use ::util::*;
use ::datetime::datetime_info_to_timespec;

pub fn k_skk_calc(env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (op, Sym));
    let skk_num_list = try!(env.find(&"skk-num-list".to_string())).clone();
    get_args!(&skk_num_list, (x, Int) (y, Int));
    let res = match &op[..] {
        "+" => x + y,
        "-" => x - y,
        "*" => x * y,
        "/" => x / y,
        op => return //Err(format!("unknown operator {}", op))
                       Err(E::User(format!("unknown operator {}", op)))
    };
    Ok(kint(res))
}

pub fn k_skk_current_date_1(_: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, &optional (specified_time, Any));
    // TODO: don't allocate month/wday table every time
    let mvec = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    let wvec = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    let now = specified_time.map_or(Ok(time::now()), |st| datetime_info_to_timespec(st).map(|tm| time::at(tm)));
    let now = try!(now);
    let year = (now.tm_year + 1900).to_string();
    let month = mvec[now.tm_mon as usize];
    let mday = now.tm_mday.to_string();
    let wday = wvec[now.tm_wday as usize];
    let hour = now.tm_hour.to_string();
    let min = now.tm_min.to_string();
    let sec = now.tm_sec.to_string();
    Ok(klist!(year, month, mday, wday, hour, min, sec))
}

pub fn k_skk_current_date(mut env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, &optional (f, Proc) (format, Any) (and_time, Any));
    let date_information = try!(k_skk_current_date_1(&mut env, &knil()));
    let nil = knil();
    let format = format.unwrap_or(&nil);
    let gengo = knil(); //or t
    let and_time = and_time.unwrap_or(&nil);
    match f {
        Some(f) => funcall(env, f, &klist!(date_information, format, gengo, and_time)),
        None => Ok(knil())
    }
}

pub fn k_skk_default_current_date(_: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args,
              (date_information, Any)
              (format, Str)
              (num_type, Int)
              (gengo, Any)//bool
              (gengo_index, Any)
              (month_alist_index, Any)
              (dayofweek_alist_index, Any)
              &optional (and_time, Any) // bool
              );
    Ok(knil())
}

pub fn init(mut env: &mut Env) -> Result<()>{
    env.fregister("skk-calc", kprim("k_skk_calc", k_skk_calc));
    env.fregister("skk-current-date-1", kprim("k_skk_current_date_1", k_skk_current_date_1));
    env.fregister("skk-current-date", kprim("k_skk_current_date", k_skk_current_date));
    Ok(())
}
<commit_msg>work pinning<commit_after>extern crate time;

use std::ops::Deref;

use ::expr::{Expr, Type, Error as E, Result};
use ::eval::funcall;
use ::env::Env;
use ::util::*;
use ::datetime::datetime_info_to_timespec;

pub fn k_skk_calc(env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, (op, Sym));
    let skk_num_list = try!(env.find(&"skk-num-list".to_string())).clone();
    get_args!(&skk_num_list, (x, Int) (y, Int));
    let res = match &op[..] {
        "+" => x + y,
        "-" => x - y,
        "*" => x * y,
        "/" => x / y,
        op => return //Err(format!("unknown operator {}", op))
                       Err(E::User(format!("unknown operator {}", op)))
    };
    Ok(kint(res))
}

pub fn k_skk_current_date_1(_: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, &optional (specified_time, Any));
    // TODO: don't allocate month/wday table every time
    let mvec = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    let wvec = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    let now = specified_time.map_or(Ok(time::now()), |st| datetime_info_to_timespec(st).map(|tm| time::at(tm)));
    let now = try!(now);
    let year = (now.tm_year + 1900).to_string();
    let month = mvec[now.tm_mon as usize];
    let mday = now.tm_mday.to_string();
    let wday = wvec[now.tm_wday as usize];
    let hour = now.tm_hour.to_string();
    let min = now.tm_min.to_string();
    let sec = now.tm_sec.to_string();
    Ok(klist!(year, month, mday, wday, hour, min, sec))
}

pub fn k_skk_current_date(mut env: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args, &optional (f, Proc) (format, Any) (and_time, Any));
    let date_information = try!(k_skk_current_date_1(&mut env, &knil()));
    let nil = knil();
    let format = format.unwrap_or(&nil);
    let gengo = knil(); //or t
    let and_time = and_time.unwrap_or(&nil);
    match f {
        Some(f) => funcall(env, f, &klist!(date_information, format, gengo, and_time)),
        None => Ok(knil())
    }
}

pub fn k_skk_default_current_date(_: &mut Env, args: &Expr) -> Result<Expr> {
    get_args!(args,
              (date_information, Any)
              (format, Nullable Str)
              (num_type, Int)
              (gengo, Bool)
              (gengo_index, Nullable Int)
              (month_alist_index, Nullable Int)
              (dayofweek_alist_index, Nullable Int)
              &optional (and_time, Bool)
              );
    get_args!(date_information, (year, Str) (month, Str) (day, Str) (day_of_week, Str)
              (hour, Str) (minute, Str) (second, Str));
    let res = match and_time {
        None | Some(false) => {
            let format = format.map_or("%s年%s月%s日(%s)", |s| &s);
            kstr(format)
        },
        _ => {
            let format = format.map_or("%s年%s月%s日(%s)%s時%s分%s秒", |s| &s);
            kstr(format)
        }
    };
    Ok(res)
}

pub fn init(mut env: &mut Env) -> Result<()>{
    env.fregister("skk-calc", kprim("k_skk_calc", k_skk_calc));
    env.fregister("skk-current-date-1", kprim("k_skk_current_date_1", k_skk_current_date_1));
    env.fregister("skk-current-date", kprim("k_skk_current_date", k_skk_current_date));
    Ok(())
}
<|endoftext|>