<commit_before>use std::io::{Buffer, Reader, IoError, IoResult, OtherIoError};
use rustc_serialize::Decoder;

pub struct DecoderReader<'a, R: 'a> {
    reader: &'a mut R
}

impl<'a, R: Reader+Buffer> DecoderReader<'a, R> {
    pub fn new(r: &'a mut R) -> DecoderReader<'a, R> {
        DecoderReader {
            reader: r
        }
    }
}

impl<'a, R: Reader+Buffer> Decoder<IoError> for DecoderReader<'a, R> {
    fn read_nil(&mut self) -> IoResult<()> {
        Ok(())
    }
    fn read_uint(&mut self) -> IoResult<uint> {
        self.read_u64().map(|x| x as uint)
    }
    fn read_u64(&mut self) -> IoResult<u64> {
        self.reader.read_be_u64()
    }
    fn read_u32(&mut self) -> IoResult<u32> {
        self.reader.read_be_u32()
    }
    fn read_u16(&mut self) -> IoResult<u16> {
        self.reader.read_be_u16()
    }
    fn read_u8(&mut self) -> IoResult<u8> {
        self.reader.read_u8()
    }
    fn read_int(&mut self) -> IoResult<int> {
        self.read_i64().map(|x| x as int)
    }
    fn read_i64(&mut self) -> IoResult<i64> {
        self.reader.read_be_i64()
    }
    fn read_i32(&mut self) -> IoResult<i32> {
        self.reader.read_be_i32()
    }
    fn read_i16(&mut self) -> IoResult<i16> {
        self.reader.read_be_i16()
    }
    fn read_i8(&mut self) -> IoResult<i8> {
        self.reader.read_i8()
    }
    fn read_bool(&mut self) -> IoResult<bool> {
        match try!(self.reader.read_i8()) {
            1 => Ok(true),
            _ => Ok(false)
        }
    }
    fn read_f64(&mut self) -> IoResult<f64> {
        self.reader.read_be_f64()
    }
    fn read_f32(&mut self) -> IoResult<f32> {
        self.reader.read_be_f32()
    }
    fn read_char(&mut self) -> IoResult<char> {
        self.reader.read_char()
    }
    fn read_str(&mut self) -> IoResult<String> {
        let len = try!(self.read_uint());
        let mut vector = Vec::with_capacity(len as uint);
        for _ in range(0, len) {
            vector.push(try!(self.reader.read_u8()));
        }
        Ok(String::from_utf8(vector).unwrap())
    }
    fn read_enum<T, F>(&mut self, _: &str, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_enum_variant<T, F>(&mut self, _: &[&str], mut f: F) -> IoResult<T> where
        F: FnMut(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            let id = try!(self.read_uint());
            f(self, id)
        }
    fn read_enum_variant_arg<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> IoResult<T> where
        F: FnMut(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            self.read_enum_variant(names, f)
        }
    fn read_enum_struct_variant_field<T, F>(&mut self,
                                            _: &str,
                                            f_idx: uint,
                                            f: F)
        -> IoResult<T> where
            F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
                self.read_enum_variant_arg(f_idx, f)
            }
    fn read_struct<T, F>(&mut self, _: &str, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_struct_field<T, F>(&mut self,
                               _: &str,
                               _: uint,
                               f: F)
        -> IoResult<T> where
            F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
                f(self)
            }
    fn read_tuple<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_tuple_arg<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_tuple_struct<T, F>(&mut self, _: &str, len: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            self.read_tuple(len, f)
        }
    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            self.read_tuple_arg(a_idx, f)
        }
    fn read_option<T, F>(&mut self, mut f: F) -> IoResult<T> where
        F: FnMut(&mut DecoderReader<'a, R>, bool) -> IoResult<T> {
            match try!(self.reader.read_u8()) {
                1 => f(self, true),
                _ => f(self, false)
            }
        }
    fn read_seq<T, F>(&mut self, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            let len = try!(self.read_uint());
            f(self, len)
        }
    fn read_seq_elt<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_map<T, F>(&mut self, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            let len = try!(self.read_uint());
            f(self, len)
        }
    fn read_map_elt_key<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_map_elt_val<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn error(&mut self, err: &str) -> IoError {
        IoError {
            kind: OtherIoError,
            desc: "failure decoding or something, I don't know",
            detail: Some(err.to_string())
        }
    }
}
<commit_msg>Perform sanity check when reading enum variant.<commit_after>use std::io::{Buffer, Reader, IoError, IoResult, OtherIoError};
use rustc_serialize::Decoder;

pub struct DecoderReader<'a, R: 'a> {
    reader: &'a mut R
}

impl<'a, R: Reader+Buffer> DecoderReader<'a, R> {
    pub fn new(r: &'a mut R) -> DecoderReader<'a, R> {
        DecoderReader {
            reader: r
        }
    }
}

impl<'a, R: Reader+Buffer> Decoder<IoError> for DecoderReader<'a, R> {
    fn read_nil(&mut self) -> IoResult<()> {
        Ok(())
    }
    fn read_uint(&mut self) -> IoResult<uint> {
        self.read_u64().map(|x| x as uint)
    }
    fn read_u64(&mut self) -> IoResult<u64> {
        self.reader.read_be_u64()
    }
    fn read_u32(&mut self) -> IoResult<u32> {
        self.reader.read_be_u32()
    }
    fn read_u16(&mut self) -> IoResult<u16> {
        self.reader.read_be_u16()
    }
    fn read_u8(&mut self) -> IoResult<u8> {
        self.reader.read_u8()
    }
    fn read_int(&mut self) -> IoResult<int> {
        self.read_i64().map(|x| x as int)
    }
    fn read_i64(&mut self) -> IoResult<i64> {
        self.reader.read_be_i64()
    }
    fn read_i32(&mut self) -> IoResult<i32> {
        self.reader.read_be_i32()
    }
    fn read_i16(&mut self) -> IoResult<i16> {
        self.reader.read_be_i16()
    }
    fn read_i8(&mut self) -> IoResult<i8> {
        self.reader.read_i8()
    }
    fn read_bool(&mut self) -> IoResult<bool> {
        match try!(self.reader.read_i8()) {
            1 => Ok(true),
            _ => Ok(false)
        }
    }
    fn read_f64(&mut self) -> IoResult<f64> {
        self.reader.read_be_f64()
    }
    fn read_f32(&mut self) -> IoResult<f32> {
        self.reader.read_be_f32()
    }
    fn read_char(&mut self) -> IoResult<char> {
        self.reader.read_char()
    }
    fn read_str(&mut self) -> IoResult<String> {
        let len = try!(self.read_uint());
        let mut vector = Vec::with_capacity(len as uint);
        for _ in range(0, len) {
            vector.push(try!(self.reader.read_u8()));
        }
        Ok(String::from_utf8(vector).unwrap())
    }
    fn read_enum<T, F>(&mut self, _: &str, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F) -> IoResult<T> where
        F: FnMut(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            let id = try!(self.read_uint());
            if id >= names.len() {
                Err(IoError {
                    kind: OtherIoError,
                    desc: "out of bounds tag when reading enum variant",
                    detail: Some(format!("Expected tag < {}, got {}", names.len(), id))
                })
            } else {
                f(self, id)
            }
        }
    fn read_enum_variant_arg<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> IoResult<T> where
        F: FnMut(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            self.read_enum_variant(names, f)
        }
    fn read_enum_struct_variant_field<T, F>(&mut self,
                                            _: &str,
                                            f_idx: uint,
                                            f: F)
        -> IoResult<T> where
            F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
                self.read_enum_variant_arg(f_idx, f)
            }
    fn read_struct<T, F>(&mut self, _: &str, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_struct_field<T, F>(&mut self,
                               _: &str,
                               _: uint,
                               f: F)
        -> IoResult<T> where
            F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
                f(self)
            }
    fn read_tuple<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_tuple_arg<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_tuple_struct<T, F>(&mut self, _: &str, len: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            self.read_tuple(len, f)
        }
    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            self.read_tuple_arg(a_idx, f)
        }
    fn read_option<T, F>(&mut self, mut f: F) -> IoResult<T> where
        F: FnMut(&mut DecoderReader<'a, R>, bool) -> IoResult<T> {
            match try!(self.reader.read_u8()) {
                1 => f(self, true),
                _ => f(self, false)
            }
        }
    fn read_seq<T, F>(&mut self, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            let len = try!(self.read_uint());
            f(self, len)
        }
    fn read_seq_elt<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_map<T, F>(&mut self, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>, uint) -> IoResult<T> {
            let len = try!(self.read_uint());
            f(self, len)
        }
    fn read_map_elt_key<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn read_map_elt_val<T, F>(&mut self, _: uint, f: F) -> IoResult<T> where
        F: FnOnce(&mut DecoderReader<'a, R>) -> IoResult<T> {
            f(self)
        }
    fn error(&mut self, err: &str) -> IoError {
        IoError {
            kind: OtherIoError,
            desc: "failure decoding or something, I don't know",
            detail: Some(err.to_string())
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::fmt;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;
use iron::modifiers::Redirect;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    // The routers, specialized by method.
    routers: HashMap<method::Method, Recognizer<Box<Handler>>>,
    // Routes that accept any method.
    wildcard: Recognizer<Box<Handler>>
}

impl Router {
    /// Construct a new, empty `Router`.
    ///
    /// ```
    /// # use router::Router;
    /// let router = Router::new();
    /// ```
    pub fn new() -> Router {
        Router {
            routers: HashMap::new(),
            wildcard: Recognizer::new()
        }
    }

    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// let mut router = Router::new();
    /// router.route(method::Get, "/users/:userid/:friendid", controller);
    /// ```
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<H, S>(&mut self, method: method::Method,
                       glob: S, handler: H) -> &mut Router
    where H: Handler, S: AsRef<str> {
        self.routers.entry(method).or_insert(Recognizer::new())
                    .add(glob.as_ref(), Box::new(handler));
        self
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Get, glob, handler)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Post, glob, handler)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Put, glob, handler)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Delete, glob, handler)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Head, glob, handler)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Patch, glob, handler)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Options, glob, handler)
    }

    /// Route will match any method, including gibberish.
    /// In case of ambiguity, handlers specific to methods will be preferred.
    pub fn any<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.wildcard.add(glob.as_ref(), Box::new(handler));
        self
    }

    fn recognize(&self, method: &method::Method, path: &str)
                     -> Option<Match<&Box<Handler>>> {
        self.routers.get(method).and_then(|router| router.recognize(path).ok())
            .or(self.wildcard.recognize(path).ok())
    }

    fn handle_options(&self, path: &str) -> Response {
        static METHODS: &'static [method::Method] =
            &[method::Get, method::Post, method::Post, method::Put,
              method::Delete, method::Head, method::Patch];

        // Get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            self.routers.get(method).map(|router| {
                if let Some(_) = router.recognize(path).ok() {
                    options.push(method.clone());
                }
            });
        }
        // If GET is there, HEAD is also there.
        if options.contains(&method::Get) && !options.contains(&method::Head) {
            options.push(method::Head);
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        res
    }

    // Tests for a match by adding or removing a trailing slash.
    fn redirect_slash(&self, req : &Request) -> Option<IronError> {
        let mut url = req.url.clone();
        let mut path = url.path.join("/");

        if let Some(last_char) = path.chars().last() {
            if last_char == '/' {
                path.pop();
                url.path.pop();
            } else {
                path.push('/');
                url.path.push(String::new());
            }
        }

        self.recognize(&req.method, &path).and(
            Some(IronError::new(TrailingSlash,
                                (status::MovedPermanently, Redirect(url))))
        )
    }

    fn handle_method(&self, req: &mut Request, path: &str) -> Option<IronResult<Response>> {
        if let Some(matched) = self.recognize(&req.method, path) {
            req.extensions.insert::<Router>(matched.params);
            Some(matched.handler.handle(req))
        } else { self.redirect_slash(req).and_then(|redirect| Some(Err(redirect))) }
    }
}

impl Key for Router { type Value = Params; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path.join("/");

        self.handle_method(req, &path).unwrap_or_else(||
            match req.method {
                method::Options => Ok(self.handle_options(&path)),
                // For HEAD, fall back to GET. Hyper ensures no response body is written.
                method::Head => {
                    req.method = method::Get;
                    self.handle_method(req, &path).unwrap_or(
                        Err(IronError::new(NoRoute, status::NotFound))
                    )
                }
                _ => Err(IronError::new(NoRoute, status::NotFound))
            }
        )
    }
}

/// The error thrown by router if there is no matching route,
/// it is always accompanied by a NotFound response.
#[derive(Debug)]
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

/// The error thrown by router if a request was redirected
/// by adding or removing a trailing slash.
#[derive(Debug)]
pub struct TrailingSlash;

impl fmt::Display for TrailingSlash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("The request had a trailing slash.")
    }
}

impl Error for TrailingSlash {
    fn description(&self) -> &str { "Trailing Slash" }
}
<commit_msg>(feat) Deriving PartialEq and Eq for routing errors.<commit_after>use std::collections::HashMap;
use std::error::Error;
use std::fmt;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;
use iron::modifiers::Redirect;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    // The routers, specialized by method.
    routers: HashMap<method::Method, Recognizer<Box<Handler>>>,
    // Routes that accept any method.
    wildcard: Recognizer<Box<Handler>>
}

impl Router {
    /// Construct a new, empty `Router`.
    ///
    /// ```
    /// # use router::Router;
    /// let router = Router::new();
    /// ```
    pub fn new() -> Router {
        Router {
            routers: HashMap::new(),
            wildcard: Recognizer::new()
        }
    }

    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// let mut router = Router::new();
    /// router.route(method::Get, "/users/:userid/:friendid", controller);
    /// ```
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<H, S>(&mut self, method: method::Method,
                       glob: S, handler: H) -> &mut Router
    where H: Handler, S: AsRef<str> {
        self.routers.entry(method).or_insert(Recognizer::new())
                    .add(glob.as_ref(), Box::new(handler));
        self
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Get, glob, handler)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Post, glob, handler)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Put, glob, handler)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Delete, glob, handler)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Head, glob, handler)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Patch, glob, handler)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.route(method::Options, glob, handler)
    }

    /// Route will match any method, including gibberish.
    /// In case of ambiguity, handlers specific to methods will be preferred.
    pub fn any<H: Handler, S: AsRef<str>>(&mut self, glob: S, handler: H) -> &mut Router {
        self.wildcard.add(glob.as_ref(), Box::new(handler));
        self
    }

    fn recognize(&self, method: &method::Method, path: &str)
                     -> Option<Match<&Box<Handler>>> {
        self.routers.get(method).and_then(|router| router.recognize(path).ok())
            .or(self.wildcard.recognize(path).ok())
    }

    fn handle_options(&self, path: &str) -> Response {
        static METHODS: &'static [method::Method] =
            &[method::Get, method::Post, method::Post, method::Put,
              method::Delete, method::Head, method::Patch];

        // Get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            self.routers.get(method).map(|router| {
                if let Some(_) = router.recognize(path).ok() {
                    options.push(method.clone());
                }
            });
        }
        // If GET is there, HEAD is also there.
        if options.contains(&method::Get) && !options.contains(&method::Head) {
            options.push(method::Head);
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        res
    }

    // Tests for a match by adding or removing a trailing slash.
    fn redirect_slash(&self, req : &Request) -> Option<IronError> {
        let mut url = req.url.clone();
        let mut path = url.path.join("/");

        if let Some(last_char) = path.chars().last() {
            if last_char == '/' {
                path.pop();
                url.path.pop();
            } else {
                path.push('/');
                url.path.push(String::new());
            }
        }

        self.recognize(&req.method, &path).and(
            Some(IronError::new(TrailingSlash,
                                (status::MovedPermanently, Redirect(url))))
        )
    }

    fn handle_method(&self, req: &mut Request, path: &str) -> Option<IronResult<Response>> {
        if let Some(matched) = self.recognize(&req.method, path) {
            req.extensions.insert::<Router>(matched.params);
            Some(matched.handler.handle(req))
        } else { self.redirect_slash(req).and_then(|redirect| Some(Err(redirect))) }
    }
}

impl Key for Router { type Value = Params; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path.join("/");

        self.handle_method(req, &path).unwrap_or_else(||
            match req.method {
                method::Options => Ok(self.handle_options(&path)),
                // For HEAD, fall back to GET. Hyper ensures no response body is written.
                method::Head => {
                    req.method = method::Get;
                    self.handle_method(req, &path).unwrap_or(
                        Err(IronError::new(NoRoute, status::NotFound))
                    )
                }
                _ => Err(IronError::new(NoRoute, status::NotFound))
            }
        )
    }
}

/// The error thrown by router if there is no matching route,
/// it is always accompanied by a NotFound response.
#[derive(Debug, PartialEq, Eq)]
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

/// The error thrown by router if a request was redirected
/// by adding or removing a trailing slash.
#[derive(Debug, PartialEq, Eq)]
pub struct TrailingSlash;

impl fmt::Display for TrailingSlash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("The request had a trailing slash.")
    }
}

impl Error for TrailingSlash {
    fn description(&self) -> &str { "Trailing Slash" }
}
<|endoftext|>


<commit_before>#!/usr/bin/env rustx

fn main () {
   io::println("Hello!");
}

fn test () {
   assert 2 + 2 == 4;
}

<commit_msg>add `use std` to fix the test syntax<commit_after>#!/usr/bin/env rustx

use std;

fn main () {
   io::println("Hello!");
}

#[test]
fn test () {
   assert 2 + 2 == 4;
}

<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate curl;
extern crate rs_es;
extern crate serde;
extern crate serde_json;
extern crate regex;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

use super::objects::{Addr, Incr, DocType};

// Rubber is an wrapper around elasticsearch API
pub struct Rubber {
    index_name: String,
    client: rs_es::Client,
}

impl Rubber {
    // build a rubber with a connection string (http://host:port/index)
    pub fn new(cnx: &str) -> Rubber {
        let re = regex::Regex::new(r"(?P<host>.+?):(?P<port>\d{4})/(?P<index>\w+)").unwrap();
        let cap = re.captures(cnx).unwrap();
        let host = cap.name("host").unwrap();
        let port = cap.name("port").unwrap().parse::<u32>().unwrap();
        let index = cap.name("index").unwrap();
        info!("elastic search host {:?} port {:?} index {:?}",
              host,
              port,
              index);

        Rubber {
            index_name: index.to_string(),
            client: rs_es::Client::new(&host, port),
        }
    }

    pub fn create_index(&mut self) -> Result<(), rs_es::error::EsError> {
        debug!("creating index");
        match self.client.delete_index(&self.index_name) {
            Err(e) => info!("unable to remove index, {}", e),
            _ => (),
        }
        // first, we must delete with its own handle the old munin

        // Note: for the moment I don't see an easy way to do this with rs_es
        let analysis = include_str!("../json/settings.json");
        // assert!(analysis.parse::<json::Json>().is_ok());
        let res = curl::http::handle().put("http://localhost:9200/munin", analysis).exec().unwrap();

        assert!(res.get_code() == 200, "Error adding analysis: {}", res);

        Ok(())
    }

    pub fn bulk_index<T, I>(&mut self, mut iter: I) -> Result<u32, rs_es::error::EsError>
        where T: serde::Serialize + DocType,
              I: Iterator<Item = T>
    {
        use self::rs_es::operations::bulk::Action;
        let mut chunk = Vec::new();
        let mut nb = 0;

        loop {
            chunk.clear();
            let addr = match iter.next() {
                Some(a) => a,
                None => break,
            };
            chunk.push(Action::index(addr));

            nb += 1;
            for addr in iter.by_ref().take(1000) {
                chunk.push(Action::index(addr));
                nb += 1;
            }
            try!(self.client
                     .bulk(&chunk)
                     .with_index(&self.index_name)
                     .with_doc_type(T::doc_type())
                     .send());
        }

        Ok(nb)
    }

    pub fn index<I: Iterator<Item = Addr>>(&mut self,
                                           iter: I)
                                           -> Result<u32, rs_es::error::EsError> {
        let mut admins = HashMap::new();
        let mut streets = HashMap::new();
        let mut nb = 0;

        nb += try!(self.bulk_index(iter.inspect(|addr| {
            upsert(&addr.street.administrative_region, &mut admins);
            upsert(&addr.street, &mut streets);
        })));
        nb += try!(self.bulk_index(admins.values()));
        nb += try!(self.bulk_index(streets.values()));
        Ok(nb)
    }
}

fn upsert<T: Incr>(elt: &T, map: &mut HashMap<String, T>) {
    match map.entry(elt.id().to_string()) {
        Vacant(e) => {
            e.insert(elt.clone());
        }
        Occupied(mut e) => e.get_mut().incr(),
    }
}
<commit_msg>corrections after reviewdo not pu http:// in es client<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program 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
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate curl;
extern crate rs_es;
extern crate serde;
extern crate serde_json;
extern crate regex;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

use super::objects::{Addr, Incr, DocType};

// Rubber is an wrapper around elasticsearch API
pub struct Rubber {
    index_name: String,
    client: rs_es::Client,
    cnx_string: String, // full cnx string since curl is still used
}

impl Rubber {
    // build a rubber with a connection string (http://host:port/index)
    pub fn new(cnx: &str) -> Rubber {
        let re = regex::Regex::new(r"(?:https?://)?(?P<host>.+?):(?P<port>\d+)/(?P<index>\w+)").unwrap();
        let cap = re.captures(cnx).unwrap();
        let host = cap.name("host").unwrap();
        let port = cap.name("port").unwrap().parse::<u32>().unwrap();
        let index = cap.name("index").unwrap();
        info!("elastic search host {:?} port {:?} index {:?}",
              host,
              port,
              index);

        Rubber {
            index_name: index.to_string(),
            client: rs_es::Client::new(&host, port),
            cnx_string: cnx.to_string()
        }
    }

    pub fn create_index(&mut self) -> Result<(), rs_es::error::EsError> {
        debug!("creating index");
        match self.client.delete_index(&self.index_name) {
            Err(e) => info!("unable to remove index, {}", e),
            _ => (),
        }
        // first, we must delete with its own handle the old munin

        // Note: for the moment I don't see an easy way to do this with rs_es
        let analysis = include_str!("../json/settings.json");
        // assert!(analysis.parse::<json::Json>().is_ok());
        let res = curl::http::handle().put(self.cnx_string.as_str(), analysis).exec().unwrap();

        assert!(res.get_code() == 200, "Error adding analysis: {}", res);

        Ok(())
    }

    pub fn bulk_index<T, I>(&mut self, mut iter: I) -> Result<u32, rs_es::error::EsError>
        where T: serde::Serialize + DocType,
              I: Iterator<Item = T>
    {
        use self::rs_es::operations::bulk::Action;
        let mut chunk = Vec::new();
        let mut nb = 0;

        loop {
            chunk.clear();
            let addr = match iter.next() {
                Some(a) => a,
                None => break,
            };
            chunk.push(Action::index(addr));

            nb += 1;
            for addr in iter.by_ref().take(1000) {
                chunk.push(Action::index(addr));
                nb += 1;
            }
            try!(self.client
                     .bulk(&chunk)
                     .with_index(&self.index_name)
                     .with_doc_type(T::doc_type())
                     .send());
        }

        Ok(nb)
    }

    pub fn index<I: Iterator<Item = Addr>>(&mut self,
                                           iter: I)
                                           -> Result<u32, rs_es::error::EsError> {
        let mut admins = HashMap::new();
        let mut streets = HashMap::new();
        let mut nb = 0;

        nb += try!(self.bulk_index(iter.inspect(|addr| {
            upsert(&addr.street.administrative_region, &mut admins);
            upsert(&addr.street, &mut streets);
        })));
        nb += try!(self.bulk_index(admins.values()));
        nb += try!(self.bulk_index(streets.values()));
        Ok(nb)
    }
}

fn upsert<T: Incr>(elt: &T, map: &mut HashMap<String, T>) {
    match map.entry(elt.id().to_string()) {
        Vacant(e) => {
            e.insert(elt.clone());
        }
        Occupied(mut e) => e.get_mut().incr(),
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::io::{Error, ErrorKind};
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::{mem, thread};
use std::net::{TcpStream, TcpListener};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};
use std::collections::LinkedList;

use libc;
use errno::errno;
use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use libc::{c_int, c_void};
use config::Config;
use openssl::ssl::{SslStream, SslContext};

use stats;
use types::*;
use resources::ResourcePool;
use ss::nonblocking::plain::Plain;
use ss::nonblocking::secure::Secure;
use ss::{Socket, Stream, SRecv, SSend, TcpOptions, SocketOptions};

// We need to be able to access our resource pool from several methods
static mut pool: *mut ResourcePool = 0 as *mut ResourcePool;

// Global SslContext
static mut ssl_context: *mut SslContext = 0 as *mut SslContext;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLET  - Fd is in EdgeTriggered mode (notification on state changes)
// EPOLLIN  - Data is available in kerndl buffer
const EVENTS: u32 = event_type::EPOLLET | event_type::EPOLLIN;

/// Starts the epoll wait and incoming connection listener threads.
pub fn begin(config: Config, handler: Box<EventHandler>) {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Stream>::new()));

    // Resource pool
    let mut rp = ResourcePool::new(config.workers);
    unsafe {
        pool = &mut rp;
    }

    // Wrap our event handler into something that can be safely shared
    // between threads.
    let e_handler = Handler(Box::into_raw(handler));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    let streams2 = sockets.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            event_loop(epfd2, streams2, e_handler);
        })
        .unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let streams3 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
           listen(config, epfd3, streams3);
        })
        .unwrap();

    // Stay alive forever, or at least we hope
    let _ = prox.join();
}

/// Incoming connection listening thread
fn listen(config: Config, epfd: RawFd, streams: StreamList) {
    // Setup server and listening port
    let listener_result = try_setup_tcp_listener(&config);
    if listener_result.is_err() {
        error!("Setting up server: {}", listener_result.unwrap_err());
        return;
    }

    // If we're using SSL, setup our context reference
    if config.ssl.is_some() {
        setup_ssl_context(&config);
    }

    // Begin listening for new connections
    let listener = listener_result.unwrap();
    for accept_result in listener.incoming() {
        match accept_result {
            Ok(tcp_stream) => handle_new_connection(tcp_stream, &config, epfd, streams.clone()),
            Err(e) => error!("Accepting connection: {}", e)
        }
    }

    drop(listener);
}

fn try_setup_tcp_listener(config: &Config) -> Result<TcpListener, Error> {
    let create_result = TcpListener::bind((&config.addr[..], config.port));
    if create_result.is_err() {
        return create_result;
    }

    let listener = create_result.unwrap();
    let server_fd = listener.as_raw_fd();

    // Set the SO_REUSEADDR so that restarts after crashes do not take 5min to unbind
    // the initial port
    unsafe {
        let optval: c_int = 1;
        let opt_result = libc::setsockopt(server_fd,
                                          libc::SOL_SOCKET,
                                          libc::SO_REUSEADDR,
                                          &optval as *const _ as *const c_void,
                                          mem::size_of::<c_int>() as u32);
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }
    }

    Ok(listener)
}

fn setup_ssl_context(config: &Config) {
    unsafe {
        ssl_context = Box::into_raw(Box::new(config.ssl.clone().unwrap()));
    }
}

fn handle_new_connection(tcp_stream: TcpStream, config: &Config, epfd: RawFd, streams: StreamList) {
    // Update our total opened file descriptors
    stats::fd_opened();

    // Create and configure a new socket
    let mut socket = Socket::new(tcp_stream.into_raw_fd());
    let result = setup_new_socket(&mut socket);
    if result.is_err() {
        close_fd(socket.as_raw_fd());
        return;
    }

    // Setup our stream
    let stream = match config.ssl {
        Some(_) => {
            let ssl_result = unsafe { SslStream::accept(&(*ssl_context), socket) };
            match ssl_result {
                Ok(ssl_stream) => {
                    let secure_stream = Secure::new(ssl_stream);
                    Stream::new(Box::new(secure_stream))
                }
                Err(ssl_error) => {
                    error!("Creating SslStream: {}", ssl_error);
                    return;
                }
            }
        }
        None => {
            let plain_text = Plain::new(socket);
            Stream::new(Box::new(plain_text))
        }
    };

    // Add stream to our server
    let fd = stream.as_raw_fd();
    add_stream_to_master_list(stream, streams.clone());
    add_to_epoll(epfd, fd, streams.clone());
}

fn setup_new_socket(socket: &mut Socket) -> Result<(), ()> {
    let result = socket.set_nonblocking();
    if result.is_err() {
        error!("Setting fd to nonblocking: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_nodelay(true);
    if result.is_err() {
        error!("Setting tcp_nodelay: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_keepalive(true);
    if result.is_err() {
        error!("Setting tcp_keepalive: {}", result.unwrap_err());
        return Err(());
    }

    Ok(())
}

/// Event loop for handling all epoll events
fn event_loop(epfd: RawFd, streams: StreamList, handler: Handler) {
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe {
        events.set_len(100);
    }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    handle_epoll_event(epfd, &events[x], streams.clone(), handler.clone());
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        };
    }
}

/// Finds the stream the epoll event is associated with and parses the event type
/// to hand off to specific handlers
fn handle_epoll_event(epfd: RawFd, event: &EpollEvent, streams: StreamList, handler: Handler) {
    const READ_EVENT: u32 = event_type::EPOLLIN;

    // Locate the stream the event was for
    let mut stream;
    {
        // Mutex lock
        // Find the stream the event was for
        let mut guard = match streams.lock() {
            Ok(guard) => guard,
            Err(poisoned) => {
                warn!("StreamList Mutex was poisoned, using anyway");
                poisoned.into_inner()
            }
        };
        let list = guard.deref_mut();

        let mut found = false;
        let mut index = 1usize;
        for s in list.iter() {
            if s.as_raw_fd() == event.data as RawFd {
                found = true;
                break;
            }
            index += 1;
        }

        if !found {
            error!("Could not find fd in stream list? Removing from epoll and closing fd");

            let fd = event.data as RawFd;
            remove_fd_from_epoll(epfd, fd);
            close_fd(fd);
            return;
        }

        if index == 1 {
            stream = list.pop_front().unwrap();
        } else {
            let mut split = list.split_off(index - 1);
            stream = split.pop_front().unwrap();
            list.append(&mut split);
        }
    } // Mutex unlock

    if (event.events & READ_EVENT) > 0 {
        trace!("event was read event");
        let _ = handle_read_event(epfd, &mut stream, handler).map(|_| {
            add_stream_to_master_list(stream, streams.clone());
        });
    } else {
        trace!("event was drop event");

        let fd = stream.as_raw_fd();
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        let stream_fd = stream.as_raw_fd();
        unsafe {
            (*pool).run(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(stream_fd);
            });
        }
    }
}

/// Reads all available data on the stream.
///
/// If a complete message(s) is available, each message will be routed through the
/// resource pool.
///
/// If an error occurs during the read, the stream is dropped from the server.
fn handle_read_event(epfd: RawFd, stream: &mut Stream, handler: Handler) -> Result<(), ()> {
    trace!("handle read event");

    match stream.recv() {
        Ok(_) => {
            let mut rx_queue = stream.drain_rx_queue();
            for payload in rx_queue.iter_mut() {
                // Check if this is a request for stats
                if payload.len() == 6 && payload[0] == 0x04 && payload[1] == 0x04 {
                    let u8ptr: *const u8 = &payload[2] as *const _;
                    let f32ptr: *const f32 = u8ptr as *const _;
                    let sec = unsafe { *f32ptr };
                    let stream_cpy = stream.clone();
                    unsafe {
                        (*pool).run(move || {
                            let mut s = stream_cpy.clone();
                            let result = stats::as_serialized_buffer(sec);
                            if result.is_ok() {
                                let _ = s.send(&result.unwrap()[..]);
                            }
                        });
                    }
                    return Ok(());
                }

                // TODO - Refactor once better function passing traits are available in stable.
                let handler_cpy = handler.clone();
                let stream_cpy = stream.clone();
                let payload_cpy = payload.clone();
                unsafe {
                    (*pool).run(move || {
                        let Handler(ptr) = handler_cpy;
                        (*ptr).on_data_received(stream_cpy.clone(), payload_cpy.clone());
                    });
                }
            }
            Ok(())
        }
        Err(e) => {
            if e.kind() == ErrorKind::WouldBlock {
                return Ok(());
            }

            error!("stream.fd: {} during read: {}", stream.as_raw_fd(), e);

            remove_fd_from_epoll(epfd, stream.as_raw_fd());
            close_fd(stream.as_raw_fd());

            let stream_fd = stream.as_raw_fd();
            unsafe {
                (*pool).run(move || {
                    let Handler(ptr) = handler;
                    (*ptr).on_stream_closed(stream_fd.clone());
                });
            }

            Err(())
        }
    }
}

/// Inserts the stream back into the master list of streams
fn add_stream_to_master_list(stream: Stream, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("StreamList Mutex failed, using anyway...");
            poisoned.into_inner()
        }
    };
    let stream_list = guard.deref_mut();
    stream_list.push_back(stream);
    stats::conn_recv();
}

/// Adds a new fd to the epoll instance
fn add_to_epoll(epfd: RawFd, fd: RawFd, streams: StreamList) {
    let result = epoll::ctl(epfd,
                            ctl_op::ADD,
                            fd,
                            &mut EpollEvent {
                                data: fd as u64,
                                events: EVENTS,
                            });

    if result.is_ok() {
        trace!("New fd added to epoll");
    } else {
        let e = result.unwrap_err();
        error!("CtrlError during add: {}", e);
        remove_fd_from_list(fd, streams.clone());
        close_fd(fd);
    }
}

/// Removes a fd from the epoll instance
fn remove_fd_from_epoll(epfd: RawFd, fd: RawFd) {
    debug!("removing fd from epoll");

    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL. We'll be as backwards compatible as possible.
    let _ = epoll::ctl(epfd,
                       ctl_op::DEL,
                       fd,
                       &mut EpollEvent {
                           data: 0 as u64,
                           events: 0 as u32,
                       })
                .map_err(|e| warn!("Epoll CtrlError during del: {}", e));
}

/// Removes stream with id from master list
fn remove_fd_from_list(fd: RawFd, streams: StreamList) {
    trace!("removing fd: {} from master list", fd);

    let mut guard = match streams.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("StreamList Mutex was poisoned, using anyway");
            poisoned.into_inner()
        }
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 1usize;
    for s in list.iter() {
        if s.as_raw_fd() == fd {
            found = true;
            break;
        }
        index += 1;
    }

    if !found {
        trace!("fd: {} not found in list", fd);
        return;
    }

    if index == 1 {
        list.pop_front();
    } else {
        let mut split = list.split_off(index - 1);
        split.pop_front();
        list.append(&mut split);
    }

    stats::conn_lost();
}

/// Closes a fd with the kernel
fn close_fd(fd: RawFd) {
    unsafe {
        let result = libc::close(fd);
        if result < 0 {
            error!("Error closing fd: {}",
                   Error::from_raw_os_error(result as i32));
            return;
        }
    }
    stats::fd_closed();
}
<commit_msg>Removed excess logs<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

use std::io::{Error, ErrorKind};
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::{mem, thread};
use std::net::{TcpStream, TcpListener};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};
use std::collections::LinkedList;

use libc;
use errno::errno;
use epoll;
use epoll::util::*;
use epoll::EpollEvent;
use libc::{c_int, c_void};
use config::Config;
use openssl::ssl::{SslStream, SslContext};

use stats;
use types::*;
use resources::ResourcePool;
use ss::nonblocking::plain::Plain;
use ss::nonblocking::secure::Secure;
use ss::{Socket, Stream, SRecv, SSend, TcpOptions, SocketOptions};

// We need to be able to access our resource pool from several methods
static mut pool: *mut ResourcePool = 0 as *mut ResourcePool;

// Global SslContext
static mut ssl_context: *mut SslContext = 0 as *mut SslContext;

// When added to epoll, these will be the conditions of kernel notification:
//
// EPOLLET  - Fd is in EdgeTriggered mode (notification on state changes)
// EPOLLIN  - Data is available in kerndl buffer
const EVENTS: u32 = event_type::EPOLLET | event_type::EPOLLIN;

/// Starts the epoll wait and incoming connection listener threads.
pub fn begin(config: Config, handler: Box<EventHandler>) {
    // Master socket list
    let sockets = Arc::new(Mutex::new(LinkedList::<Stream>::new()));

    // Resource pool
    let mut rp = ResourcePool::new(config.workers);
    unsafe {
        pool = &mut rp;
    }

    // Wrap our event handler into something that can be safely shared
    // between threads.
    let e_handler = Handler(Box::into_raw(handler));

    // Epoll instance
    let result = epoll::create1(0);
    if result.is_err() {
        let err = result.unwrap_err();
        error!("Unable to create epoll instance: {}", err);
        panic!()
    }
    let epfd = result.unwrap();

    // Epoll wait thread
    let epfd2 = epfd.clone();
    let streams2 = sockets.clone();
    thread::Builder::new()
        .name("Epoll Wait".to_string())
        .spawn(move || {
            event_loop(epfd2, streams2, e_handler);
        })
        .unwrap();

    // New connection thread
    let epfd3 = epfd.clone();
    let streams3 = sockets.clone();
    let prox = thread::Builder::new()
        .name("TCP Incoming Listener".to_string())
        .spawn(move || {
           listen(config, epfd3, streams3);
        })
        .unwrap();

    // Stay alive forever, or at least we hope
    let _ = prox.join();
}

/// Incoming connection listening thread
fn listen(config: Config, epfd: RawFd, streams: StreamList) {
    // Setup server and listening port
    let listener_result = try_setup_tcp_listener(&config);
    if listener_result.is_err() {
        error!("Setting up server: {}", listener_result.unwrap_err());
        return;
    }

    // If we're using SSL, setup our context reference
    if config.ssl.is_some() {
        setup_ssl_context(&config);
    }

    // Begin listening for new connections
    let listener = listener_result.unwrap();
    for accept_result in listener.incoming() {
        match accept_result {
            Ok(tcp_stream) => handle_new_connection(tcp_stream, &config, epfd, streams.clone()),
            Err(e) => error!("Accepting connection: {}", e)
        }
    }

    drop(listener);
}

fn try_setup_tcp_listener(config: &Config) -> Result<TcpListener, Error> {
    let create_result = TcpListener::bind((&config.addr[..], config.port));
    if create_result.is_err() {
        return create_result;
    }

    let listener = create_result.unwrap();
    let server_fd = listener.as_raw_fd();

    // Set the SO_REUSEADDR so that restarts after crashes do not take 5min to unbind
    // the initial port
    unsafe {
        let optval: c_int = 1;
        let opt_result = libc::setsockopt(server_fd,
                                          libc::SOL_SOCKET,
                                          libc::SO_REUSEADDR,
                                          &optval as *const _ as *const c_void,
                                          mem::size_of::<c_int>() as u32);
        if opt_result < 0 {
            return Err(Error::from_raw_os_error(errno().0 as i32));
        }
    }

    Ok(listener)
}

fn setup_ssl_context(config: &Config) {
    unsafe {
        ssl_context = Box::into_raw(Box::new(config.ssl.clone().unwrap()));
    }
}

fn handle_new_connection(tcp_stream: TcpStream, config: &Config, epfd: RawFd, streams: StreamList) {
    // Update our total opened file descriptors
    stats::fd_opened();

    // Create and configure a new socket
    let mut socket = Socket::new(tcp_stream.into_raw_fd());
    let result = setup_new_socket(&mut socket);
    if result.is_err() {
        close_fd(socket.as_raw_fd());
        return;
    }

    // Setup our stream
    let stream = match config.ssl {
        Some(_) => {
            let sock_fd = socket.as_raw_fd();
            let ssl_result = unsafe { SslStream::accept(&(*ssl_context), socket) };
            match ssl_result {
                Ok(ssl_stream) => {
                    let secure_stream = Secure::new(ssl_stream);
                    Stream::new(Box::new(secure_stream))
                }
                Err(ssl_error) => {
                    error!("Creating SslStream: {}", ssl_error);
                    close_fd(sock_fd);
                    return;
                }
            }
        }
        None => {
            let plain_text = Plain::new(socket);
            Stream::new(Box::new(plain_text))
        }
    };

    // Add stream to our server
    let fd = stream.as_raw_fd();
    add_stream_to_master_list(stream, streams.clone());
    add_to_epoll(epfd, fd, streams.clone());
}

fn setup_new_socket(socket: &mut Socket) -> Result<(), ()> {
    let result = socket.set_nonblocking();
    if result.is_err() {
        error!("Setting fd to nonblocking: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_nodelay(true);
    if result.is_err() {
        error!("Setting tcp_nodelay: {}", result.unwrap_err());
        return Err(());
    }

    let result = socket.set_tcp_keepalive(true);
    if result.is_err() {
        error!("Setting tcp_keepalive: {}", result.unwrap_err());
        return Err(());
    }

    Ok(())
}

/// Event loop for handling all epoll events
fn event_loop(epfd: RawFd, streams: StreamList, handler: Handler) {
    let mut events = Vec::<EpollEvent>::with_capacity(100);
    unsafe {
        events.set_len(100);
    }

    loop {
        match epoll::wait(epfd, &mut events[..], -1) {
            Ok(num_events) => {
                for x in 0..num_events as usize {
                    handle_epoll_event(epfd, &events[x], streams.clone(), handler.clone());
                }
            }
            Err(e) => {
                error!("Error on epoll::wait(): {}", e);
                panic!()
            }
        };
    }
}

/// Finds the stream the epoll event is associated with and parses the event type
/// to hand off to specific handlers
fn handle_epoll_event(epfd: RawFd, event: &EpollEvent, streams: StreamList, handler: Handler) {
    const READ_EVENT: u32 = event_type::EPOLLIN;

    // Locate the stream the event was for
    let mut stream;
    {
        // Mutex lock
        // Find the stream the event was for
        let mut guard = match streams.lock() {
            Ok(guard) => guard,
            Err(poisoned) => {
                warn!("StreamList Mutex was poisoned, using anyway");
                poisoned.into_inner()
            }
        };
        let list = guard.deref_mut();

        let mut found = false;
        let mut index = 1usize;
        for s in list.iter() {
            if s.as_raw_fd() == event.data as RawFd {
                found = true;
                break;
            }
            index += 1;
        }

        if !found {
            let fd = event.data as RawFd;
            remove_fd_from_epoll(epfd, fd);
            close_fd(fd);
            return;
        }

        if index == 1 {
            stream = list.pop_front().unwrap();
        } else {
            let mut split = list.split_off(index - 1);
            stream = split.pop_front().unwrap();
            list.append(&mut split);
        }
    } // Mutex unlock

    if (event.events & READ_EVENT) > 0 {
        let _ = handle_read_event(epfd, &mut stream, handler).map(|_| {
            add_stream_to_master_list(stream, streams.clone());
        });
    } else {
        let fd = stream.as_raw_fd();
        remove_fd_from_epoll(epfd, fd);
        close_fd(fd);

        let stream_fd = stream.as_raw_fd();
        unsafe {
            (*pool).run(move || {
                let Handler(ptr) = handler;
                (*ptr).on_stream_closed(stream_fd);
            });
        }
    }
}

/// Reads all available data on the stream.
///
/// If a complete message(s) is available, each message will be routed through the
/// resource pool.
///
/// If an error occurs during the read, the stream is dropped from the server.
fn handle_read_event(epfd: RawFd, stream: &mut Stream, handler: Handler) -> Result<(), ()> {
    match stream.recv() {
        Ok(_) => {
            let mut rx_queue = stream.drain_rx_queue();
            for payload in rx_queue.iter_mut() {
                // Check if this is a request for stats
                if payload.len() == 6 && payload[0] == 0x04 && payload[1] == 0x04 {
                    let u8ptr: *const u8 = &payload[2] as *const _;
                    let f32ptr: *const f32 = u8ptr as *const _;
                    let sec = unsafe { *f32ptr };
                    let stream_cpy = stream.clone();
                    unsafe {
                        (*pool).run(move || {
                            let mut s = stream_cpy.clone();
                            let result = stats::as_serialized_buffer(sec);
                            if result.is_ok() {
                                let _ = s.send(&result.unwrap()[..]);
                            }
                        });
                    }
                    return Ok(());
                }

                // TODO - Refactor once better function passing traits are available in stable.
                let handler_cpy = handler.clone();
                let stream_cpy = stream.clone();
                let payload_cpy = payload.clone();
                unsafe {
                    (*pool).run(move || {
                        let Handler(ptr) = handler_cpy;
                        (*ptr).on_data_received(stream_cpy.clone(), payload_cpy.clone());
                    });
                }
            }
            Ok(())
        }
        Err(e) => {
            remove_fd_from_epoll(epfd, stream.as_raw_fd());
            close_fd(stream.as_raw_fd());

            let stream_fd = stream.as_raw_fd();
            unsafe {
                (*pool).run(move || {
                    let Handler(ptr) = handler;
                    (*ptr).on_stream_closed(stream_fd.clone());
                });
            }

            Err(())
        }
    }
}

/// Inserts the stream back into the master list of streams
fn add_stream_to_master_list(stream: Stream, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("StreamList Mutex failed, using anyway...");
            poisoned.into_inner()
        }
    };
    let stream_list = guard.deref_mut();
    stream_list.push_back(stream);
    stats::conn_recv();
}

/// Adds a new fd to the epoll instance
fn add_to_epoll(epfd: RawFd, fd: RawFd, streams: StreamList) {
    let result = epoll::ctl(epfd,
                            ctl_op::ADD,
                            fd,
                            &mut EpollEvent {
                                data: fd as u64,
                                events: EVENTS,
                            });

    if result.is_err() {
        let e = result.unwrap_err();
        error!("poll::CtrlError during add: {}", e);
        remove_fd_from_list(fd, streams.clone());
        close_fd(fd);
    }
}

/// Removes a fd from the epoll instance
fn remove_fd_from_epoll(epfd: RawFd, fd: RawFd) {
    // In kernel versions before 2.6.9, the EPOLL_CTL_DEL operation required
    // a non-null pointer in event, even though this argument is ignored.
    // Since Linux 2.6.9, event can be specified as NULL when using
    // EPOLL_CTL_DEL. We'll be as backwards compatible as possible.
    let _ = epoll::ctl(epfd,
                       ctl_op::DEL,
                       fd,
                       &mut EpollEvent {
                           data: 0 as u64,
                           events: 0 as u32,
                       })
                .map_err(|e| warn!("Epoll CtrlError during del: {}", e));
}

/// Removes stream with fd from master list
fn remove_fd_from_list(fd: RawFd, streams: StreamList) {
    let mut guard = match streams.lock() {
        Ok(guard) => guard,
        Err(poisoned) => {
            warn!("StreamList Mutex was poisoned, using anyway");
            poisoned.into_inner()
        }
    };
    let list = guard.deref_mut();

    let mut found = false;
    let mut index = 1usize;
    for s in list.iter() {
        if s.as_raw_fd() == fd {
            found = true;
            break;
        }
        index += 1;
    }

    if !found {
        trace!("fd: {} not found in list", fd);
        return;
    }

    if index == 1 {
        list.pop_front();
    } else {
        let mut split = list.split_off(index - 1);
        split.pop_front();
        list.append(&mut split);
    }

    stats::conn_lost();
}

/// Closes a fd with the kernel
fn close_fd(fd: RawFd) {
    unsafe {
        let result = libc::close(fd);
        if result < 0 {
            error!("Error closing fd: {}",
                   Error::from_raw_os_error(result as i32));
            return;
        }
    }
    stats::fd_closed();
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2017 Ivo Wetzel

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// STD Dependencies -----------------------------------------------------------
use std::io::{Error, ErrorKind};
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::mpsc::TryRecvError;
use std::collections::{HashMap, VecDeque};

// Internal Dependencies ------------------------------------------------------
use shared::stats::{Stats, StatsCollector};
use shared::ticker::Ticker;
use super::{
    Config,
    ConnectionID, Connection, ConnectionEvent,
    RateLimiter, PacketModifier, Socket
};

/// Enum of server network events.
#[derive(Debug, PartialEq)]
pub enum ServerEvent {

    /// Event emitted once a new client connection has been established.
    Connection(ConnectionID),

    /// Event emitted when a existing client connection is lost.
    ConnectionLost(ConnectionID),

    /// Event emitted when a client connection is closed programmatically.
    ConnectionClosed(ConnectionID, bool),

    /// Event emitted for each message received from a client connection.
    Message(ConnectionID, Vec<u8>),

    /// Event emitted each time a client's connection congestion state changes.
    ConnectionCongestionStateChanged(ConnectionID, bool),

    /// Event emitted each time a client connection packet is lost.
    PacketLost(ConnectionID, Vec<u8>)

}

/// Implementation of a multi-client low latency socket server.
///
/// # Basic Usage
///
/// ```
/// use cobalt::{
///     BinaryRateLimiter, Server, Config, NoopPacketModifier, MessageKind, UdpSocket
/// };
///
/// // Create a new server that communicates over a udp socket
/// let mut server = Server::<UdpSocket, BinaryRateLimiter, NoopPacketModifier>::new(Config::default());
///
/// // Make the server listen on port `1234` on all interfaces.
/// server.listen("0.0.0.0:1234").expect("Failed to bind to socket.");
///
/// // loop {
///
///     // Accept incoming connections and fetch their events
///     while let Ok(event) = server.accept_receive() {
///         // Handle events (e.g. Connection, Messages, etc.)
///     }
///
///     // Send a message to all connected clients
///     for (_, conn) in server.connections() {
///         conn.send(MessageKind::Instant, b"Ping".to_vec());
///     }
///
///     // Send all outgoing messages.
///     //
///     // Also auto delay the current thread to achieve the configured tick rate.
///     server.send(true);
///
/// // }
///
/// // Shutdown the server (freeing its socket and closing all its connections)
/// server.shutdown();
/// ```
///
#[derive(Debug)]
pub struct Server<S: Socket, R: RateLimiter, M: PacketModifier> {
    config: Config,
    socket: Option<S>,
    connections: HashMap<ConnectionID, Connection<R, M>>,
    addresses: HashMap<ConnectionID, SocketAddr>,
    ticker: Ticker,
    local_address: Option<SocketAddr>,
    events: VecDeque<ServerEvent>,
    should_receive: bool,
    stats_collector: StatsCollector,
    stats: Stats
}

impl<S: Socket, R: RateLimiter, M: PacketModifier> Server<S, R, M> {

    /// Creates a new server with the given configuration.
    pub fn new(config: Config) -> Server<S, R, M> {
        Server {
            config: config,
            socket: None,
            connections: HashMap::new(),
            addresses: HashMap::new(),
            ticker: Ticker::new(config),
            local_address: None,
            events: VecDeque::new(),
            should_receive: false,
            stats_collector: StatsCollector::new(config),
            stats: Stats {
                bytes_sent: 0,
                bytes_received: 0
            }
        }
    }

    /// Returns the number of bytes sent over the last second.
    pub fn bytes_sent(&self) -> u32 {
        self.stats.bytes_sent
    }

    /// Returns the number of bytes received over the last second.
    pub fn bytes_received(&self) -> u32 {
        self.stats.bytes_received
    }

    /// Returns the local address that the client is sending from.
    pub fn local_addr(&self) -> Result<SocketAddr, Error> {
        self.local_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, ""))
    }

    /// Returns a mutable reference to the specified client connection.
    pub fn connection(&mut self, id: &ConnectionID) -> Result<&mut Connection<R, M>, Error> {
        if self.socket.is_some() {
            if let Some(conn) = self.connections.get_mut(id) {
                Ok(conn)

            } else {
                Err(Error::new(ErrorKind::NotFound, ""))
            }

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    /// Returns a mutable reference to the servers client connections.
    pub fn connections(&mut self) -> &mut HashMap<ConnectionID, Connection<R, M>> {
        &mut self.connections
    }

    /// Returns a mutable reference to the server's underlying socket.
    pub fn socket(&mut self) -> Result<&mut S, Error> {
        if let Some(socket) = self.socket.as_mut() {
            Ok(socket)

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    /// Returns the server's current configuration.
    pub fn config(&self) -> Config {
        self.config
    }

    /// Overrides the server's current configuration.
    pub fn set_config(&mut self, config: Config) {

        self.config = config;
        self.ticker.set_config(config);
        self.stats_collector.set_config(config);

        for (_, conn) in &mut self.connections {
            conn.set_config(config);
        }

    }

    /// Binds the server to listen the specified address.
    pub fn listen<A: ToSocketAddrs>(&mut self, addr: A) -> Result<(), Error> {

        if self.socket.is_none() {

            let local_addr = try!(addr.to_socket_addrs()).nth(0).unwrap();
            let socket = try!(S::new(
                local_addr,
                self.config.packet_max_size
            ));

            self.socket = Some(socket);
            self.local_address = Some(local_addr);
            self.should_receive = true;

            Ok(())

        } else {
            Err(Error::new(ErrorKind::AlreadyExists, ""))
        }

    }

    /// Accepts new incoming client connections from the server's underlying
    /// server and receives and returns messages from them.
    pub fn accept_receive(&mut self) -> Result<ServerEvent, TryRecvError> {

        if self.socket.is_none() {
            Err(TryRecvError::Disconnected)

        } else {

            if self.should_receive {

                self.ticker.begin_tick();

                let local_address = self.local_address.unwrap();

                // Receive all incoming UDP packets to our local address
                let mut bytes_received = 0;
                while let Ok((addr, packet)) = self.socket.as_mut().unwrap().try_recv() {

                    // Try to extract the connection id from the packet
                    if let Some(id) = Connection::<R, M>::id_from_packet(&self.config, &packet) {

                        // Update server statistics
                        bytes_received += packet.len();

                        // Get existing connection
                        let connection = if self.connections.contains_key(&id) {

                            let connection = self.connections.get_mut(&id).unwrap();

                            // Check if the packet was actually handled
                            if connection.receive_packet(packet) {

                                // Map the current remote address of the connection to
                                // the latest address that sent a packet for the
                                // connection id in question. This is done in order to
                                // work in situations were the remote port of a
                                // connection is switched around by NAT.
                                if addr != connection.peer_addr() {
                                    connection.set_peer_addr(addr);
                                    self.addresses.remove(&id);
                                    self.addresses.insert(id, addr);
                                }

                            }

                            connection

                        // Or insert new one
                        } else {

                            let mut conn = Connection::new(
                                self.config,
                                local_address,
                                addr,
                                R::new(self.config),
                                M::new(self.config)
                            );

                            conn.set_id(id);

                            self.connections.insert(id, conn);
                            self.addresses.insert(id, addr);

                            // Receive first packet
                            let connection = self.connections.get_mut(&id).unwrap();
                            connection.receive_packet(packet);

                            connection

                        };

                        // Map any connection events
                        map_connection_events(&mut self.events, connection);

                    }

                }

                self.stats_collector.set_bytes_received(bytes_received as u32);
                self.should_receive = false;

            }

            if let Some(event) = self.events.pop_front() {
                Ok(event)

            } else {
                Err(TryRecvError::Empty)
            }

        }

    }

    /// Sends all queued messages to the server's underlying client connections.
    ///
    /// If `auto_tick` is specified as `true` this method will block the
    /// current thread for the amount of time which is required to limit the
    /// number of calls per second (when called inside a loop) to the server's
    /// configured `send_rate`.
    pub fn send(&mut self, auto_tick: bool) -> Result<(), Error> {
        if self.socket.is_some() {

            // List of dropped connections
            let mut dropped: Vec<ConnectionID> = Vec::new();

            // Create outgoing packets for all connections
            let mut bytes_sent = 0;
            for (id, connection) in &mut self.connections {

                // Resolve the last known remote address for this
                // connection and send the data
                let addr = &self.addresses[id];

                // Then invoke the connection to send a outgoing packet
                bytes_sent += connection.send_packet(
                    self.socket.as_mut().unwrap(),
                    addr
                );

                // Collect all lost / closed connections
                if !connection.open() {
                    // Map any remaining connection events
                    map_connection_events(&mut self.events, connection);
                    dropped.push(*id);
                }

            }

            // Remove any dropped connections and their address mappings
            for id in dropped {
                self.connections.remove(&id).unwrap().reset();
                self.addresses.remove(&id);
            }

            self.stats_collector.set_bytes_sent(bytes_sent);
            self.stats_collector.tick();
            self.stats = self.stats_collector.average();

            self.should_receive = true;

            if auto_tick {
                self.ticker.end_tick();
            }

            Ok(())

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    /// Shuts down all of the server's client connections, clearing any state
    /// and freeing the server's socket.
    pub fn shutdown(&mut self) -> Result<(), Error> {
        if self.socket.is_some() {
            self.should_receive = false;
            self.stats_collector.reset();
            self.stats.reset();
            self.events.clear();
            self.connections.clear();
            self.addresses.clear();
            self.ticker.reset();
            self.local_address = None;
            self.socket = None;
            Ok(())

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

}

// Helpers --------------------------------------------------------------------
fn map_connection_events<R: RateLimiter, M: PacketModifier>(
    server_events: &mut VecDeque<ServerEvent>,
    connection: &mut Connection<R, M>
) {
    let id = connection.id();
    for event in connection.events() {
        server_events.push_back(match event {
            ConnectionEvent::Connected => ServerEvent::Connection(id),
            ConnectionEvent::Lost => ServerEvent::ConnectionLost(id),
            ConnectionEvent::FailedToConnect => unreachable!(),
            ConnectionEvent::Closed(p) => ServerEvent::ConnectionClosed(id, p),
            ConnectionEvent::Message(payload) => ServerEvent::Message(id, payload),
            ConnectionEvent::CongestionStateChanged(c) => ServerEvent::ConnectionCongestionStateChanged(id, c),
            ConnectionEvent::PacketLost(payload) => ServerEvent::PacketLost(id, payload)
        })
    }
}

<commit_msg>[REFACTOR] Split up server connection/packet handling code.<commit_after>// Copyright (c) 2015-2017 Ivo Wetzel

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// STD Dependencies -----------------------------------------------------------
use std::io::{Error, ErrorKind};
use std::net::{SocketAddr, ToSocketAddrs};
use std::sync::mpsc::TryRecvError;
use std::collections::{HashMap, VecDeque};

// Internal Dependencies ------------------------------------------------------
use shared::stats::{Stats, StatsCollector};
use shared::ticker::Ticker;
use super::{
    Config,
    ConnectionID, Connection, ConnectionEvent,
    RateLimiter, PacketModifier, Socket
};

/// Enum of server network events.
#[derive(Debug, PartialEq)]
pub enum ServerEvent {

    /// Event emitted once a new client connection has been established.
    Connection(ConnectionID),

    /// Event emitted when a existing client connection is lost.
    ConnectionLost(ConnectionID),

    /// Event emitted when a client connection is closed programmatically.
    ConnectionClosed(ConnectionID, bool),

    /// Event emitted for each message received from a client connection.
    Message(ConnectionID, Vec<u8>),

    /// Event emitted each time a client's connection congestion state changes.
    ConnectionCongestionStateChanged(ConnectionID, bool),

    /// Event emitted each time a client connection packet is lost.
    PacketLost(ConnectionID, Vec<u8>)

}

/// Implementation of a multi-client low latency socket server.
///
/// # Basic Usage
///
/// ```
/// use cobalt::{
///     BinaryRateLimiter, Server, Config, NoopPacketModifier, MessageKind, UdpSocket
/// };
///
/// // Create a new server that communicates over a udp socket
/// let mut server = Server::<UdpSocket, BinaryRateLimiter, NoopPacketModifier>::new(Config::default());
///
/// // Make the server listen on port `1234` on all interfaces.
/// server.listen("0.0.0.0:1234").expect("Failed to bind to socket.");
///
/// // loop {
///
///     // Accept incoming connections and fetch their events
///     while let Ok(event) = server.accept_receive() {
///         // Handle events (e.g. Connection, Messages, etc.)
///     }
///
///     // Send a message to all connected clients
///     for (_, conn) in server.connections() {
///         conn.send(MessageKind::Instant, b"Ping".to_vec());
///     }
///
///     // Send all outgoing messages.
///     //
///     // Also auto delay the current thread to achieve the configured tick rate.
///     server.send(true);
///
/// // }
///
/// // Shutdown the server (freeing its socket and closing all its connections)
/// server.shutdown();
/// ```
///
#[derive(Debug)]
pub struct Server<S: Socket, R: RateLimiter, M: PacketModifier> {
    config: Config,
    socket: Option<S>,
    connections: HashMap<ConnectionID, Connection<R, M>>,
    addresses: HashMap<ConnectionID, SocketAddr>,
    ticker: Ticker,
    local_address: Option<SocketAddr>,
    events: VecDeque<ServerEvent>,
    should_receive: bool,
    stats_collector: StatsCollector,
    stats: Stats
}

impl<S: Socket, R: RateLimiter, M: PacketModifier> Server<S, R, M> {

    /// Creates a new server with the given configuration.
    pub fn new(config: Config) -> Server<S, R, M> {
        Server {
            config: config,
            socket: None,
            connections: HashMap::new(),
            addresses: HashMap::new(),
            ticker: Ticker::new(config),
            local_address: None,
            events: VecDeque::new(),
            should_receive: false,
            stats_collector: StatsCollector::new(config),
            stats: Stats {
                bytes_sent: 0,
                bytes_received: 0
            }
        }
    }

    /// Returns the number of bytes sent over the last second.
    pub fn bytes_sent(&self) -> u32 {
        self.stats.bytes_sent
    }

    /// Returns the number of bytes received over the last second.
    pub fn bytes_received(&self) -> u32 {
        self.stats.bytes_received
    }

    /// Returns the local address that the client is sending from.
    pub fn local_addr(&self) -> Result<SocketAddr, Error> {
        self.local_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, ""))
    }

    /// Returns a mutable reference to the specified client connection.
    pub fn connection(&mut self, id: &ConnectionID) -> Result<&mut Connection<R, M>, Error> {
        if self.socket.is_some() {
            if let Some(conn) = self.connections.get_mut(id) {
                Ok(conn)

            } else {
                Err(Error::new(ErrorKind::NotFound, ""))
            }

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    /// Returns a mutable reference to the servers client connections.
    pub fn connections(&mut self) -> &mut HashMap<ConnectionID, Connection<R, M>> {
        &mut self.connections
    }

    /// Returns a mutable reference to the server's underlying socket.
    pub fn socket(&mut self) -> Result<&mut S, Error> {
        if let Some(socket) = self.socket.as_mut() {
            Ok(socket)

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    /// Returns the server's current configuration.
    pub fn config(&self) -> Config {
        self.config
    }

    /// Overrides the server's current configuration.
    pub fn set_config(&mut self, config: Config) {

        self.config = config;
        self.ticker.set_config(config);
        self.stats_collector.set_config(config);

        for (_, conn) in &mut self.connections {
            conn.set_config(config);
        }

    }

    /// Binds the server to listen the specified address.
    pub fn listen<A: ToSocketAddrs>(&mut self, addr: A) -> Result<(), Error> {

        if self.socket.is_none() {

            let local_addr = try!(addr.to_socket_addrs()).nth(0).unwrap();
            let socket = try!(S::new(
                local_addr,
                self.config.packet_max_size
            ));

            self.socket = Some(socket);
            self.local_address = Some(local_addr);
            self.should_receive = true;

            Ok(())

        } else {
            Err(Error::new(ErrorKind::AlreadyExists, ""))
        }

    }

    /// Accepts new incoming client connections from the server's underlying
    /// server and receives and returns messages from them.
    pub fn accept_receive(&mut self) -> Result<ServerEvent, TryRecvError> {

        if self.socket.is_none() {
            Err(TryRecvError::Disconnected)

        } else {

            if self.should_receive {

                self.ticker.begin_tick();

                // Receive all incoming UDP packets to our local address
                let mut bytes_received = 0;
                while let Ok((addr, packet)) = self.socket.as_mut().unwrap().try_recv() {

                    // Try to extract the connection id from the packet
                    if let Some(id) = Connection::<R, M>::id_from_packet(&self.config, &packet) {
                        bytes_received += self.receive_connection_packet(id, addr, packet);
                    }

                }

                self.stats_collector.set_bytes_received(bytes_received as u32);
                self.should_receive = false;

            }

            if let Some(event) = self.events.pop_front() {
                Ok(event)

            } else {
                Err(TryRecvError::Empty)
            }

        }

    }

    /// Sends all queued messages to the server's underlying client connections.
    ///
    /// If `auto_tick` is specified as `true` this method will block the
    /// current thread for the amount of time which is required to limit the
    /// number of calls per second (when called inside a loop) to the server's
    /// configured `send_rate`.
    pub fn send(&mut self, auto_tick: bool) -> Result<(), Error> {
        if self.socket.is_some() {

            // List of dropped connections
            let mut dropped: Vec<ConnectionID> = Vec::new();

            // Create outgoing packets for all connections
            let mut bytes_sent = 0;
            for (id, connection) in &mut self.connections {

                // Resolve the last known remote address for this
                // connection and send the data
                let addr = &self.addresses[id];

                // Then invoke the connection to send a outgoing packet
                bytes_sent += connection.send_packet(
                    self.socket.as_mut().unwrap(),
                    addr
                );

                // Collect all lost / closed connections
                if !connection.open() {
                    // Map any remaining connection events
                    map_connection_events(&mut self.events, connection);
                    dropped.push(*id);
                }

            }

            // Remove any dropped connections and their address mappings
            for id in dropped {
                self.connections.remove(&id).unwrap().reset();
                self.addresses.remove(&id);
            }

            self.stats_collector.set_bytes_sent(bytes_sent);
            self.stats_collector.tick();
            self.stats = self.stats_collector.average();

            self.should_receive = true;

            if auto_tick {
                self.ticker.end_tick();
            }

            Ok(())

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    /// Shuts down all of the server's client connections, clearing any state
    /// and freeing the server's socket.
    pub fn shutdown(&mut self) -> Result<(), Error> {
        if self.socket.is_some() {
            self.should_receive = false;
            self.stats_collector.reset();
            self.stats.reset();
            self.events.clear();
            self.connections.clear();
            self.addresses.clear();
            self.ticker.reset();
            self.local_address = None;
            self.socket = None;
            Ok(())

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    // Internal ---------------------------------------------------------------
    fn receive_connection_packet(
        &mut self,
        id: ConnectionID,
        addr: SocketAddr,
        packet: Vec<u8>

    ) -> usize {

        let packet_length = packet.len();

        // Get existing connection
        if self.connections.contains_key(&id) {

            let connection = self.connections.get_mut(&id).unwrap();

            // Check if the packet was actually handled
            if connection.receive_packet(packet) {

                // Map the current remote address of the connection to
                // the latest address that sent a packet for the
                // connection id in question. This is done in order to
                // work in situations were the remote port of a
                // connection is switched around by NAT.
                if addr != connection.peer_addr() {
                    connection.set_peer_addr(addr);
                    self.addresses.remove(&id);
                    self.addresses.insert(id, addr);
                }

            }

            // Map any connection events
            map_connection_events(&mut self.events, connection);

            packet_length

        // Or insert new one
        } else {

            let mut conn = Connection::new(
                self.config,
                self.local_address.unwrap(),
                addr,
                R::new(self.config),
                M::new(self.config)
            );

            conn.set_id(id);

            self.connections.insert(id, conn);
            self.addresses.insert(id, addr);

            // Receive first packet
            let connection = self.connections.get_mut(&id).unwrap();

            if connection.receive_packet(packet) {

                // Map any connection events
                map_connection_events(&mut self.events, connection);

            }

            packet_length

        }

    }

}

// Helpers --------------------------------------------------------------------
fn map_connection_events<R: RateLimiter, M: PacketModifier>(
    server_events: &mut VecDeque<ServerEvent>,
    connection: &mut Connection<R, M>
) {
    let id = connection.id();
    for event in connection.events() {
        server_events.push_back(match event {
            ConnectionEvent::Connected => ServerEvent::Connection(id),
            ConnectionEvent::Lost => ServerEvent::ConnectionLost(id),
            ConnectionEvent::FailedToConnect => unreachable!(),
            ConnectionEvent::Closed(p) => ServerEvent::ConnectionClosed(id, p),
            ConnectionEvent::Message(payload) => ServerEvent::Message(id, payload),
            ConnectionEvent::CongestionStateChanged(c) => ServerEvent::ConnectionCongestionStateChanged(id, c),
            ConnectionEvent::PacketLost(payload) => ServerEvent::PacketLost(id, payload)
        })
    }
}

<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    pub fn exec(&mut self, Inst(n, cmd): Inst) {
        use super::Mode::*;
        use super::PrimitiveMode::*;
        use super::CommandMode::*;
        match self.cursor().mode {
            Command(Normal) => match cmd {
                'i' => {
                    self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                        InsertOptions {
                            mode: InsertMode::Insert,
                        }));

                },
                'h' => self.left(n as usize),
                'j' => self.down(n as usize),
                'k' => self.up(n as usize),
                'l' => self.right(n as usize),
                'x' => self.delete(),
                ' ' => self.next(),
                _ => {},
            },
            Primitive(Insert(_)) => {
                self.insert(cmd);
            },
        }
    }
}
<commit_msg>Add $ and 0 commands<commit_after>use super::*;
use redox::*;

impl Editor {
    pub fn exec(&mut self, Inst(n, cmd): Inst) {
        use super::Mode::*;
        use super::PrimitiveMode::*;
        use super::CommandMode::*;
        match self.cursor().mode {
            Command(Normal) => match cmd {
                'i' => {
                    self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                        InsertOptions {
                            mode: InsertMode::Insert,
                        }));

                },
                'h' => self.left(n as usize),
                'j' => self.down(n as usize),
                'k' => self.up(n as usize),
                'l' => self.right(n as usize),
                'J' => self.down(15),
                'K' => self.up(15),
                'x' => self.delete(),
                'X' => {
                    self.previous();
                    self.delete();
                },
                '$' => self.cursor_mut().x = self.text[self.y()].len(),
                '0' => self.cursor_mut().x = 0,
                ' ' => self.next(),
                _ => {},
            },
            Primitive(Insert(_)) => {
                self.insert(cmd);
            },
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015, The Rust-gnome Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or
// <http://opensource.org/licenses/MIT>

use libc::c_void;

use ffi::{self, Gboolean, gpointer, GCallback};
use translate::{ToGlib, ToGlibPtr};

/// Whether to propagate the signal to other handlers
pub struct Propagate(pub bool);

impl ToGlib for Propagate {
    type GlibType = Gboolean;

    #[inline]
    fn to_glib(&self) -> Gboolean {
        self.0.to_glib()
    }
}

pub unsafe fn connect(receiver: gpointer, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn()>) -> u64 {
    let handle = ffi::g_signal_connect_data(receiver, signal_name.borrow_to_glib().0,
        trampoline, closure as gpointer, destroy_closure, 0) as u64;
    assert!(handle > 0);
    handle
}

extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut c_void) {
    unsafe {
        let ptr = ptr as *mut Box<Fn()>;
        // destroy
        Box::from_raw(ptr);
    }
}
<commit_msg>signals: Remove struct Propagate<commit_after>// Copyright 2015, The Rust-gnome Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or
// <http://opensource.org/licenses/MIT>

use libc::c_void;

use ffi::{self, gpointer, GCallback};
use translate::ToGlibPtr;

pub unsafe fn connect(receiver: gpointer, signal_name: &str, trampoline: GCallback,
                      closure: *mut Box<Fn()>) -> u64 {
    let handle = ffi::g_signal_connect_data(receiver, signal_name.borrow_to_glib().0,
        trampoline, closure as gpointer, destroy_closure, 0) as u64;
    assert!(handle > 0);
    handle
}

extern "C" fn destroy_closure(ptr: *mut c_void, _: *mut c_void) {
    unsafe {
        let ptr = ptr as *mut Box<Fn()>;
        // destroy
        Box::from_raw(ptr);
    }
}
<|endoftext|>