websocket-stream 0.0.4

Non-blocking Websocket (RFC-6455) wrapper for TcpStream
docs.rs failed to build websocket-stream-0.0.4
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: websocket-stream-0.0.5

websocket-stream

websocket-stream is a RFC-6455 wrapper for TcpStream on POSIX-like kernels. It can be used in blocking or non-blocking mode.

I don't do enough Windows development to care about ensuring it is platform agnostic. Feel free to send me a pull request if you want to take the time to implement Windows sockets as well.

It achieves it's non-blocking state by setting the O_NONBLOCK flag on the stream's file descriptor.

Why another Websocket Thing in Rust?

There are a lot of Websocket libraries out for Rust right now, but they all force the same model of server design on the library user. Most implement Websockets by creating a thread for each connection to read, and one to write. Mainly to overcome Rust's blocking as default IO implementation. This is wonderful, unless your server is expected to handle lots of concurrent connections for long periods of time. Context switching between 200k threads will absolutely kill any gains you get by having separate read and write operations. So, I wrote this thing.

Example Usage

extern crate websocket_stream as wss;

use wss::{WebsocketStream, ReadResult, WriteResult, Mode};
use wss::util::{OpCode, ReadError, WriteError};

fn some_function() {
    // stream is some std::net::TcpStream
    let mut ws_stream = match WebsocketStream::new(stream, Mode::NonBlock) {
        Ok(ws) => ws,
        Err(e) => {
            // This arm is hit when the system does not support 0_NONBLOCK
            panic!("Websocket creation failed, errno: {}", e)
        }
    };

    // Read a thing
    match ws_stream.read() {
        Ok(res_tuple) => {
            match res_tuple.0 {
                OpCode::Continuation    => handle_cont(res_tuple.1),
                OpCode::Text            => handle_text(res_tuple.1),
                OpCode::Binary          => handle_binary(res_tuple.1),
                OpCode::Close           => handle_close(res_tuple.1),
                OpCode::Ping            => handle_ping(res_tuple.1),
                OpCode::Pong            => handle_pong(res_tuple.1)
            }
        }
        Err(e) => {
            match e {
                ReadError::EAGAIN => {
                    // This arm is hit in Mode::NonBlock
                    // Signifies there was no data to read
                }
                _ => {
                    // This arm is hit on syscall level errors.
                    // ReadError can be printed for details
                }
            }
        }
    }

    // Write a thing
    let mut buf: Vec<u8> = Vec::new(); // Buffer full of awesome
    match ws_stream.write(OpCode::Text, &mut buf) {
        Ok(num_written) => {
            // Obv, num_written is the amount of bytes written
        }
        Err(e) => {
            // This arm is hit on syscall level errors.
            // WriteError can be printed for details
        }
    }
}