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) } }