websocket/server/mod.rs
1//! Provides an implementation of a WebSocket server
2#[cfg(any(feature = "sync-ssl", feature = "async-ssl"))]
3use native_tls::TlsAcceptor;
4
5use self::upgrade::{HyperIntoWsError, Request};
6use crate::stream::Stream;
7use std::fmt::{Debug, Formatter, Result as FmtResult};
8
9pub mod upgrade;
10
11#[cfg(feature = "async")]
12pub mod r#async;
13
14#[cfg(feature = "sync")]
15pub mod sync;
16
17/// Marker struct for a struct not being secure
18#[derive(Clone)]
19pub struct NoTlsAcceptor;
20/// Trait that is implemented over NoSslAcceptor and SslAcceptor that
21/// serves as a generic bound to make a struct with.
22/// Used in the Server to specify impls based on whether the server
23/// is running over SSL or not.
24pub trait OptionalTlsAcceptor {}
25impl OptionalTlsAcceptor for NoTlsAcceptor {}
26#[cfg(any(feature = "sync-ssl", feature = "async-ssl"))]
27impl OptionalTlsAcceptor for TlsAcceptor {}
28
29/// When a sever tries to accept a connection many things can go wrong.
30///
31/// This struct is all the information that is recovered from a failed
32/// websocket handshake, in case one wants to use the connection for something
33/// else (such as HTTP).
34pub struct InvalidConnection<S, B>
35where
36 S: Stream,
37{
38 /// if the stream was successfully setup it will be included here
39 /// on a failed connection.
40 pub stream: Option<S>,
41 /// the parsed request. **This is a normal HTTP request** meaning you can
42 /// simply run this server and handle both HTTP and Websocket connections.
43 /// If you already have a server you want to use, checkout the
44 /// `server::upgrade` module to integrate this crate with your server.
45 pub parsed: Option<Request>,
46 /// the buffered data that was already taken from the stream
47 pub buffer: Option<B>,
48 /// the cause of the failed websocket connection setup
49 pub error: HyperIntoWsError,
50}
51
52impl<S, B> Debug for InvalidConnection<S, B>
53where
54 S: Stream,
55{
56 fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
57 fmt.debug_struct("InvalidConnection")
58 .field("stream", &String::from("..."))
59 .field("parsed", &String::from("..."))
60 .field("buffer", &String::from("..."))
61 .field("error", &self.error)
62 .finish()
63 }
64}
65
66/// Represents a WebSocket server which can work with either normal
67/// (non-secure) connections, or secure WebSocket connections.
68///
69/// This is a convenient way to implement WebSocket servers, however
70/// it is possible to use any sendable Reader and Writer to obtain
71/// a WebSocketClient, so if needed, an alternative server implementation can be used.
72///
73/// # Synchronous Servers
74/// Synchronous implementations of a websocket server are available below, each method is
75/// documented so the reader knows whether is it synchronous or asynchronous.
76///
77/// To use the synchronous implementation, you must have the `sync` feature enabled
78/// (it is enabled by default).
79/// To use the synchronous SSL implementation, you must have the `sync-ssl` feature enabled
80/// (it is enabled by default).
81///
82/// # Asynchronous Servers
83/// Asynchronous implementations of a websocket server are available below, each method is
84/// documented so the reader knows whether is it synchronous or asynchronous.
85/// Simply look out for the implementation of `Server` whose methods only return `Future`s
86/// (it is also written in the docs if the method is async).
87///
88/// To use the asynchronous implementation, you must have the `async` feature enabled
89/// (it is enabled by default).
90/// To use the asynchronous SSL implementation, you must have the `async-ssl` feature enabled
91/// (it is enabled by default).
92///
93/// # A Hyper Server
94/// This crates comes with hyper integration out of the box, you can create a hyper
95/// server and serve websocket and HTTP **on the same port!**
96/// check out the docs over at `websocket::server::upgrade::sync::HyperRequest` for an example.
97///
98/// # A Custom Server
99/// So you don't want to use any of our server implementations? That's O.K.
100/// All it takes is implementing the `IntoWs` trait for your server's streams,
101/// then calling `.into_ws()` on them.
102/// check out the docs over at `websocket::server::upgrade::sync` for more.
103#[cfg(any(feature = "sync", feature = "async"))]
104pub struct WsServer<S, L>
105where
106 S: OptionalTlsAcceptor,
107{
108 listener: L,
109 /// The SSL acceptor given to the server
110 pub ssl_acceptor: S,
111}