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

~~~rust extern crate websocket_stream as wss;

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

fn somefunction() { // stream is some std::net::TcpStream let mut wsstream = 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
    }
}

} ~~~