<commit_before>//! This library provide a way to evaluate [`Reverse Polish Notated`] expressions for
//! numbers and basic evaluators.
//!
//! [`Floats`] and [`signed integers`] has already been implemented with basic evaluators
//! (cf. `+`, `-`, `*`, `/`, `neg`, `pow`...).
//!
//! Of course you can build your own Evaluators by implementing the [`Evaluate`] Trait,
//! the only constraint is the compatibility with the [`Operand`] type,
//! that can be everything you want (cf. `letters`, `Enums`, `chinese symbols`...).
//!
//! # Example
//!
//! ```
//! use ripin::evaluate::{FloatExpr, IntExpr};
//!
//! let str_expr = "3 4 + 2 *"; // (3 + 4) * 2
//! let tokens = str_expr.split_whitespace();
//! let expr = FloatExpr::<f32>::from_iter(tokens).unwrap();
//!
//! assert_eq!(expr.evaluate(), Ok(14.0)); // yup that's a Float evaluation
//!
//! // let's try an Integer evaluation:
//! let tokens = str_expr.split_whitespace();
//! let expr = IntExpr::<i32>::from_iter(tokens).unwrap();
//! assert_eq!(expr.evaluate(), Ok(14));
//! ```
//!
//! [`Reverse Polish Notated`]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
//! [`str`]: https://doc.rust-lang.org/std/str/index.html
//! [`Floats`]: evaluate/enum.FloatEvaluator.html
//! [`signed integers`]: evaluate/enum.IntEvaluator.html
//! [`Evaluate`]: evaluate/trait.Evaluate.html
//! [`Operand`]: expression/enum.Arithm.html

extern crate num;

mod stack;

/// Custom conversion module
pub mod convert_ref;

/// Operation on expressions and `Expression` construction methods.
pub mod expression;

pub mod variable;

/// `Evaluate Trait` and default `Evaluators`.
pub mod evaluate;

pub use stack::Stack;

/// Removes the last two elements from a stack and return them,
/// or `None` if there is not enough element.
pub fn pop_two_operands<T>(stack: &mut Stack<T>) -> Option<(T, T)> {
    if stack.len() >= 2 {
        let (a, b) = (stack.pop().unwrap(), stack.pop().unwrap());
        Some((b, a))
    } else {
        None
    }
}
<commit_msg>meta: Add example of variable expressions usage<commit_after>//! This library provide a way to evaluate [`Reverse Polish Notated`] expressions for
//! numbers and basic evaluators.
//!
//! [`Floats`] and [`signed integers`] has already been implemented with basic evaluators
//! (cf. `+`, `-`, `*`, `/`, `neg`, `pow`...).
//!
//! Of course you can build your own Evaluators by implementing the [`Evaluate`] Trait,
//! the only constraint is the compatibility with the [`Operand`] type,
//! that can be everything you want (cf. `letters`, `Enums`, `chinese symbols`...).
//!
//! # Example
//!
//! ```
//! use ripin::evaluate::{FloatExpr, IntExpr};
//!
//! let str_expr = "3 4 + 2 *"; // (3 + 4) * 2
//! let tokens = str_expr.split_whitespace();
//! let expr = FloatExpr::<f32>::from_iter(tokens).unwrap();
//!
//! assert_eq!(expr.evaluate(), Ok(14.0)); // yup that's a Float evaluation
//!
//! // let's try an Integer evaluation:
//! let tokens = str_expr.split_whitespace();
//! let expr = IntExpr::<i32>::from_iter(tokens).unwrap();
//! assert_eq!(expr.evaluate(), Ok(14));
//!
//! // You need variable expressions ? No problem Ripin can do this !
//! use ripin::evaluate::VariableFloatExpr;
//! use ripin::variable::VarIdx;
//!
//! let variables = vec![3.0, 500.0];
//!
//! let str_expr = "3 4 + 2 * $0 -"; // (3 + 4) * 2 - $0
//! let tokens = str_expr.split_whitespace();
//! let expr = VariableFloatExpr::<f32, VarIdx>::from_iter(tokens).unwrap();
//!
//! assert_eq!(expr.evaluate_with_variables::<usize, _>(variables), Ok(11.0));
//! ```
//!
//! [`Reverse Polish Notated`]: https://en.wikipedia.org/wiki/Reverse_Polish_notation
//! [`str`]: https://doc.rust-lang.org/std/str/index.html
//! [`Floats`]: evaluate/enum.FloatEvaluator.html
//! [`signed integers`]: evaluate/enum.IntEvaluator.html
//! [`Evaluate`]: evaluate/trait.Evaluate.html
//! [`Operand`]: expression/enum.Arithm.html

extern crate num;

mod stack;

/// Custom conversion module
pub mod convert_ref;

/// Operation on expressions and `Expression` construction methods.
pub mod expression;

pub mod variable;

/// `Evaluate Trait` and default `Evaluators`.
pub mod evaluate;

pub use stack::Stack;

/// Removes the last two elements from a stack and return them,
/// or `None` if there is not enough element.
pub fn pop_two_operands<T>(stack: &mut Stack<T>) -> Option<(T, T)> {
    if stack.len() >= 2 {
        let (a, b) = (stack.pop().unwrap(), stack.pop().unwrap());
        Some((b, a))
    } else {
        None
    }
}
<|endoftext|>


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

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
request.respond(response)
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::error::Error;
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::ToSocketAddrs;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,

    /// If `Some`, then the server will use SSL to encode the communications.
    pub ssl: Option<SslConfig>,
}

/// Configuration of the server for SSL.
#[derive(Debug, Clone)]
pub struct SslConfig {
    /// Contains the public certificate to send to clients.
    pub certificate: Vec<u8>,
    /// Contains the ultra-secret private key used to decode communications.
    pub private_key: Vec<u8>,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: None,
        })
    }

    /// Shortcut for an HTTPS server on a specific address.
    #[cfg(feature = "ssl")]
    #[inline]
    pub fn https<A>(addr: A, config: SslConfig)
                    -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: Some(config),
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = match config.ssl {
            #[cfg(feature = "ssl")]
            Some(mut config) => {
                use std::io::Cursor;
                use openssl::ssl;
                use openssl::x509::X509;
                use openssl::crypto::pkey::PKey;
                use openssl::ssl::SSL_VERIFY_PEER;

                let mut ctxt = try!(SslContext::new(ssl::SslMethod::Sslv23));
                try!(ctxt.set_cipher_list("DEFAULT"));
                let certificate = try!(X509::from_pem(&mut Cursor::new(&config.certificate)));
                try!(ctxt.set_certificate(&certificate));
                let private_key = try!(PKey::private_key_from_pem(&mut Cursor::new(&config.private_key)));
                try!(ctxt.set_private_key(&private_key));
                //ctxt.set_verify(SSL_VERIFY_PEER, None);
                try!(ctxt.check_private_key());

                // let's wipe the certificate and private key from memory, because we're
                // better safe than sorry
                for b in &mut config.certificate { *b = 0; }
                for b in &mut config.private_key { *b = 0; }

                Some(ctxt)
            },
            #[cfg(not(feature = "ssl"))]
            Some(_) => return Err("Building a server with SSL requires enabling the `ssl` feature \
                                   in tiny-http".to_owned().into()),
            None => None,
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            loop {
                let new_client = match server.accept() {
                    Ok((sock, _)) => {
                        use util::RefinedTcpStream;

                        let (read_closable, write_closable) = match ssl {
                            None => {
                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(feature = "ssl")]
                            Some(ref ssl) => {
                                // trying to apply SSL over the connection
                                // if an error occurs, we just close the socket and resume listening
                                let sock = match openssl::ssl::SslStream::accept(ssl, sock) {
                                    Ok(s) => s,
                                    Err(_) => continue
                                };

                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(not(feature = "ssl"))]
                            Some(_) => unreachable!(),
                        };

                        Ok(ClientConnection::new(write_closable, read_closable))
                    },
                    Err(e) => Err(e),
                };

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        loop {
            match self.messages.pop() {
                Message::Error(err) => return Err(err),
                Message::NewRequest(rq) => return Ok(rq),
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        loop {
            match self.messages.try_pop() {
                Some(Message::Error(err)) => return Err(err),
                Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
                None => return Ok(None)
            }
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomic::Ordering::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<commit_msg>Specify certificate verification<commit_after>// Copyright 2015 The tiny-http Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::http()`.

The `http()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```no_run
let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```no_run
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();

loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    // ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```no_run
# use std::sync::Arc;
# use std::thread;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
let server = Arc::new(server);
let mut guards = Vec::with_capacity(4);

for _ in (0 .. 4) {
    let server = server.clone();

    let guard = thread::spawn(move || {
        loop {
            let rq = server.recv().unwrap();

            // ...
        }
    });

    guards.push(guard);
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.method()` and `request.url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```no_run
# use std::fs::File;
# use std::path::Path;
let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
```

All that remains to do is call `request.respond()`:

```no_run
# use std::fs::File;
# use std::path::Path;
# let server = tiny_http::Server::http("0.0.0.0:0").unwrap();
# let request = server.recv().unwrap();
# let response = tiny_http::Response::from_file(File::open(&Path::new("image.png")).unwrap());
request.respond(response)
```
*/
#![crate_name = "tiny_http"]
#![crate_type = "lib"]
#![forbid(unsafe_code)]

extern crate ascii;
extern crate chunked_transfer;
extern crate encoding;
extern crate url;
extern crate chrono;

#[cfg(feature = "ssl")]
extern crate openssl;

use std::error::Error;
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::thread;
use std::net;
use std::net::ToSocketAddrs;

use client::ClientConnection;
use util::MessagesQueue;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::{ResponseBox, Response};

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
pub struct Server {
    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // queue for messages received by child threads
    messages: Arc<MessagesQueue<Message>>,

    // result of TcpListener::local_addr()
    listening_addr: net::SocketAddr,
}

enum Message {
    Error(IoError),
    NewRequest(Request),
}

impl From<IoError> for Message {
    fn from(e: IoError) -> Message {
        Message::Error(e)
    }
}

impl From<Request> for Message {
    fn from(rq: Request) -> Message {
        Message::NewRequest(rq)
    }
}

// this trait is to make sure that Server implements Share and Send
#[doc(hidden)]
trait MustBeShareDummy : Sync + Send {}
#[doc(hidden)]
impl MustBeShareDummy for Server {}

pub struct IncomingRequests<'a> {
    server: &'a Server
}

/// Represents the parameters required to create a server.
#[derive(Debug, Clone)]
pub struct ServerConfig<A> where A: ToSocketAddrs {
    /// The addresses to listen to.
    pub addr: A,

    /// If `Some`, then the server will use SSL to encode the communications.
    pub ssl: Option<SslConfig>,
}

/// Configuration of the server for SSL.
#[derive(Debug, Clone)]
pub struct SslConfig {
    /// Contains the public certificate to send to clients.
    pub certificate: Vec<u8>,
    /// Contains the ultra-secret private key used to decode communications.
    pub private_key: Vec<u8>,
}

impl Server {
    /// Shortcut for a simple server on a specific address.
    #[inline]
    pub fn http<A>(addr: A) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: None,
        })
    }

    /// Shortcut for an HTTPS server on a specific address.
    #[cfg(feature = "ssl")]
    #[inline]
    pub fn https<A>(addr: A, config: SslConfig)
                    -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        Server::new(ServerConfig {
            addr: addr,
            ssl: Some(config),
        })
    }

    /// Builds a new server that listens on the specified address.
    pub fn new<A>(config: ServerConfig<A>) -> Result<Server, Box<Error + Send + Sync + 'static>>
        where A: ToSocketAddrs
    {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpListener
        let (server, local_addr) = {
            let listener = try!(net::TcpListener::bind(config.addr));
            let local_addr = try!(listener.local_addr());
            (listener, local_addr)
        };

        // building the SSL capabilities
        #[cfg(feature = "ssl")]
        type SslContext = openssl::ssl::SslContext;
        #[cfg(not(feature = "ssl"))]
        type SslContext = ();
        let ssl: Option<SslContext> = match config.ssl {
            #[cfg(feature = "ssl")]
            Some(mut config) => {
                use std::io::Cursor;
                use openssl::ssl;
                use openssl::x509::X509;
                use openssl::crypto::pkey::PKey;
                use openssl::ssl::SSL_VERIFY_NONE;

                let mut ctxt = try!(SslContext::new(ssl::SslMethod::Sslv23));
                try!(ctxt.set_cipher_list("DEFAULT"));
                let certificate = try!(X509::from_pem(&mut Cursor::new(&config.certificate)));
                try!(ctxt.set_certificate(&certificate));
                let private_key = try!(PKey::private_key_from_pem(&mut Cursor::new(&config.private_key)));
                try!(ctxt.set_private_key(&private_key));
                ctxt.set_verify(SSL_VERIFY_NONE, None);
                try!(ctxt.check_private_key());

                // let's wipe the certificate and private key from memory, because we're
                // better safe than sorry
                for b in &mut config.certificate { *b = 0; }
                for b in &mut config.private_key { *b = 0; }

                Some(ctxt)
            },
            #[cfg(not(feature = "ssl"))]
            Some(_) => return Err("Building a server with SSL requires enabling the `ssl` feature \
                                   in tiny-http".to_owned().into()),
            None => None,
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are pushed in the messages queue
        let messages = MessagesQueue::with_capacity(8);

        let inside_close_trigger = close_trigger.clone();
        let inside_messages = messages.clone();
        thread::spawn(move || {
            // a tasks pool is used to dispatch the connections into threads
            let tasks_pool = util::TaskPool::new();

            loop {
                let new_client = match server.accept() {
                    Ok((sock, _)) => {
                        use util::RefinedTcpStream;

                        let (read_closable, write_closable) = match ssl {
                            None => {
                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(feature = "ssl")]
                            Some(ref ssl) => {
                                // trying to apply SSL over the connection
                                // if an error occurs, we just close the socket and resume listening
                                let sock = match openssl::ssl::SslStream::accept(ssl, sock) {
                                    Ok(s) => s,
                                    Err(_) => continue
                                };

                                RefinedTcpStream::new(sock)
                            },
                            #[cfg(not(feature = "ssl"))]
                            Some(_) => unreachable!(),
                        };

                        Ok(ClientConnection::new(write_closable, read_closable))
                    },
                    Err(e) => Err(e),
                };

                match new_client {
                    Ok(client) => {
                        let messages = inside_messages.clone();
                        let mut client = Some(client);
                        tasks_pool.spawn(Box::new(move || {
                            if let Some(client) = client.take() {
                                for rq in client {
                                    messages.push(rq.into());
                                }
                            }
                        }));
                    },

                    Err(e) => {
                        inside_messages.push(e.into());
                        break;
                    }
                }
            }
        });

        // result
        Ok(Server {
            messages: messages,
            close: close_trigger,
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[inline]
    pub fn incoming_requests(&self) -> IncomingRequests {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[inline]
    pub fn server_addr(&self) -> net::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    pub fn num_connections(&self) -> usize {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    pub fn recv(&self) -> IoResult<Request> {
        loop {
            match self.messages.pop() {
                Message::Error(err) => return Err(err),
                Message::NewRequest(rq) => return Ok(rq),
            }
        }
    }

    /// Same as `recv()` but doesn't block.
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        loop {
            match self.messages.try_pop() {
                Some(Message::Error(err)) => return Err(err),
                Some(Message::NewRequest(rq)) => return Ok(Some(rq)),
                None => return Ok(None)
            }
        }
    }
}

impl<'a> Iterator for IncomingRequests<'a> {
    type Item = Request;
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomic::Ordering::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<|endoftext|>


<commit_before>
#![feature(tuple_indexing)]
#![feature(macro_rules)]
#![feature(concat_idents)]
#![feature(default_type_params)]
#![feature(globs)]
#![deny(warnings)]
#![deny(bad_style)]

extern crate serialize;
extern crate time;

#[cfg(feature = "postgres")]
extern crate postgres;
extern crate uuid;

pub use field::{
    Field,
    NamedField,

    BoolField,
    I8Field,
    I16Field,
    I32Field,
    I64Field,
    F32Field,
    F64Field,
    StringField,
    ByteListField,
    JsonField,
    TimespecField,
};

pub use predicate::{
    Predicate,
    RcPredicate,
    IsPredicate, ToIsPredicate,
    OrPredicate, ToOrPredicate,
    AndPredicate, ToAndPredicate,
    InPredicate, ToInPredicate,
    InRangePredicate, ToInRangePredicate,
    InRangeBounds,
    InequalityPredicate, ToInequalityPredicate,
    Inequality,
    ExcludePredicate, ToExcludePredicate,
    LikePredicate, ToLikePredicate,
    IsNullPredicate, ToIsNullPredicate,
    RawPredicate
};

pub use select_query::{
    Selectable,
    Queryable,
    Orderable,
    SelectQuery,
    RcSelectQuery,
    ToSelectQuery,
    Select,
    NoResult,
    LimitOne,
    LimitTwo,
    LimitMany
};

pub use update_query::{
    UpdateQuery,
    FieldUpdate,
    FieldUpd,
    Updatable,
    ToFieldUpdate,
};

pub use insert_query::{
    InsertQuery,
    Insertable,
};

pub use delete_query::{
    DeleteQuery,
    Deletable,
};

pub use expression::{
    ToExpression,
    ToExprValue,
    BoxedExpression,
    UntypedExpression,
    Expression,
    RcExpression,
    ExprValue,
    RawExpr
};

pub use sql::{SqlContext, ToSql, QueryToSql, FromToSql, ToPredicateValue};
#[cfg(feature = "postgres")] pub use sql::{AsPostgresValue};
pub use from::{TableDef, Table, BoxedTable, RcTable, From, BoxedFrom, RcFrom};

pub use function::{
    Sum, SumArg,
    Min, MinArg,
    Max, MaxArg,
    Avg, AvgArg,
    Count, CountArg,
    CountAll
};

pub use placeholder::{
    Placeholder
};

macro_rules! with_clone(
    ($slf: ident, $v:ident, $ex:expr) => ({
        let mut $v = $slf.clone();
        $ex;
        $v
    })
)

mod field;
mod predicate;
mod select_query;
mod insert_query;

#[macro_escape]
mod delete_query;
mod update_query;
pub mod sql;
mod expression;
mod order_by;
mod from;
mod join;
mod distinct;
mod group_by;
mod function;
mod placeholder;

<commit_msg>refactor: remove unused feature gate<commit_after>
#![feature(macro_rules)]
#![feature(concat_idents)]
#![feature(default_type_params)]
#![feature(globs)]
#![deny(warnings)]
#![deny(bad_style)]

extern crate serialize;
extern crate time;

#[cfg(feature = "postgres")]
extern crate postgres;
extern crate uuid;

pub use field::{
    Field,
    NamedField,

    BoolField,
    I8Field,
    I16Field,
    I32Field,
    I64Field,
    F32Field,
    F64Field,
    StringField,
    ByteListField,
    JsonField,
    TimespecField,
};

pub use predicate::{
    Predicate,
    RcPredicate,
    IsPredicate, ToIsPredicate,
    OrPredicate, ToOrPredicate,
    AndPredicate, ToAndPredicate,
    InPredicate, ToInPredicate,
    InRangePredicate, ToInRangePredicate,
    InRangeBounds,
    InequalityPredicate, ToInequalityPredicate,
    Inequality,
    ExcludePredicate, ToExcludePredicate,
    LikePredicate, ToLikePredicate,
    IsNullPredicate, ToIsNullPredicate,
    RawPredicate
};

pub use select_query::{
    Selectable,
    Queryable,
    Orderable,
    SelectQuery,
    RcSelectQuery,
    ToSelectQuery,
    Select,
    NoResult,
    LimitOne,
    LimitTwo,
    LimitMany
};

pub use update_query::{
    UpdateQuery,
    FieldUpdate,
    FieldUpd,
    Updatable,
    ToFieldUpdate,
};

pub use insert_query::{
    InsertQuery,
    Insertable,
};

pub use delete_query::{
    DeleteQuery,
    Deletable,
};

pub use expression::{
    ToExpression,
    ToExprValue,
    BoxedExpression,
    UntypedExpression,
    Expression,
    RcExpression,
    ExprValue,
    RawExpr
};

pub use sql::{SqlContext, ToSql, QueryToSql, FromToSql, ToPredicateValue};
#[cfg(feature = "postgres")] pub use sql::{AsPostgresValue};
pub use from::{TableDef, Table, BoxedTable, RcTable, From, BoxedFrom, RcFrom};

pub use function::{
    Sum, SumArg,
    Min, MinArg,
    Max, MaxArg,
    Avg, AvgArg,
    Count, CountArg,
    CountAll
};

pub use placeholder::{
    Placeholder
};

macro_rules! with_clone(
    ($slf: ident, $v:ident, $ex:expr) => ({
        let mut $v = $slf.clone();
        $ex;
        $v
    })
)

mod field;
mod predicate;
mod select_query;
mod insert_query;

#[macro_escape]
mod delete_query;
mod update_query;
pub mod sql;
mod expression;
mod order_by;
mod from;
mod join;
mod distinct;
mod group_by;
mod function;
mod placeholder;

<|endoftext|>


<commit_before>//! # Scuttlebutt
//!
//! Scuttlebutt is an interface for extending kubernetes by feeding off a stream of kubernetes
//! cluster events

#[macro_use]
extern crate log;
extern crate hyper;
extern crate serde_json;

use hyper::{Client, Error as HttpError, Url};
use serde_json::StreamDeserializer;
use std::io::Read;
use std::sync::mpsc::{channel, Receiver};
use std::thread;

include!(concat!(env!("OUT_DIR"), "/lib.rs"));

const DEFAULT_HOST: &'static str = "http://localhost:8001";

pub type Result<T> = std::result::Result<T, Error>;

/// An enumeratation of potential errors
#[derive(Debug)]
pub enum Error {
    Transport(HttpError),
}

impl From<HttpError> for Error {
    fn from(error: HttpError) -> Error {
        Error::Transport(error)
    }
}

/// A cluster contains an address
/// for interacting with a kubernetes Cluster
/// of nodes
pub struct Cluster {
    host: Url,
}

/// Events provides a means for generating
/// a reciever for events
pub trait Events {
    fn events(&mut self) -> Result<Receiver<Event>>;

    fn generator<Iter>(&self, iter: Iter) -> Result<Receiver<Event>>
        where Iter: Iterator<Item = std::io::Result<u8>>,
              Iter: Send + 'static
    {
        let (tx, rx) = channel();
        let stream: StreamDeserializer<Event, _> = StreamDeserializer::new(iter);
        thread::spawn(move || {
            for e in stream {
                match e {
                    Ok(event) => {
                        if let Err(e) = tx.send(event) {
                            debug!("{:#?}", e);
                            break;
                        }
                    }
                    Err(e) => {
                        debug!("{:#?}", e);
                        break;
                    }
                }
            }
        });
        Ok(rx)
    }
}

impl Cluster {
    pub fn new() -> Cluster {
        Cluster { host: Url::parse(DEFAULT_HOST).unwrap() }
    }
}

impl Events for Cluster {
    fn events(&mut self) -> Result<Receiver<Event>> {
        let res = try!(Client::new()
            .get(self.host.join("/api/v1/events?watch=true").unwrap())
            .send());
        self.generator(res.bytes())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::Receiver;
    use std::io::Read;
    #[test]
    fn events_generator() {
        impl Events for &'static str {
            fn events(&mut self) -> Result<Receiver<Event>> {
                self.generator(self.bytes().into_iter().map(|b| Ok(b)))
            }
        }
        let events = r#"{
            "object":{
                "apiVersion": "1",
                "count": 1,
                "firstTimestamp": "...",
                "lastTimestamp": "...",
                "kind":"Event",
                "message":"test",
                "involvedObject": {
                    "apiVersion": "1",
                    "resourceVersion": "2",
                    "uid":"2",
                    "kind": "POD",
                    "name": "test_name",
                    "namespace": "test_namespace"
                },
                "metadata": {
                    "creationTimestamp": "...",
                    "deletionTimestamp": "...",
                    "name": "test",
                    "namespace":"default",
                    "resourceVersion": "1",
                    "selfLink": "...",
                    "uid": "1"
                },
                "reason": "started",
                "source": {
                    "component": "test",
                    "host": "foo.com"
                },
                "type": "Normal"
            },
            "type":"ADDED"
        }"#
            .events();
        assert!(events.unwrap()
            .into_iter()
            .map(|e| e.object.involved_object.namespace)
            .nth(0) == Some("test_namespace".to_owned()))
    }
}
<commit_msg>doc typo<commit_after>//! # Scuttlebutt
//!
//! Scuttlebutt is an interface for extending kubernetes by feeding off a stream of kubernetes
//! cluster events

#[macro_use]
extern crate log;
extern crate hyper;
extern crate serde_json;

use hyper::{Client, Error as HttpError, Url};
use serde_json::StreamDeserializer;
use std::io::Read;
use std::sync::mpsc::{channel, Receiver};
use std::thread;

include!(concat!(env!("OUT_DIR"), "/lib.rs"));

const DEFAULT_HOST: &'static str = "http://localhost:8001";

pub type Result<T> = std::result::Result<T, Error>;

/// An enumeratation of potential errors
#[derive(Debug)]
pub enum Error {
    Transport(HttpError),
}

impl From<HttpError> for Error {
    fn from(error: HttpError) -> Error {
        Error::Transport(error)
    }
}

/// A cluster contains an address
/// for interacting with a kubernetes Cluster
/// of nodes
pub struct Cluster {
    host: Url,
}

/// Events provides a means for generating
/// a receiver for events
pub trait Events {
    fn events(&mut self) -> Result<Receiver<Event>>;

    fn generator<Iter>(&self, iter: Iter) -> Result<Receiver<Event>>
        where Iter: Iterator<Item = std::io::Result<u8>>,
              Iter: Send + 'static
    {
        let (tx, rx) = channel();
        let stream: StreamDeserializer<Event, _> = StreamDeserializer::new(iter);
        thread::spawn(move || {
            for e in stream {
                match e {
                    Ok(event) => {
                        if let Err(e) = tx.send(event) {
                            debug!("{:#?}", e);
                            break;
                        }
                    }
                    Err(e) => {
                        debug!("{:#?}", e);
                        break;
                    }
                }
            }
        });
        Ok(rx)
    }
}

impl Cluster {
    pub fn new() -> Cluster {
        Cluster { host: Url::parse(DEFAULT_HOST).unwrap() }
    }
}

impl Events for Cluster {
    fn events(&mut self) -> Result<Receiver<Event>> {
        let res = try!(Client::new()
            .get(self.host.join("/api/v1/events?watch=true").unwrap())
            .send());
        self.generator(res.bytes())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::mpsc::Receiver;
    use std::io::Read;
    #[test]
    fn events_generator() {
        impl Events for &'static str {
            fn events(&mut self) -> Result<Receiver<Event>> {
                self.generator(self.bytes().into_iter().map(|b| Ok(b)))
            }
        }
        let events = r#"{
            "object":{
                "apiVersion": "1",
                "count": 1,
                "firstTimestamp": "...",
                "lastTimestamp": "...",
                "kind":"Event",
                "message":"test",
                "involvedObject": {
                    "apiVersion": "1",
                    "resourceVersion": "2",
                    "uid":"2",
                    "kind": "POD",
                    "name": "test_name",
                    "namespace": "test_namespace"
                },
                "metadata": {
                    "creationTimestamp": "...",
                    "deletionTimestamp": "...",
                    "name": "test",
                    "namespace":"default",
                    "resourceVersion": "1",
                    "selfLink": "...",
                    "uid": "1"
                },
                "reason": "started",
                "source": {
                    "component": "test",
                    "host": "foo.com"
                },
                "type": "Normal"
            },
            "type":"ADDED"
        }"#
            .events();
        assert!(events.unwrap()
            .into_iter()
            .map(|e| e.object.involved_object.namespace)
            .nth(0) == Some("test_namespace".to_owned()))
    }
}
<|endoftext|>


<commit_before>extern crate arc_swap;
extern crate libc;

use std::collections::hash_map::Entry;
use std::collections::{BTreeMap, HashMap};
use std::io::Error;
use std::mem;
use std::panic::{self, AssertUnwindSafe};
use std::process;
use std::ptr;
use std::sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT};
use std::thread;

use arc_swap::ArcSwap;
use libc::{c_int, c_void, sigaction, siginfo_t, sigset_t, SIG_BLOCK, SIG_SETMASK};

#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
struct ActionId(u64);

#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct SigId {
    signal: c_int,
    action: ActionId,
}

#[derive(Clone)]
struct Slot {
    prev: sigaction,
    actions: BTreeMap<ActionId, Arc<Fn()>>,
}

impl Slot {
    fn new(signal: libc::c_int) -> Result<Self, Error> {
        // C data structure, expected to be zeroed out.
        let mut new: libc::sigaction = unsafe { mem::zeroed() };
        new.sa_sigaction = handler as usize;
        #[cfg(target_os = "android")]
        fn flags() -> libc::c_ulong {
            (libc::SA_RESTART as libc::c_ulong)
                | libc::SA_SIGINFO
                | (libc::SA_NOCLDSTOP as libc::c_ulong)
        }
        #[cfg(not(target_os = "android"))]
        fn flags() -> libc::c_int {
            libc::SA_RESTART | libc::SA_SIGINFO | libc::SA_NOCLDSTOP
        }
        new.sa_flags = flags();
        // C data structure, expected to be zeroed out.
        let mut old: libc::sigaction = unsafe { mem::zeroed() };
        // FFI ‒ pointers are valid, it doesn't take ownership.
        if unsafe { libc::sigaction(signal, &new, &mut old) } != 0 {
            return Err(Error::last_os_error());
        }
        Ok(Slot {
            prev: old,
            actions: BTreeMap::new(),
        })
    }
}

type AllSignals = HashMap<c_int, Slot>;

struct GlobalData {
    all_signals: ArcSwap<AllSignals>,
    rcu_lock: Mutex<u64>,
}

static mut GLOBAL_DATA: Option<GlobalData> = None;
static GLOBAL_INIT: Once = ONCE_INIT;

impl GlobalData {
    fn get() -> &'static Self {
        unsafe { GLOBAL_DATA.as_ref().unwrap() }
    }
    fn ensure() -> &'static Self {
        GLOBAL_INIT.call_once(|| unsafe {
            GLOBAL_DATA = Some(GlobalData {
                all_signals: ArcSwap::from(Arc::new(HashMap::new())),
                rcu_lock: Mutex::new(0),
            });
        });
        Self::get()
    }
    fn load(&self) -> (AllSignals, MutexGuard<u64>) {
        let lock = self.rcu_lock.lock().unwrap();
        let signals = AllSignals::clone(&self.all_signals.load());
        (signals, lock)
    }
    fn store(&self, signals: AllSignals, lock: MutexGuard<u64>) {
        let mut previous = self.all_signals.swap(Arc::new(signals));
        while let Err(failed_unwrap) = Arc::try_unwrap(previous) {
            previous = failed_unwrap;
            thread::yield_now();
        }
        drop(lock);
    }
}

extern "C" fn handler(sig: c_int, info: *mut siginfo_t, data: *mut c_void) {
    let result = panic::catch_unwind(AssertUnwindSafe(|| {
        let signals = GlobalData::get().all_signals.load();

        if let Some(ref slot) = signals.get(&sig) {
            let fptr = slot.prev.sa_sigaction;
            if fptr != 0 && fptr != libc::SIG_DFL && fptr != libc::SIG_IGN {
                // FFI ‒ calling the original signal handler.
                unsafe {
                    if slot.prev.sa_flags & libc::SA_SIGINFO == 0 {
                        let action = mem::transmute::<usize, extern "C" fn(c_int)>(fptr);
                        action(sig);
                    } else {
                        type SigAction = extern "C" fn(c_int, *mut siginfo_t, *mut c_void);
                        let action = mem::transmute::<usize, SigAction>(fptr);
                        action(sig, info, data);
                    }
                }
            }

            for action in slot.actions.values() {
                action();
            }
        }
    }));
    if result.is_err() {
        eprintln!("Panic inside a signal handler for {}", sig);
        process::abort();
    }
}

fn block_signal(signal: c_int) -> Result<sigset_t, Error> {
    unsafe {
        let mut newsigs: sigset_t = mem::uninitialized();
        libc::sigemptyset(&mut newsigs);
        libc::sigaddset(&mut newsigs, signal);
        let mut oldsigs: sigset_t = mem::uninitialized();
        libc::sigemptyset(&mut oldsigs);
        if libc::sigprocmask(SIG_BLOCK, &newsigs, &mut oldsigs) == 0 {
            Ok(oldsigs)
        } else {
            Err(Error::last_os_error())
        }
    }
}

fn restore_signals(signals: libc::sigset_t) -> Result<(), Error> {
    if unsafe { libc::sigprocmask(SIG_SETMASK, &signals, ptr::null_mut()) } == 0 {
        Ok(())
    } else {
        Err(Error::last_os_error())
    }
}

fn without_signal<F: FnOnce() -> Result<(), Error>>(signal: c_int, f: F) -> Result<(), Error> {
    let old_signals = block_signal(signal)?;
    let result = f();
    let restored = restore_signals(old_signals);
    // In case of errors in both, prefer the one in result.
    result.and(restored)
}

pub unsafe fn register_action(signal: c_int, action: Box<Fn()>) -> Result<SigId, Error> {
    let globals = GlobalData::ensure();
    let (mut signals, mut lock) = globals.load();
    let id = ActionId(*lock);
    *lock += 1;
    let action = Arc::from(action);
    without_signal(signal, || {
        match signals.entry(signal) {
            Entry::Occupied(mut occupied) => {
                assert!(occupied.get_mut().actions.insert(id, action).is_none());
            }
            Entry::Vacant(place) => {
                let mut slot = Slot::new(signal)?;
                slot.actions.insert(id, action);
                place.insert(slot);
            }
        }

        globals.store(signals, lock);

        Ok(())
    })?;

    Ok(SigId { signal, action: id })
}

pub fn unregister(id: SigId) -> bool {
    let globals = GlobalData::ensure();
    let (mut signals, lock) = globals.load();
    let mut replace = false;
    if let Some(slot) = signals.get_mut(&id.signal) {
        replace = slot.actions.remove(&id.action).is_some();
    }
    if replace {
        globals.store(signals, lock);
    }
    replace
}
<commit_msg>Fix soundness hole<commit_after>extern crate arc_swap;
extern crate libc;

use std::collections::hash_map::Entry;
use std::collections::{BTreeMap, HashMap};
use std::io::Error;
use std::mem;
use std::panic::{self, AssertUnwindSafe};
use std::process;
use std::ptr;
use std::sync::{Arc, Mutex, MutexGuard, Once, ONCE_INIT};
use std::thread;

use arc_swap::ArcSwap;
use libc::{c_int, c_void, sigaction, siginfo_t, sigset_t, SIG_BLOCK, SIG_SETMASK};

#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
struct ActionId(u64);

#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct SigId {
    signal: c_int,
    action: ActionId,
}

pub type Action = Fn() + Send + Sync;

#[derive(Clone)]
struct Slot {
    prev: sigaction,
    actions: BTreeMap<ActionId, Arc<Action>>,
}

impl Slot {
    fn new(signal: libc::c_int) -> Result<Self, Error> {
        // C data structure, expected to be zeroed out.
        let mut new: libc::sigaction = unsafe { mem::zeroed() };
        new.sa_sigaction = handler as usize;
        #[cfg(target_os = "android")]
        fn flags() -> libc::c_ulong {
            (libc::SA_RESTART as libc::c_ulong)
                | libc::SA_SIGINFO
                | (libc::SA_NOCLDSTOP as libc::c_ulong)
        }
        #[cfg(not(target_os = "android"))]
        fn flags() -> libc::c_int {
            libc::SA_RESTART | libc::SA_SIGINFO | libc::SA_NOCLDSTOP
        }
        new.sa_flags = flags();
        // C data structure, expected to be zeroed out.
        let mut old: libc::sigaction = unsafe { mem::zeroed() };
        // FFI ‒ pointers are valid, it doesn't take ownership.
        if unsafe { libc::sigaction(signal, &new, &mut old) } != 0 {
            return Err(Error::last_os_error());
        }
        Ok(Slot {
            prev: old,
            actions: BTreeMap::new(),
        })
    }
}

type AllSignals = HashMap<c_int, Slot>;

struct GlobalData {
    all_signals: ArcSwap<AllSignals>,
    rcu_lock: Mutex<u64>,
}

static mut GLOBAL_DATA: Option<GlobalData> = None;
static GLOBAL_INIT: Once = ONCE_INIT;

impl GlobalData {
    fn get() -> &'static Self {
        unsafe { GLOBAL_DATA.as_ref().unwrap() }
    }
    fn ensure() -> &'static Self {
        GLOBAL_INIT.call_once(|| unsafe {
            GLOBAL_DATA = Some(GlobalData {
                all_signals: ArcSwap::from(Arc::new(HashMap::new())),
                rcu_lock: Mutex::new(0),
            });
        });
        Self::get()
    }
    fn load(&self) -> (AllSignals, MutexGuard<u64>) {
        let lock = self.rcu_lock.lock().unwrap();
        let signals = AllSignals::clone(&self.all_signals.load());
        (signals, lock)
    }
    fn store(&self, signals: AllSignals, lock: MutexGuard<u64>) {
        let mut previous = self.all_signals.swap(Arc::new(signals));
        while let Err(failed_unwrap) = Arc::try_unwrap(previous) {
            previous = failed_unwrap;
            thread::yield_now();
        }
        drop(lock);
    }
}

extern "C" fn handler(sig: c_int, info: *mut siginfo_t, data: *mut c_void) {
    let result = panic::catch_unwind(AssertUnwindSafe(|| {
        let signals = GlobalData::get().all_signals.load();

        if let Some(ref slot) = signals.get(&sig) {
            let fptr = slot.prev.sa_sigaction;
            if fptr != 0 && fptr != libc::SIG_DFL && fptr != libc::SIG_IGN {
                // FFI ‒ calling the original signal handler.
                unsafe {
                    if slot.prev.sa_flags & libc::SA_SIGINFO == 0 {
                        let action = mem::transmute::<usize, extern "C" fn(c_int)>(fptr);
                        action(sig);
                    } else {
                        type SigAction = extern "C" fn(c_int, *mut siginfo_t, *mut c_void);
                        let action = mem::transmute::<usize, SigAction>(fptr);
                        action(sig, info, data);
                    }
                }
            }

            for action in slot.actions.values() {
                action();
            }
        }
    }));
    if result.is_err() {
        eprintln!("Panic inside a signal handler for {}", sig);
        process::abort();
    }
}

fn block_signal(signal: c_int) -> Result<sigset_t, Error> {
    unsafe {
        let mut newsigs: sigset_t = mem::uninitialized();
        libc::sigemptyset(&mut newsigs);
        libc::sigaddset(&mut newsigs, signal);
        let mut oldsigs: sigset_t = mem::uninitialized();
        libc::sigemptyset(&mut oldsigs);
        if libc::sigprocmask(SIG_BLOCK, &newsigs, &mut oldsigs) == 0 {
            Ok(oldsigs)
        } else {
            Err(Error::last_os_error())
        }
    }
}

fn restore_signals(signals: libc::sigset_t) -> Result<(), Error> {
    if unsafe { libc::sigprocmask(SIG_SETMASK, &signals, ptr::null_mut()) } == 0 {
        Ok(())
    } else {
        Err(Error::last_os_error())
    }
}

fn without_signal<F: FnOnce() -> Result<(), Error>>(signal: c_int, f: F) -> Result<(), Error> {
    let old_signals = block_signal(signal)?;
    let result = f();
    let restored = restore_signals(old_signals);
    // In case of errors in both, prefer the one in result.
    result.and(restored)
}

pub unsafe fn register_action(signal: c_int, action: Box<Action>) -> Result<SigId, Error> {
    let globals = GlobalData::ensure();
    let (mut signals, mut lock) = globals.load();
    let id = ActionId(*lock);
    *lock += 1;
    let action = Arc::from(action);
    without_signal(signal, || {
        match signals.entry(signal) {
            Entry::Occupied(mut occupied) => {
                assert!(occupied.get_mut().actions.insert(id, action).is_none());
            }
            Entry::Vacant(place) => {
                let mut slot = Slot::new(signal)?;
                slot.actions.insert(id, action);
                place.insert(slot);
            }
        }

        globals.store(signals, lock);

        Ok(())
    })?;

    Ok(SigId { signal, action: id })
}

pub fn unregister(id: SigId) -> bool {
    let globals = GlobalData::ensure();
    let (mut signals, lock) = globals.load();
    let mut replace = false;
    if let Some(slot) = signals.get_mut(&id.signal) {
        replace = slot.actions.remove(&id.action).is_some();
    }
    if replace {
        globals.store(signals, lock);
    }
    replace
}
<|endoftext|>


<commit_before>#[crate_id = "rustful#0.1-pre"];

#[comment = "RESTful web framework"];
#[license = "MIT"];
#[crate_type = "lib"];
#[crate_type = "rlib"];

#[doc(html_root_url = "http://www.rust-ci.org/Ogeon/rustful/doc/")];

#[cfg(test)]
extern crate test;

extern crate collections;
extern crate url;
extern crate time;
extern crate http;

pub use router::Router;
pub use server::Server;
pub use request::Request;
pub use response::Response;

pub mod router;
pub mod server;
pub mod request;
pub mod response;<commit_msg>Changed to the new inner attribute syntax<commit_after>#![crate_id = "rustful#0.1-pre"]

#![comment = "RESTful web framework"]
#![license = "MIT"]
#![crate_type = "lib"]
#![crate_type = "rlib"]

#![doc(html_root_url = "http://www.rust-ci.org/Ogeon/rustful/doc/")]

#[cfg(test)]
extern crate test;

extern crate collections;
extern crate url;
extern crate time;
extern crate http;

pub use router::Router;
pub use server::Server;
pub use request::Request;
pub use response::Response;

pub mod router;
pub mod server;
pub mod request;
pub mod response;<|endoftext|>


<commit_before>extern crate mio;
extern crate crossbeam;

use mio::tcp::*;
use mio::TryWrite;
use mio::util::Slab;
use std::net::SocketAddr;
use std::io::Result;
use mio::{EventSet, EventLoop, Token, Handler, PollOpt};
use std::thread;
//use std::thread::{JoinHandle, JoinInner};
use std::sync::{Arc, RwLock, Condvar};
//use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::VecDeque;
use crossbeam::Scope;

const CLIENT_TOKEN: mio::Token = mio::Token(1);

pub struct ClientNetworkInterface{
    socket: TcpStream,

    //thread_handle: Arc<Option<JoinHandle<()>>>,

    client: Arc<RwLock<Client>>
}

impl ClientNetworkInterface{
    pub fn new(event_loop: &mut EventLoop<ClientNetworkInterface>, socket: TcpStream, client: Arc<RwLock<Client>>) -> Arc<RwLock<ClientNetworkInterface>>{
        let interface = Arc::new(RwLock::new(ClientNetworkInterface{
            socket: socket,
            //thread_handle: Arc::new(None),
            client: client
        }));

        let thread_interface = interface.clone();
        println!("Before");
        crossbeam::scope(|scope|{
            scope.spawn(||{
                println!("thread start");
                loop{
                    if let Ok(mut client_interface) = thread_interface.write(){
                        event_loop.run_once(&mut client_interface, None);
                    }
                }
            });
        });
        println!("after");

        // if let Ok(interface_mut) = interface.write(){
        //     interface_mut.thread_handle = handle;
        // }

        return interface;
    }

    fn register(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, client_ref: Arc<RwLock<Client>>){
        if let Ok(client) = client_ref.read(){
            event_loop.register(
                &self.socket,
                client.token,
                client.interest,
                PollOpt::edge() | PollOpt::oneshot()
            ).or_else(|e| {
                println!("Failed to register server! {:?}", e);
                Err(e)
            });
        }
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, client_ref: Arc<RwLock<Client>>){
        if let Ok(client) = client_ref.read(){
            event_loop.reregister(&self.socket, client.token, client.interest, PollOpt::edge())
                .or_else(|e|{
                    println!("I am a sad panda, {:?}", e);
                    Err(e)
            });
        }
    }
}

pub struct Client{
    pub token: Token,

    interest: EventSet,

    send_queue: VecDeque<String>,
}

impl Client{
    pub fn new() -> Client{
        Client {
            send_queue: VecDeque::new(),
            token: CLIENT_TOKEN,
            interest: EventSet::readable() | EventSet::writable()
        }
        // client.register(event_loop).ok();
        //
        // client.send_queue.push_back(String::from("Hell fucking yeah motherfucker"));
        // client.send_queue.push_back(String::from("And so I wake in the morning"));
        // client.send_queue.push_back(String::from("And I step outside"));
        // client.send_queue.push_back(String::from("And I take a deep breath and I get real high"));
        // client.send_queue.push_back(String::from("And I scream from the top of my lungs"));
        // client.send_queue.push_back(String::from("What's going on?"));
        //
        //
        // event_loop.run(&mut client).or_else(|e|{
        //     println!("Failed to start event loop!");
        //     Err(e)
        // });
    }
}

type RwArcClientInterface = Arc<RwLock<ClientNetworkInterface>>;

impl Handler for ClientNetworkInterface{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, _: &mut EventLoop<ClientNetworkInterface>) {
        println!("Begin client tick");

        println!("End client tick");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, token: Token, events: EventSet) {
        assert!(token != Token(0), "Token 0, y?????");

        if events.is_error(){
            println!("Client received error for token {:?}", token);
            return;
        }

        if events.is_hup(){
            println!("Oh shit, did the server crash or some shit?!");
            return;
        }

        if events.is_writable(){
            println!("TIME TO TALK MOTHERFUCKER");

            if let Ok(mut client) = self.client.write(){
                if !client.send_queue.is_empty(){
                    if let Some(message) = client.send_queue.pop_front(){
                        match self.socket.try_write(message.as_bytes()){
                            Ok(Some(n)) => {
                                println!("Wrote {} bytes", n);
                            },
                            Ok(None) => {
                                println!("Nothing happened but it's okay I guess?");
                                client.send_queue.push_back(message);
                            },
                            Err(e) => {
                                println!("Oh fuck me god fucking damn it fucking shit fuck: {:?}", e);
                                client.send_queue.push_back(message);
                            }
                        };
                    }
                    else{
                        println!("Failed to pop message from queue!");
                    }
                }
                else{
                    println!("WTF do you mean there's no messages for me?");
                }
            }
        }

        if events.is_readable(){
            println!("OH shit, what've you got to say?");
        }

        let mut client_rereg = self.client.clone();
        self.reregister(event_loop, client_rereg);
        //self.debug.fetch_add(1, Ordering::SeqCst);
    }

    fn notify(&mut self, _: &mut EventLoop<Self>, _: Self::Message) {
        println!("Received notify!");
    }

    fn timeout(&mut self, _: &mut EventLoop<Self>, _: Self::Timeout) {
        println!("Received timeout");
    }
    fn interrupted(&mut self, _: &mut EventLoop<Self>) {
        println!("Interrupted! :O");
    }
}

#[test]
fn connect(){
    let addr = "127.0.0.1:6969".parse().unwrap();

    let mut socket = TcpStream::connect(&addr);
    if socket.is_ok(){

        println!("Starting thing");
        let mut event_loop = EventLoop::new().ok().expect("Failed to create event loop!");
        let mut client = Arc::new(RwLock::new(Client::new()));
        let mut client_interface = ClientNetworkInterface::new(&mut event_loop, socket.unwrap(), client.clone());
        println!("Starting debug loop");

        if let Ok(mut interface) = client_interface.write(){
            interface.register(&mut event_loop, client);
        }

        loop{
            // if client.debug.load(Ordering::Relaxed) > 0{
            //     break;
            // }
        }

        println!("Done with this shit");
    }
    else{
        println!("Failed to open socket! {:?}", socket.unwrap_err());
    }
}

#[cfg(test)]
mod test {
    use mio::tcp::*;
    use mio::TryWrite;
    use std::net::SocketAddr;
    //use lag_client::Client;

}
<commit_msg>Hell yaaaas! Got me some threaded messaging<commit_after>extern crate mio;
extern crate crossbeam;

use mio::tcp::*;
use mio::TryWrite;
use mio::util::Slab;
use std::net::SocketAddr;
use std::io::Result;
use mio::{EventSet, EventLoop, Token, Handler, PollOpt};
use std::thread;
//use std::thread::{JoinHandle, JoinInner};
use std::sync::{Arc, RwLock, Condvar};
//use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::VecDeque;
//use crossbeam::Scope;

const CLIENT_TOKEN: mio::Token = mio::Token(1);

pub struct ClientNetworkInterface{
    socket: TcpStream,

    //thread_handle: Arc<Option<JoinHandle<()>>>,

    client: Arc<RwLock<Client>>
}

impl ClientNetworkInterface{
    pub fn new(event_loop: Arc<RwLock<EventLoop<ClientNetworkInterface>>>, socket: TcpStream, client: Arc<RwLock<Client>>) -> Arc<RwLock<ClientNetworkInterface>>{
        let interface = Arc::new(RwLock::new(ClientNetworkInterface{
            socket: socket,
            //thread_handle: Arc::new(None),
            client: client
        }));

        let thread_interface = interface.clone();
        println!("Before");
        thread::spawn(move||{
            println!("Hello from thread!");

            loop{
                if let Ok(mut event_loop) = event_loop.write(){
                    if let Ok(mut client_interface) = thread_interface.write(){
                        event_loop.run_once(&mut client_interface, None);
                    }
                }
            }
        });
        // crossbeam::scope(|scope|{
        //     scope.spawn(||{
        //         println!("thread start");
        //         loop{
        //             if let Ok(mut client_interface) = thread_interface.write(){
        //                 event_loop.run_once(&mut client_interface, None);
        //             }
        //         }
        //     });
        // });
        println!("after");

        // if let Ok(interface_mut) = interface.write(){
        //     interface_mut.thread_handle = handle;
        // }

        return interface;
    }

    fn register(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, client_ref: &Arc<RwLock<Client>>){
        if let Ok(client) = client_ref.read(){
            event_loop.register(
                &self.socket,
                client.token,
                client.interest,
                PollOpt::edge() | PollOpt::oneshot()
            ).or_else(|e| {
                println!("Failed to register server! {:?}", e);
                Err(e)
            });
        }
    }

    fn reregister(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, client_ref: Arc<RwLock<Client>>){
        if let Ok(client) = client_ref.read(){
            event_loop.reregister(&self.socket, client.token, client.interest, PollOpt::edge())
                .or_else(|e|{
                    println!("I am a sad panda, {:?}", e);
                    Err(e)
            });
        }
    }
}

pub struct Client{
    pub token: Token,

    interest: EventSet,

    send_queue: VecDeque<String>,
}

impl Client{
    pub fn new() -> Client{
        Client {
            send_queue: VecDeque::new(),
            token: CLIENT_TOKEN,
            interest: EventSet::readable() | EventSet::writable()
        }
        // client.register(event_loop).ok();
        //
        // client.send_queue.push_back(String::from("Hell fucking yeah motherfucker"));
        // client.send_queue.push_back(String::from("And so I wake in the morning"));
        // client.send_queue.push_back(String::from("And I step outside"));
        // client.send_queue.push_back(String::from("And I take a deep breath and I get real high"));
        // client.send_queue.push_back(String::from("And I scream from the top of my lungs"));
        // client.send_queue.push_back(String::from("What's going on?"));
        //
        //
        // event_loop.run(&mut client).or_else(|e|{
        //     println!("Failed to start event loop!");
        //     Err(e)
        // });
    }
}

type RwArcClientInterface = Arc<RwLock<ClientNetworkInterface>>;

impl Handler for ClientNetworkInterface{
    type Timeout = ();
    type Message = ();

    fn tick(&mut self, _: &mut EventLoop<ClientNetworkInterface>) {
        println!("Begin client tick");

        println!("End client tick");
    }

    fn ready(&mut self, event_loop: &mut EventLoop<ClientNetworkInterface>, token: Token, events: EventSet) {
        assert!(token != Token(0), "Token 0, y?????");

        if events.is_error(){
            println!("Client received error for token {:?}", token);
            return;
        }

        if events.is_hup(){
            println!("Oh shit, did the server crash or some shit?!");
            return;
        }

        if events.is_writable(){
            println!("TIME TO TALK MOTHERFUCKER");

            if let Ok(mut client) = self.client.write(){
                if !client.send_queue.is_empty(){
                    if let Some(message) = client.send_queue.pop_front(){
                        match self.socket.try_write(message.as_bytes()){
                            Ok(Some(n)) => {
                                println!("Wrote {} bytes", n);
                            },
                            Ok(None) => {
                                println!("Nothing happened but it's okay I guess?");
                                client.send_queue.push_back(message);
                            },
                            Err(e) => {
                                println!("Oh fuck me god fucking damn it fucking shit fuck: {:?}", e);
                                client.send_queue.push_back(message);
                            }
                        };
                    }
                    else{
                        println!("Failed to pop message from queue!");
                    }
                }
                else{
                    println!("WTF do you mean there's no messages for me?");
                }
            }
        }

        if events.is_readable(){
            println!("OH shit, what've you got to say?");
        }

        let mut client_rereg = self.client.clone();
        self.reregister(event_loop, client_rereg);
        //self.debug.fetch_add(1, Ordering::SeqCst);
    }

    fn notify(&mut self, _: &mut EventLoop<Self>, _: Self::Message) {
        println!("Received notify!");
    }

    fn timeout(&mut self, _: &mut EventLoop<Self>, _: Self::Timeout) {
        println!("Received timeout");
    }
    fn interrupted(&mut self, _: &mut EventLoop<Self>) {
        println!("Interrupted! :O");
    }
}

#[test]
fn connect(){
    let addr = "127.0.0.1:6969".parse().unwrap();

    let mut socket = TcpStream::connect(&addr);
    if socket.is_ok(){

        println!("Starting thing");
        let mut event_loop = Arc::new(RwLock::new(EventLoop::new().ok().expect("Failed to create event loop!")));
        let mut client = Arc::new(RwLock::new(Client::new()));

        let interface_event_loop = event_loop.clone();
        let mut client_interface = ClientNetworkInterface::new(interface_event_loop, socket.unwrap(), client.clone());
        println!("Starting debug loop");

        if let Ok(mut event_loop_ref) = event_loop.write(){
            if let Ok(mut interface) = client_interface.write(){
                interface.register(&mut event_loop_ref, &client);
            }
        }

        if let Ok(mut client_ref) = client.write(){
            client_ref.send_queue.push_front(String::from("Hello, world!"));
        }

        loop{
            // if client.debug.load(Ordering::Relaxed) > 0{
            //     break;
            // }
        }

        println!("Done with this shit");
    }
    else{
        println!("Failed to open socket! {:?}", socket.unwrap_err());
    }
}

#[cfg(test)]
mod test {
    use mio::tcp::*;
    use mio::TryWrite;
    use std::net::SocketAddr;
    //use lag_client::Client;

}
<|endoftext|>


<commit_before>#[crate_type = "lib"];
#[crate_id = "strain#0.0.1"];
#[feature(globs,phase)];
#[phase(syntax, link)] extern crate log;

extern crate leveldb;

use state::State;

pub mod state;
pub mod mutable;
//pub mod immutable;
pub mod errors;
pub mod strain;

#[cfg(test)]
mod tests {
  use super::state::State;
  use super::mutable::Event;
  use super::mutable::MutableStrain;
  use super::strain::Strain;
  use super::errors::{Errors, PreConditionNotMet, PostConditionNotMet};

  struct Counter {
    count: int,
  }
  impl State for Counter {}

  struct Increment;
  struct Decrement;

  impl Event<Counter> for Increment {
    fn precondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 0 {
        Err(PreConditionNotMet(~"I cannot count to negatives"))
      } else {
        Ok(())
      }
    }

    fn action(&self, state: &mut Counter) -> Result<(), Errors>  {
      state.count = state.count + 1;
      Ok(())
    }

    fn postcondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 0 {
        Err(PostConditionNotMet(~"I shouldn't have counted to negatives"))
      } else {
        Ok(())
      }
    }
  }

  impl Event<Counter> for Decrement {
    fn precondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 1 {
        Err(PreConditionNotMet(~"I cannot count to negatives"))
      } else {
        Ok(())
      }
    }

    fn action(&self, state: &mut Counter) -> Result<(), Errors>  {
      state.count = state.count - 1;
      Ok(())
    }

    fn postcondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 0 {
        Err(PostConditionNotMet(~"I shouldn't have counted to negatives"))
      } else {
        Ok(())
      }
    }

  }

  #[test]
  fn test_state_changes() {
    let mut strain : Strain<Counter> = Strain { state: ~Counter { count: 0 } };
    let res = strain.feed(&Increment).and_then(|_| {
      strain.feed(&Increment).and_then(|_| {
        strain.feed(&Decrement)
      })
    });
    assert!(res.is_ok());
    assert_eq!(strain.state().count, 1);
  }

  #[test]
  fn test_unmet_pre_condition() {
    let mut strain : Strain<Counter> = Strain { state: ~Counter { count: -1 } };
    let res = strain.feed(&Increment);
    assert!(res.is_err());
    assert_eq!(strain.state().count, -1);
  }
}
<commit_msg>Use new attribute syntax, remove warnings<commit_after>#![crate_type = "lib"]
#![crate_id = "strain#0.0.1"]
#![feature(globs,phase)]
#![phase(syntax, link)] extern crate log;

extern crate leveldb;

pub mod state;
pub mod mutable;
//pub mod immutable;
pub mod errors;
pub mod strain;

#[cfg(test)]
mod tests {
  use super::state::State;
  use super::mutable::Event;
  use super::mutable::MutableStrain;
  use super::strain::Strain;
  use super::errors::{Errors, PreConditionNotMet, PostConditionNotMet};

  struct Counter {
    count: int,
  }
  impl State for Counter {}

  struct Increment;
  struct Decrement;

  impl Event<Counter> for Increment {
    fn precondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 0 {
        Err(PreConditionNotMet(~"I cannot count to negatives"))
      } else {
        Ok(())
      }
    }

    fn action(&self, state: &mut Counter) -> Result<(), Errors>  {
      state.count = state.count + 1;
      Ok(())
    }

    fn postcondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 0 {
        Err(PostConditionNotMet(~"I shouldn't have counted to negatives"))
      } else {
        Ok(())
      }
    }
  }

  impl Event<Counter> for Decrement {
    fn precondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 1 {
        Err(PreConditionNotMet(~"I cannot count to negatives"))
      } else {
        Ok(())
      }
    }

    fn action(&self, state: &mut Counter) -> Result<(), Errors>  {
      state.count = state.count - 1;
      Ok(())
    }

    fn postcondition(&self, state: &Counter) -> Result<(), Errors> {
      if state.count < 0 {
        Err(PostConditionNotMet(~"I shouldn't have counted to negatives"))
      } else {
        Ok(())
      }
    }

  }

  #[test]
  fn test_state_changes() {
    let mut strain : Strain<Counter> = Strain { state: ~Counter { count: 0 } };
    let res = strain.feed(&Increment).and_then(|_| {
      strain.feed(&Increment).and_then(|_| {
        strain.feed(&Decrement)
      })
    });
    assert!(res.is_ok());
    assert_eq!(strain.state().count, 1);
  }

  #[test]
  fn test_unmet_pre_condition() {
    let mut strain : Strain<Counter> = Strain { state: ~Counter { count: -1 } };
    let res = strain.feed(&Increment);
    assert!(res.is_err());
    assert_eq!(strain.state().count, -1);
  }
}
<|endoftext|>


<commit_before>/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::new()`.

The `new()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```rust
let server = httpd::Server::new().unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```rust
loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```rust
let server = Arc::new(server);

for _ in range(0u, 4) {
    let server = server.clone();

    spawn(proc() {
        loop {
            let rq = server.recv().unwrap();

            ...
        }
    })
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.get_method()` and `request.get_url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```rust
let response = httpd::Response::from_file(Path::new("image.png"));
```

All that remains to do is call `request.respond()`:

```rust
request.respond(response)
```
*/

#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]
#![feature(unsafe_destructor)]

extern crate encoding;
extern crate time;
extern crate url;

use std::io::{Acceptor, IoResult, Listener};
use std::io::net::ip;
use std::io::net::tcp;
use std::comm::Select;
use std::sync::{Arc, Mutex};
use std::sync::atomics::AtomicBool;
use client::ClientConnection;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::Response;

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
#[unstable]
pub struct Server {
    // tasks where the client connections are dispatched
    tasks_pool: util::TaskPool,

    // receiver for client connections
    connections_receiver: Mutex<Receiver<IoResult<ClientConnection>>>,

    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // the sender linked to requests_receiver
    // cloned each time a client connection is created
    requests_sender: Mutex<Sender<Request>>,

    // channel to receive requests from
    requests_receiver: Mutex<Receiver<Request>>,

    // result of TcpListener::socket_name()
    listening_addr: ip::SocketAddr,
}

// this trait is to make sure that Server implements Share and Send
trait MustBeShareDummy : Share + Send {}
impl MustBeShareDummy for Server {}

#[unstable]
pub struct IncomingRequests<'a> {
    server: &'a Server
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    #[unstable]
    #[inline]
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    #[unstable]
    #[inline]
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server on a rand port and that listens to all inputs.
    /// Returns the server and the port it was created on.
    /// This function is guaranteed not to fail because of a port already in use,
    ///  and is useful for testing purposes.
    #[unstable]
    #[inline]
    pub fn new_with_random_port() -> IoResult<(Server, ip::Port)> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: 0})
            .map(|s| { let port = s.get_server_addr().port; (s, port) })
    }

    /// Builds a new server that listens on the specified address.
    #[unstable]
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpAcceptor
        let (server, local_addr) = {
            let mut listener = try!(tcp::TcpListener::bind(
                format!("{}", addr.ip).as_slice(), addr.port));
            let local_addr = try!(listener.socket_name());
            let server = try!(listener.listen());
            let server = util::ClosableTcpAcceptor::new(server, close_trigger.clone());
            (server, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();

        let inside_close_trigger = close_trigger.clone();
        spawn(proc() {
            let mut server = server;

            loop {
                let new_client = server.accept().map(|sock| {
                    use util::ClosableTcpStream;

                    let read_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), true, false);

                    let write_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), false, true);

                    ClientConnection::new(write_closable, read_closable)
                });

                if tx_incoming.send_opt(new_client).is_err() {
                    break
                }
            }
        });

        //
        let (tx_requests, rx_requests) = channel();

        // result
        Ok(Server {
            tasks_pool: util::TaskPool::new(),
            connections_receiver: Mutex::new(rx_incoming),
            close: close_trigger,
            requests_sender: Mutex::new(tx_requests),
            requests_receiver: Mutex::new(rx_requests),
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[unstable]
    #[inline]
    pub fn incoming_requests<'a>(&'a self) -> IncomingRequests<'a> {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[experimental]
    #[inline]
    pub fn get_server_addr(&self) -> ip::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    #[stable]
    pub fn get_num_connections(&self) -> uint {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        let connections_receiver = self.connections_receiver.lock();
        let requests_receiver = self.requests_receiver.lock();

        // TODO: the select! macro doesn't seem to be usable without moving
        //       out of self, so we use Select directly

        let select = Select::new();

        let mut request_handle = select.handle(&*requests_receiver);
        unsafe { request_handle.add() };

        let mut connect_handle = select.handle(&*connections_receiver);
        unsafe { connect_handle.add() };

        loop {
            let id = select.wait();

            if id == request_handle.id() {
                let request = request_handle.recv();

                unsafe { request_handle.remove() };
                unsafe { connect_handle.remove() };

                return Ok(request)
            }

            if id == connect_handle.id() {
                let client = connect_handle.recv_opt();

                match client {
                    Ok(Ok(client)) => {
                        self.add_client(client);
                        continue
                    },
                    Ok(Err(err)) => {
                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(err)
                    },
                    Err(_) => {
                        use std::io;

                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(io::standard_error(io::Closed));
                    }
                }
            }

            unreachable!()
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        let mut connections_receiver = self.connections_receiver.lock();
        let mut requests_receiver = self.requests_receiver.lock();

        // processing all new clients
        loop {
            match connections_receiver.try_recv() {
                Ok(client) => self.add_client(try!(client)),
                Err(_) => break
            }
        }

        // reading the next request
        Ok(requests_receiver.try_recv().ok())
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let requests_sender = self.requests_sender.lock().clone();

        self.tasks_pool.spawn(proc() {
            let mut client = client;
            // TODO: when the channel is being closed, immediatly notify the task
            client.advance(|rq| requests_sender.send_opt(rq).is_ok());
        });
    }
}

impl<'a> Iterator<Request> for IncomingRequests<'a> {
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomics::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<commit_msg>Clarify add_client function body<commit_after>/*!
# Simple usage

## Creating the server

The easiest way to create a server is to call `Server::new()`.

The `new()` function returns an `IoResult<Server>` which will return an error
in the case where the server creation fails (for example if the listening port is already
occupied).

```rust
let server = httpd::Server::new().unwrap();
```

A newly-created `Server` will immediatly start listening for incoming connections and HTTP
requests.

## Receiving requests

Calling `server.recv()` will block until the next request is available.
This function returns an `IoResult<Request>`, so you need to handle the possible errors.

```rust
loop {
    // blocks until the next request is received
    let request = match server.recv() {
        Ok(rq) => rq,
        Err(e) => { println!("error: {}", e); break }
    };

    // do something with the request
    ...
}
```

In a real-case scenario, you will probably want to spawn multiple worker tasks and call
`server.recv()` on all of them. Like this:

```rust
let server = Arc::new(server);

for _ in range(0u, 4) {
    let server = server.clone();

    spawn(proc() {
        loop {
            let rq = server.recv().unwrap();

            ...
        }
    })
}
```

If you don't want to block, you can call `server.try_recv()` instead.

## Handling requests

The `Request` object returned by `server.recv()` contains informations about the client's request.
The most useful methods are probably `request.get_method()` and `request.get_url()` which return
the requested method (`GET`, `POST`, etc.) and url.

To handle a request, you need to create a `Response` object. See the docs of this object for
more infos. Here is an example of creating a `Response` from a file:

```rust
let response = httpd::Response::from_file(Path::new("image.png"));
```

All that remains to do is call `request.respond()`:

```rust
request.respond(response)
```
*/

#![crate_name = "tiny-http"]
#![crate_type = "lib"]
#![license = "Apache"]
#![feature(unsafe_destructor)]

extern crate encoding;
extern crate time;
extern crate url;

use std::io::{Acceptor, IoResult, Listener};
use std::io::net::ip;
use std::io::net::tcp;
use std::comm::Select;
use std::sync::{Arc, Mutex};
use std::sync::atomics::AtomicBool;
use client::ClientConnection;

pub use common::{Header, HeaderField, HTTPVersion, Method, StatusCode};
pub use request::Request;
pub use response::Response;

mod client;
mod common;
mod request;
mod response;

#[allow(dead_code)]     // TODO: remove when everything is implemented
mod util;

/// The main class of this library.
///
/// Destroying this object will immediatly close the listening socket annd the reading
///  part of all the client's connections. Requests that have already been returned by
///  the `recv()` function will not close and the responses will be transferred to the client.
#[unstable]
pub struct Server {
    // tasks where the client connections are dispatched
    tasks_pool: util::TaskPool,

    // receiver for client connections
    connections_receiver: Mutex<Receiver<IoResult<ClientConnection>>>,

    // should be false as long as the server exists
    // when set to true, all the subtasks will close within a few hundreds ms
    close: Arc<AtomicBool>,

    // the sender linked to requests_receiver
    // cloned each time a client connection is created
    requests_sender: Mutex<Sender<Request>>,

    // channel to receive requests from
    requests_receiver: Mutex<Receiver<Request>>,

    // result of TcpListener::socket_name()
    listening_addr: ip::SocketAddr,
}

// this trait is to make sure that Server implements Share and Send
trait MustBeShareDummy : Share + Send {}
impl MustBeShareDummy for Server {}

#[unstable]
pub struct IncomingRequests<'a> {
    server: &'a Server
}

impl Server {
    /// Builds a new server on port 80 that listens to all inputs.
    #[unstable]
    #[inline]
    pub fn new() -> IoResult<Server> {
        Server::new_with_port(80)
    }

    /// Builds a new server on a given port and that listens to all inputs.
    #[unstable]
    #[inline]
    pub fn new_with_port(port: ip::Port) -> IoResult<Server> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: port})
    }

    /// Builds a new server on a rand port and that listens to all inputs.
    /// Returns the server and the port it was created on.
    /// This function is guaranteed not to fail because of a port already in use,
    ///  and is useful for testing purposes.
    #[unstable]
    #[inline]
    pub fn new_with_random_port() -> IoResult<(Server, ip::Port)> {
        Server::new_with_addr(&ip::SocketAddr{ip: ip::Ipv4Addr(0, 0, 0, 0), port: 0})
            .map(|s| { let port = s.get_server_addr().port; (s, port) })
    }

    /// Builds a new server that listens on the specified address.
    #[unstable]
    pub fn new_with_addr(addr: &ip::SocketAddr) -> IoResult<Server> {
        // building the "close" variable
        let close_trigger = Arc::new(AtomicBool::new(false));

        // building the TcpAcceptor
        let (server, local_addr) = {
            let mut listener = try!(tcp::TcpListener::bind(
                format!("{}", addr.ip).as_slice(), addr.port));
            let local_addr = try!(listener.socket_name());
            let server = try!(listener.listen());
            let server = util::ClosableTcpAcceptor::new(server, close_trigger.clone());
            (server, local_addr)
        };

        // creating a task where server.accept() is continuously called
        // and ClientConnection objects are returned in the receiver
        let (tx_incoming, rx_incoming) = channel();

        let inside_close_trigger = close_trigger.clone();
        spawn(proc() {
            let mut server = server;

            loop {
                let new_client = server.accept().map(|sock| {
                    use util::ClosableTcpStream;

                    let read_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), true, false);

                    let write_closable = ClosableTcpStream::new(sock.clone(),
                        inside_close_trigger.clone(), false, true);

                    ClientConnection::new(write_closable, read_closable)
                });

                if tx_incoming.send_opt(new_client).is_err() {
                    break
                }
            }
        });

        //
        let (tx_requests, rx_requests) = channel();

        // result
        Ok(Server {
            tasks_pool: util::TaskPool::new(),
            connections_receiver: Mutex::new(rx_incoming),
            close: close_trigger,
            requests_sender: Mutex::new(tx_requests),
            requests_receiver: Mutex::new(rx_requests),
            listening_addr: local_addr,
        })
    }

    /// Returns an iterator for all the incoming requests.
    ///
    /// The iterator will return `None` if the server socket is shutdown.
    #[unstable]
    #[inline]
    pub fn incoming_requests<'a>(&'a self) -> IncomingRequests<'a> {
        IncomingRequests { server: self }
    }

    /// Returns the address the server is listening to.
    #[experimental]
    #[inline]
    pub fn get_server_addr(&self) -> ip::SocketAddr {
        self.listening_addr.clone()
    }

    /// Returns the number of clients currently connected to the server.
    #[stable]
    pub fn get_num_connections(&self) -> uint {
        unimplemented!()
        //self.requests_receiver.lock().len()
    }

    /// Blocks until an HTTP request has been submitted and returns it.
    #[stable]
    pub fn recv(&self) -> IoResult<Request> {
        let connections_receiver = self.connections_receiver.lock();
        let requests_receiver = self.requests_receiver.lock();

        // TODO: the select! macro doesn't seem to be usable without moving
        //       out of self, so we use Select directly

        let select = Select::new();

        let mut request_handle = select.handle(&*requests_receiver);
        unsafe { request_handle.add() };

        let mut connect_handle = select.handle(&*connections_receiver);
        unsafe { connect_handle.add() };

        loop {
            let id = select.wait();

            if id == request_handle.id() {
                let request = request_handle.recv();

                unsafe { request_handle.remove() };
                unsafe { connect_handle.remove() };

                return Ok(request)
            }

            if id == connect_handle.id() {
                let client = connect_handle.recv_opt();

                match client {
                    Ok(Ok(client)) => {
                        self.add_client(client);
                        continue
                    },
                    Ok(Err(err)) => {
                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(err)
                    },
                    Err(_) => {
                        use std::io;

                        unsafe { request_handle.remove() };
                        unsafe { connect_handle.remove() };

                        return Err(io::standard_error(io::Closed));
                    }
                }
            }

            unreachable!()
        }
    }

    /// Same as `recv()` but doesn't block.
    #[stable]
    pub fn try_recv(&self) -> IoResult<Option<Request>> {
        let mut connections_receiver = self.connections_receiver.lock();
        let mut requests_receiver = self.requests_receiver.lock();

        // processing all new clients
        loop {
            match connections_receiver.try_recv() {
                Ok(client) => self.add_client(try!(client)),
                Err(_) => break
            }
        }

        // reading the next request
        Ok(requests_receiver.try_recv().ok())
    }

    /// Adds a new client to the list.
    fn add_client(&self, client: ClientConnection) {
        let requests_sender = self.requests_sender.lock().clone();

        self.tasks_pool.spawn(proc() {
            let mut client = client;

            for rq in client {
                let res = requests_sender.send_opt(rq);
                if res.is_err() {
                    break
                }
            }
        });
    }
}

impl<'a> Iterator<Request> for IncomingRequests<'a> {
    fn next(&mut self) -> Option<Request> {
        self.server.recv().ok()
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        use std::sync::atomics::Relaxed;
        self.close.store(true, Relaxed);
    }
}
<|endoftext|>