Skip to content

Commit

Permalink
Merge pull request #479 from mikedilger/ssl_context
Browse files Browse the repository at this point in the history
Ssl context
  • Loading branch information
seanmonstar committed Apr 27, 2015
2 parents caa2e5a + 3a1a242 commit f7f0361
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 17 deletions.
5 changes: 5 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ impl HttpListener {
try!(ssl_context.set_certificate_file(cert, X509FileType::PEM).map_err(lift_ssl_error));
try!(ssl_context.set_private_key_file(key, X509FileType::PEM).map_err(lift_ssl_error));
ssl_context.set_verify(SSL_VERIFY_NONE, None);
HttpListener::https_with_context(addr, ssl_context)
}

/// Start listening to an address of HTTPS using the given SslContext
pub fn https_with_context<To: ToSocketAddrs>(addr: To, ssl_context: SslContext) -> io::Result<HttpListener> {
Ok(HttpListener::Https(try!(TcpListener::bind(addr)), Arc::new(ssl_context)))
}
}
Expand Down
54 changes: 37 additions & 17 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use std::path::Path;
use std::thread::{self, JoinHandle};

use num_cpus;
use openssl::ssl::SslContext;

pub use self::request::Request;
pub use self::response::Response;
Expand All @@ -50,14 +51,20 @@ pub mod response;

mod listener;

#[derive(Debug)]
enum SslConfig<'a> {
CertAndKey(&'a Path, &'a Path),
Context(SslContext),
}

/// A server can listen on a TCP socket.
///
/// Once listening, it will create a `Request`/`Response` pair for each
/// incoming connection, and hand them to the provided handler.
#[derive(Debug)]
pub struct Server<'a, H: Handler, L = HttpListener> {
handler: H,
ssl: Option<(&'a Path, &'a Path)>,
ssl: Option<SslConfig<'a>>,
_marker: PhantomData<L>
}

Expand Down Expand Up @@ -90,7 +97,15 @@ impl<'a, H: Handler + 'static> Server<'a, H, HttpListener> {
pub fn https(handler: H, cert: &'a Path, key: &'a Path) -> Server<'a, H, HttpListener> {
Server {
handler: handler,
ssl: Some((cert, key)),
ssl: Some(SslConfig::CertAndKey(cert, key)),
_marker: PhantomData
}
}
/// Creates a new server that will handler `HttpStreams`s using a TLS connection defined by an SslContext.
pub fn https_with_context(handler: H, ssl_context: SslContext) -> Server<'a, H, HttpListener> {
Server {
handler: handler,
ssl: Some(SslConfig::Context(ssl_context)),
_marker: PhantomData
}
}
Expand All @@ -100,10 +115,11 @@ impl<'a, H: Handler + 'static> Server<'a, H, HttpListener> {
/// Binds to a socket, and starts handling connections using a task pool.
pub fn listen_threads<T: ToSocketAddrs>(self, addr: T, threads: usize) -> HttpResult<Listening> {
let listener = try!(match self.ssl {
Some((cert, key)) => HttpListener::https(addr, cert, key),
Some(SslConfig::CertAndKey(cert, key)) => HttpListener::https(addr, cert, key),
Some(SslConfig::Context(ssl_context)) => HttpListener::https_with_context(addr, ssl_context),
None => HttpListener::http(addr)
});
self.with_listener(listener, threads)
with_listener(self.handler, listener, threads)
}

/// Binds to a socket and starts handling connections.
Expand All @@ -117,23 +133,27 @@ H: Handler + 'static,
L: NetworkListener<Stream=S> + Send + 'static,
S: NetworkStream + Clone + Send> Server<'a, H, L> {
/// Creates a new server that will handle `HttpStream`s.
pub fn with_listener(self, mut listener: L, threads: usize) -> HttpResult<Listening> {
let socket = try!(listener.local_addr());
let handler = self.handler;
pub fn with_listener(self, listener: L, threads: usize) -> HttpResult<Listening> {
with_listener(self.handler, listener, threads)
}
}

debug!("threads = {:?}", threads);
let pool = ListenerPool::new(listener.clone());
let work = move |mut stream| handle_connection(&mut stream, &handler);
fn with_listener<H, L>(handler: H, mut listener: L, threads: usize) -> HttpResult<Listening>
where H: Handler + 'static,
L: NetworkListener + Send + 'static {
let socket = try!(listener.local_addr());

let guard = thread::spawn(move || pool.accept(work, threads));
debug!("threads = {:?}", threads);
let pool = ListenerPool::new(listener.clone());
let work = move |mut stream| handle_connection(&mut stream, &handler);

Ok(Listening {
_guard: Some(guard),
socket: socket,
})
}
}
let guard = thread::spawn(move || pool.accept(work, threads));

Ok(Listening {
_guard: Some(guard),
socket: socket,
})
}

fn handle_connection<'h, S, H>(mut stream: &mut S, handler: &'h H)
where S: NetworkStream + Clone, H: Handler {
Expand Down

0 comments on commit f7f0361

Please sign in to comment.