Add some documentation to WebSocket and Error.

pull/79/head
Naja Melan 5 years ago
parent fc41b598ce
commit f818322a25
  1. 36
      src/error.rs
  2. 59
      src/protocol/mod.rs

@ -25,30 +25,40 @@ pub type Result<T> = result::Result<T, Error>;
/// Possible WebSocket errors /// Possible WebSocket errors
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
/// WebSocket connection closed normally /// WebSocket connection closed normally. This informs you of the close.
/// It's not an error as such and nothing wrong happened.
/// ///
/// Upon receiving this, the server must drop the WebSocket object as soon as possible /// This is returned as soon as the close handshake is finished (we have both sent and
/// to close the connection. /// received a close frame) on the server end and as soon as the server has closed the
/// The client gets this error if the connection is already closed at the server side. /// underlying connection if this endpoint is a client.
/// ///
/// Receiving this error means that the WebSocket object is not usable anymore and the only /// Thus when you receive this, it is safe to drop the underlying connection.
/// meaningful action with it is dropping it. ///
/// Receiving this error means that the WebSocket object is not usable anymore and the
/// only meaningful action with it is dropping it.
ConnectionClosed, ConnectionClosed,
/// Trying to work with already closed connection /// Trying to work with already closed connection.
///
/// Trying to read or write after receiving `ConnectionClosed` causes this.
/// ///
/// Trying to write after receiving `Message::Close` or trying to read after receiving /// As opposed to `ConnectionClosed`, this indicates your code tries to operate on the
/// `Error::ConnectionClosed` causes this. /// connection when it really shouldn't anymore, so this really indicates a programmer
/// error on your part.
AlreadyClosed, AlreadyClosed,
/// Input-output error /// Input-output error. Appart from WouldBlock, these are generally errors with the
/// underlying connection and you should probably consider them fatal.
Io(io::Error), Io(io::Error),
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
/// TLS error /// TLS error
Tls(tls::Error), Tls(tls::Error),
/// Buffer capacity exhausted /// - When reading: buffer capacity exhausted.
/// - When writing: your message is bigger than the configured max message size
/// (64MB by default).
Capacity(Cow<'static, str>), Capacity(Cow<'static, str>),
/// Protocol violation /// Protocol violation. Only returned from reads, if the remote caused a protocol
/// violation. Messages you send are currently not checked for protocol validity.
Protocol(Cow<'static, str>), Protocol(Cow<'static, str>),
/// Message send queue full /// Message send queue full.
SendQueueFull(Message), SendQueueFull(Message),
/// UTF coding error /// UTF coding error
Utf8, Utf8,

@ -115,8 +115,18 @@ impl<Stream> WebSocket<Stream> {
impl<Stream: Read + Write> WebSocket<Stream> { impl<Stream: Read + Write> WebSocket<Stream> {
/// Read a message from stream, if possible. /// Read a message from stream, if possible.
/// ///
/// This function sends pong and close responses automatically. /// This will queue responses to ping and close messages to be sent. It will call
/// However, it never blocks on write. /// `write_pending` before trying to read in order to make sure that those responses
/// make progress even if you never call `write_pending`. That does mean that they
/// get sent out earliest on the next call to `read_message`, `write_message` or `write_pending`.
///
/// ## Closing the connection
/// When the remote endpoint decides to close the connection this will return
/// the close message with an optional close frame.
///
/// You should continue calling `read_message`, `write_message` or `write_pending` to drive
/// the reply to the close frame until [Error::ConnectionClosed] is returned. Once that happens
/// it is safe to drop the underlying connection.
pub fn read_message(&mut self) -> Result<Message> { pub fn read_message(&mut self) -> Result<Message> {
self.context.read_message(&mut self.socket) self.context.read_message(&mut self.socket)
} }
@ -124,11 +134,30 @@ impl<Stream: Read + Write> WebSocket<Stream> {
/// Send a message to stream, if possible. /// Send a message to stream, if possible.
/// ///
/// WebSocket will buffer a configurable number of messages at a time, except to reply to Ping /// WebSocket will buffer a configurable number of messages at a time, except to reply to Ping
/// and Close requests. If the WebSocket's send queue is full, `SendQueueFull` will be returned /// requests. A Pong reply will jump the queue because the
/// along with the passed message. Otherwise, the message is queued and Ok(()) is returned. /// [websocket RFC](https://tools.ietf.org/html/rfc6455#section-5.5.2) specifies it should be sent
/// as soon as is practical.
/// ///
/// Note that only the last pong frame is stored to be sent, and only the /// Note that upon receiving a ping message, tungstenite cues a pong reply automatically.
/// most recent pong frame is sent if multiple pong frames are queued. /// When you call either `read_message`, `write_message` or `write_pending` next it will try to send
/// that pong out if the underlying connection can take more data. This means you should not
/// respond to ping frames manually.
///
/// You can however send pong frames manually in order to indicate a unidirectional heartbeat
/// as described in [RFC 6455](https://tools.ietf.org/html/rfc6455#section-5.5.3). Note that
/// if `read_message` returns a ping, you should call `write_pending` until it doesn't return
/// WouldBlock before passing a pong to `write_message`, otherwise the response to the
/// ping will not be sent, but rather replaced by your custom pong message.
///
/// ## Errors
/// - If the WebSocket's send queue is full, `SendQueueFull` will be returned
/// along with the passed message. Otherwise, the message is queued and Ok(()) is returned.
/// - If the connection is closed and should be dropped, this will return [Error::ConnectionClosed].
/// - If you try again after [Error::ConnectionClosed] was returned either from here or from `read_message`,
/// [Error::AlreadyClosed] will be returned. This indicates a program error on your part.
/// - [Error::Io] is returned if the underlying connection returns an error
/// (consider these fatal except for WouldBlock).
/// - [Error::Capacity] if your message size is bigger than the configured max message size.
pub fn write_message(&mut self, message: Message) -> Result<()> { pub fn write_message(&mut self, message: Message) -> Result<()> {
self.context.write_message(&mut self.socket, message) self.context.write_message(&mut self.socket, message)
} }
@ -142,7 +171,23 @@ impl<Stream: Read + Write> WebSocket<Stream> {
/// ///
/// This function guarantees that the close frame will be queued. /// This function guarantees that the close frame will be queued.
/// There is no need to call it again. Calling this function is /// There is no need to call it again. Calling this function is
/// the same as calling `write(Message::Close(..))`. /// the same as calling `write_message(Message::Close(..))`.
///
/// After queing the close frame you should continue calling `read_message` or
/// `write_pending` to drive the close handshake to completion.
///
/// The websocket RFC defines that the underlying connection should be closed
/// by the server. Tungstenite takes care of this asymmetry for you.
///
/// When the close handshake is finished (we have both sent and received
/// a close message), `read_message` or `write_pending` will return
/// [Error::ConnectionClosed] if this endpoint is the server.
///
/// If this endpoint is a client, [Error::ConnectionClosed] will only be
/// returned after the server has closed the underlying connection.
///
/// It is thus safe to drop the underlying connection as soon as [Error::ConnectionClosed]
/// is returned from `read_message` or `write_pending`.
pub fn close(&mut self, code: Option<CloseFrame>) -> Result<()> { pub fn close(&mut self, code: Option<CloseFrame>) -> Result<()> {
self.context.close(&mut self.socket, code) self.context.close(&mut self.socket, code)
} }

Loading…
Cancel
Save