#async #foreign-interface #http #web

websocket-std

Websocket implementation using std support, focus on microcontrollers and interoperability with other languages like C through the ffi

4 releases

0.0.6 Feb 15, 2024
0.0.5 Feb 15, 2024
0.0.2 May 10, 2023

#463 in Embedded development

MIT license

77KB
1.5K SLoC

websocket-std

This is a WebSocket implementation in Rust that utilizes the standard library. Its goal is to function on low-resource devices such as microcontrollers, although it can also be applied in high-performance computer programs. I started the project for three main reasons:

  • Learn rust.
  • Publish a library in crates.io.
  • How to use the library from other languages.

The project is currently in beta phase, and while it is functional, further work is needed for the final version. Since I am a sole developer and cannot dedicate as much time as I would like, I have decided to publish it for those who want to try it out and contribute to the project CONTRIBUTING.md.

You can use the library in the following ways:

  • In any Rust project that allows the use of the standard library, such as esp-rs with std support. Check out the esp-rs docs for more information.
  • In any C project, as it has a compatible FFI (Foreign Function Interface). You’ll need to compile the project as a static library and link it appropriately. Refer to this guide (static lib usage) for more details.

Feel free to explore the project and contribute! 🚀


Static library

In the ffi/ folder you will find the websocket-std.h header and a compiled static library for the xtensa architecture of the esp32 microcontroller from espressif.

You can use this static library in your esp idf and arduino projects for esp32. Check ffi/xtensa-esp32-idf for more information.

Examples

The examples folder contains various examples of how to use websocket-std.

Features

Sync Client

The sync client manage an internal event loop, when you call a function to perform a websocket operation (init, send, ...) it will be queued and as soon as you call the event_loop function it will perform one input (something was received) and one output (something to send to server) operations in one execution.

You can also use threads to work with the library. Check examples for more information.

What works

  • Send text messages.
  • Handle received text messages.
  • Handle on connection events.
  • Handle on close events.
  • Work with websocket protocols.
  • Set the maximun length of the text that the websocket will send for each dataframe.

Comming

  • Websocket over SSL.
  • Send and receive binary data.
  • Websocket extensions.

Sync Server

I'm planning also to introduce in the library a sync server following the same philosophy as the sync client.


MCUs Tested

  • ESP32 using esp-rs with std support
  • ESP32 using arduino framework in a PlatformIO project. (Should also work with esp-idf proyects).

Test

Since is my first rust big project I started using the following tools for testing and code coveragera, but I would like to define another way of doing that because the test coverage reports are not the bests. I'm open to hear better ways of doing testing in rust.

Execute all test

cargo test

Generate coverage report

Requirements

Install grcov tool

  1. Install the llvm-tools or llvm-tools-preview component
rustup component add llvm-tools-preview
  1. Ensure that the following environment variable is set up
export RUSTFLAGS="-Cinstrument-coverage"
  1. Ensure each test runs gets its own profile information by defining the LLVM_PROFILE_FILE environment variable (%p will be replaced by the process ID, and %m by the binary signature)
export LLVM_PROFILE_FILE="websocket-std-%p-%m.profraw"
  1. Install grcov
cargo install grcov

Generate report

Ensure that there isn't compilation or test errors.

  1. Build the code
cargo build
  1. Run tests and ensure that all are OK
cargo test
  1. Be sure that the variables are exported.
  • RUSTFLAGS
  • LLVM_PROFILE_FILE
  1. Generate coverage report as HTML
grcov . --binary-path ./target/debug/deps/ -s . -t html --branch --ignore-not-existing --ignore '../*' --ignore "/*" -o target/coverage --excl-line grcov-excl-line

The report will be generated at target/coverage/, open index.html with a browser to see the results.


Python websocket server

Since the library doesn't have a way to create websocket servers, here you will find an echo server example in python to test the client.

Requirements

  • pip install websockets==11.0.3

Code

import asyncio
from websockets.server import serve

HOST  = "0.0.0.0"
PORT  = 3000
protocol = ["superchat", "app", "chat"]

async def echo(websocket):
    async for message in websocket:
        if websocket.open:
            await websocket.send(message)

async def main():
    async with serve(echo, HOST, PORT, subprotocols=protocol):
        print(f"Websocket server running on: {HOST}:{PORT}")
        await asyncio.Future()  # run forever

asyncio.run(main())

Dependencies

~500–730KB
~13K SLoC