Expand description

Holochain utilities for websocket serving and connecting.

To establish an outgoing connection, use connect which will return a tuple (WebsocketSender, WebsocketReceiver)

To open a listening socket, use WebsocketListener::bind which will give you a WebsocketListener which is an async Stream whose items resolve to that same tuple ( WebsocketSender, WebsocketReceiver ).

If you want to be able to shutdown the stream use WebsocketListener::bind_with_handle which will give you a tuple (ListenerHandle, ListenerStream). You can use ListenerHandle::close to close immediately or ListenerHandle::close_on to close on a future completing.

Example

use holochain_serialized_bytes::prelude::*;
use holochain_websocket::*;

use std::convert::TryInto;
use tokio_stream::StreamExt;
use url2::prelude::*;

#[derive(serde::Serialize, serde::Deserialize, SerializedBytes, Debug)]
struct TestMessage(pub String);

#[tokio::main]
async fn main() {
    // Create a new server listening for connections
    let mut server = WebsocketListener::bind(
        url2!("ws://127.0.0.1:0"),
        std::sync::Arc::new(WebsocketConfig::default()),
    )
    .await
    .unwrap();

    // Get the address of the server
    let binding = server.local_addr().clone();

    tokio::task::spawn(async move {
        // Handle new connections
        while let Some(Ok((_send, mut recv))) = server.next().await {
            tokio::task::spawn(async move {
                // Receive a message and echo it back
                if let Some((msg, resp)) = recv.next().await {
                    // Deserialize the message
                    let msg: TestMessage = msg.try_into().unwrap();
                    // If this message is a request then we can respond
                    if resp.is_request() {
                        let msg = TestMessage(format!("echo: {}", msg.0));
                        resp.respond(msg.try_into().unwrap()).await.unwrap();
                    }
                }
            });
        }
    });

    // Connect the client to the server
    let (mut send, _recv) = connect(binding, std::sync::Arc::new(WebsocketConfig::default()))
        .await
        .unwrap();

    let msg = TestMessage("test".to_string());
    // Make a request and get the echoed response
    let rsp: TestMessage = send.request(msg).await.unwrap();

    assert_eq!("echo: test", &rsp.0,);
}

Structs

Handle for shutting down a listener stream.

Shuts down the receiver on drop or if you call close.

A builder-style config struct for setting up websockets.

Listens for connecting clients.

Receive signals and requests from a connection.

The sender half of an active connection.

Enums

The response half to a WebsocketMessage. If this message is a request Respond::is_request you can respond with Respond::respond.

The messages actually sent over the wire by this library. If you want to impliment your own server or client you will need this type or be able to serialize / deserialize it.

Functions

Create a new external websocket connection.

Type Definitions

New connection result returned from the ListenerStream.

Stream of new connections.

WebsocketSender and WebsocketReceiver for an active connection.

Closure for responding to a Respond::Request

The SerializedBytes message contents and the Respond from the WebsocketReceiver Stream.