Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add some documentation to WebSocket and Error. #79

Merged
merged 2 commits into from
Sep 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,39 @@ pub type Result<T> = result::Result<T, Error>;
/// Possible WebSocket errors
#[derive(Debug)]
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
/// to close the connection.
/// The client gets this error if the connection is already closed at the server side.
/// This is returned as soon as the close handshake is finished (we have both sent and
/// received a close frame) on the server end and as soon as the server has closed the
/// underlying connection if this endpoint is a client.
///
/// Receiving this error means that the WebSocket object is not usable anymore and the only
/// meaningful action with it is dropping it.
/// Thus when you receive this, it is safe to drop the underlying connection.
///
/// Receiving this error means that the WebSocket object is not usable anymore and the
/// only meaningful action with it is dropping it.
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
/// `Error::ConnectionClosed` causes this.
/// As opposed to `ConnectionClosed`, this indicates your code tries to operate on the
/// connection when it really shouldn't anymore, so this really indicates a programmer
/// error on your part.
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),
#[cfg(feature = "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>),
/// Protocol violation
/// Protocol violation.
Protocol(Cow<'static, str>),
/// Message send queue full
/// Message send queue full.
SendQueueFull(Message),
/// UTF coding error
Utf8,
Expand Down
59 changes: 52 additions & 7 deletions src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,49 @@ impl<Stream> WebSocket<Stream> {
impl<Stream: Read + Write> WebSocket<Stream> {
/// Read a message from stream, if possible.
///
/// This function sends pong and close responses automatically.
/// However, it never blocks on write.
/// This will queue responses to ping and close messages to be sent. It will call
/// `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> {
self.context.read_message(&mut self.socket)
}

/// Send a message to stream, if possible.
///
/// 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
/// along with the passed message. Otherwise, the message is queued and Ok(()) is returned.
/// requests. A Pong reply will jump the queue because the
/// [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
/// most recent pong frame is sent if multiple pong frames are queued.
/// Note that upon receiving a ping message, tungstenite cues a pong reply automatically.
/// 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<()> {
self.context.write_message(&mut self.socket, message)
}
Expand All @@ -142,7 +171,23 @@ impl<Stream: Read + Write> WebSocket<Stream> {
///
/// This function guarantees that the close frame will be queued.
/// 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<()> {
self.context.close(&mut self.socket, code)
}
Expand Down