1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Provides an implementation of a WebSocket server
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;

/// Represents a WebSocket server which can work with either normal (non-secure) connections, or secure WebSocket connections.
///
/// This is a convenient way to implement WebSocket servers, however it is possible to use any sendable Reader and Writer to obtain
/// a WebSocketClient, so if needed, an alternative server implementation can be used.
///#Non-secure Servers
///
/// ```no_run
///extern crate websocket;
///# fn main() {
///use std::thread;
///use websocket::{Server, Message};
///
///let server = Server::bind("127.0.0.1:1234").unwrap();
///
///for connection in server {
///    // Spawn a new thread for each connection.
///    thread::spawn(move || {
///		   let request = connection.unwrap().read_request().unwrap(); // Get the request
///		   let response = request.accept(); // Form a response
///		   let mut client = response.send().unwrap(); // Send the response
///
///		   let message = Message::text("Hello, client!");
///		   let _ = client.send_message(&message);
///
///		   // ...
///    });
///}
/// # }
/// ```
///
///#Secure Servers
/// ```no_run
///extern crate websocket;
///extern crate openssl;
///# fn main() {
///use std::thread;
///use std::path::Path;
///use websocket::{Server, Message};
///use openssl::ssl::{SslContext, SslMethod};
///use openssl::x509::X509FileType;
///
///let mut context = SslContext::new(SslMethod::Tlsv1).unwrap();
///let _ = context.set_certificate_file(&(Path::new("cert.pem")), X509FileType::PEM);
///let _ = context.set_private_key_file(&(Path::new("key.pem")), X509FileType::PEM);
///let server = Server::bind_secure("127.0.0.1:1234", &context).unwrap();
///
///for connection in server {
///    // Spawn a new thread for each connection.
///    thread::spawn(move || {
///		   let request = connection.unwrap().read_request().unwrap(); // Get the request
///		   let response = request.accept(); // Form a response
///		   let mut client = response.send().unwrap(); // Send the response
///
///		   let message = Message::text("Hello, client!");
///		   let _ = client.send_message(&message);
///
///		   // ...
///    });
///}
/// # }
/// ```
pub struct Server<'a> {
	inner: TcpListener,
	context: Option<&'a SslContext>,
}

impl<'a> Server<'a> {
	/// Bind this Server to this socket
	pub fn bind<T: ToSocketAddrs>(addr: T) -> io::Result<Server<'a>> {
		Ok(Server {
			inner: try!(TcpListener::bind(&addr)),
			context: None,
		})
	}
	/// Bind this Server to this socket, utilising the given SslContext
	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),
		})
	}
	/// Get the socket address of this server
	pub fn local_addr(&self) -> io::Result<SocketAddr> {
		self.inner.local_addr()
	}

	/// Create a new independently owned handle to the underlying socket.
	pub fn try_clone(&self) -> io::Result<Server<'a>> {
		let inner = try!(self.inner.try_clone());
		Ok(Server {
			inner: inner,
			context: self.context
		})
	}

	/// Wait for and accept an incoming WebSocket connection, returning a WebSocketRequest
	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())
	}
}

/// Represents a connection to the server that has not been processed yet.
pub struct Connection<R: Read, W: Write>(R, W);

impl<R: Read, W: Write> Connection<R, W> {
	/// Process this connection and read the request.
	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> {
    /// Shuts down the currennt connection in the specified way.
    /// All future IO calls to this connection will return immediately with an appropriate
    /// return value.
    pub fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
        self.0.shutdown(how)
    }
}