use std::net::{SocketAddr, ToSocketAddrs, TcpListener};
use std::net::Shutdown;
use std::io::{Read, Write};
use std::io;
pub use self::request::Request;
pub use self::response::Response;
use stream::WebSocketStream;
use openssl::ssl::SslContext;
use openssl::ssl::SslStream;
pub mod request;
pub mod response;
pub struct Server<'a> {
inner: TcpListener,
context: Option<&'a SslContext>,
}
impl<'a> Server<'a> {
pub fn bind<T: ToSocketAddrs>(addr: T) -> io::Result<Server<'a>> {
Ok(Server {
inner: try!(TcpListener::bind(&addr)),
context: None,
})
}
pub fn bind_secure<T: ToSocketAddrs>(addr: T, context: &'a SslContext) -> io::Result<Server<'a>> {
Ok(Server {
inner: try!(TcpListener::bind(&addr)),
context: Some(context),
})
}
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.inner.local_addr()
}
pub fn try_clone(&self) -> io::Result<Server<'a>> {
let inner = try!(self.inner.try_clone());
Ok(Server {
inner: inner,
context: self.context
})
}
pub fn accept(&mut self) -> io::Result<Connection<WebSocketStream, WebSocketStream>> {
let stream = try!(self.inner.accept()).0;
let wsstream = match self.context {
Some(context) => {
let sslstream = match SslStream::accept(context, stream) {
Ok(s) => s,
Err(err) => {
return Err(io::Error::new(io::ErrorKind::Other, err));
}
};
WebSocketStream::Ssl(sslstream)
}
None => { WebSocketStream::Tcp(stream) }
};
Ok(Connection(try!(wsstream.try_clone()), try!(wsstream.try_clone())))
}
}
impl<'a> Iterator for Server<'a> {
type Item = io::Result<Connection<WebSocketStream, WebSocketStream>>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
Some(self.accept())
}
}
pub struct Connection<R: Read, W: Write>(R, W);
impl<R: Read, W: Write> Connection<R, W> {
pub fn read_request(self) -> io::Result<Request<R, W>> {
match Request::read(self.0, self.1) {
Ok(result) => { Ok(result) },
Err(err) => {
Err(io::Error::new(io::ErrorKind::InvalidInput, err))
}
}
}
}
impl Connection<WebSocketStream, WebSocketStream> {
pub fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
self.0.shutdown(how)
}
}