12 unstable releases (3 breaking)

0.4.2 Sep 1, 2020
0.4.1 Jun 17, 2020
0.3.2 Jan 22, 2020
0.3.1 Dec 30, 2019
0.1.0 Jun 5, 2019

#3 in WebSocket

Download history 6735/week @ 2020-06-06 6726/week @ 2020-06-13 7125/week @ 2020-06-20 7760/week @ 2020-06-27 8121/week @ 2020-07-04 7255/week @ 2020-07-11 8680/week @ 2020-07-18 9398/week @ 2020-07-25 9161/week @ 2020-08-01 8228/week @ 2020-08-08 8659/week @ 2020-08-15 8145/week @ 2020-08-22 6589/week @ 2020-08-29 8210/week @ 2020-09-05 9053/week @ 2020-09-12 8700/week @ 2020-09-19

35,638 downloads per month
Used in 54 crates (4 directly)

Apache-2.0 OR MIT

105KB
2K SLoC

Soketto

An implementation of the RFC 6455 websocket protocol. This crate is a heavily modified fork of the twist crate.


lib.rs:

An implementation of the RFC 6455 websocket protocol.

To begin a websocket connection one first needs to perform a handshake, either as client or server, in order to upgrade from HTTP. Once successful, the client or server can transition to a connection, i.e. a Sender/Receiver pair and send and receive textual or binary data.

Note: While it is possible to only receive websocket messages it is not possible to only send websocket messages. Receiving data is required in order to react to control frames such as PING or CLOSE. While those will be answered transparently they have to be received in the first place, so calling [connection::Receiver::receive] is imperative.

Note: None of the async methods are safe to cancel so their Futures must not be dropped unless they return Poll::Ready.

Client example

# use tokio_util::compat::Tokio02AsyncReadCompatExt;
# async fn doc() -> Result<(), soketto::BoxedError> {
use soketto::handshake::{Client, ServerResponse};

// First, we need to establish a TCP connection.
let socket = tokio::net::TcpStream::connect("...").await?;

// Then we configure the client handshake.
let mut client = Client::new(socket.compat(), "...", "/");

// And finally we perform the handshake and handle the result.
let (mut sender, mut receiver) = match client.handshake().await? {
    ServerResponse::Accepted { .. } => client.into_builder().finish(),
    ServerResponse::Redirect { status_code, location } => unimplemented!("follow location URL"),
    ServerResponse::Rejected { status_code } => unimplemented!("handle failure")
};

// Over the established websocket connection we can send
sender.send_text("some text").await?;
sender.send_text("some more text").await?;
sender.flush().await?;

// ... and receive data.
let mut data = Vec::new();
receiver.receive_data(&mut data).await?;

# Ok(())
# }

Server example

# use tokio_util::compat::Tokio02AsyncReadCompatExt;
# use tokio::stream::StreamExt;
# async fn doc() -> Result<(), soketto::BoxedError> {
use soketto::{handshake::{Server, ClientRequest, server::Response}};

// First, we listen for incoming connections.
let mut listener = tokio::net::TcpListener::bind("...").await?;
let mut incoming = listener.incoming();

while let Some(socket) = incoming.next().await {
    // For each incoming connection we perform a handshake.
    let mut server = Server::new(socket?.compat());

    let websocket_key = {
        let req = server.receive_request().await?;
        req.into_key()
    };

    // Here we accept the client unconditionally.
    let accept = Response::Accept { key: &websocket_key, protocol: None };
    server.send_response(&accept).await?;

    // And we can finally transition to a websocket connection.
    let (mut sender, mut receiver) = server.into_builder().finish();

    let mut data = Vec::new();
    let data_type = receiver.receive_data(&mut data).await?;

    if data_type.is_text() {
        sender.send_text(std::str::from_utf8(&data)?).await?
    } else {
        sender.send_binary(&data).await?
    }

    sender.close().await?
}

# Ok(())
# }

Dependencies

~2.1–3.5MB
~68K SLoC