gel-stream

Crates.iogel-stream
lib.rsgel-stream
version0.4.5
created_at2025-02-20 18:42:12.901865+00
updated_at2025-06-24 14:30:30.64016+00
descriptionA library for streaming data between clients and servers.
homepage
repository
max_upload_size
id1562970
size322,780
EdgeDB CI and Release Bot (edgedb-ci)

documentation

README

gel-stream

This crate provides a runtime and TLS agnostic client and server stream API for services requiring TCP/Unix socket, plaintext, TLS, and STARTTLS connections.

The crate may be used with either an OpenSSL or Rustls TLS implementation without changing the API.

Features

  • full: Enable all features (not recommended).
  • openssl: Enable OpenSSL support.
  • rustls: Enable Rustls support.
  • tokio: Enable Tokio support (default).
  • hickory: Enable Hickory support.
  • keepalive: Enable keepalive support.
  • serde: Enable serde serialization support for most types.
  • pem: Enable PEM support for TLS parameters.

TLS

TLS is supported via the openssl or rustls features. Regardless of which TLS library is used, the API is the same.

Usage

The crate provides a Target and Connector for clients and a Acceptor for servers.

Examples

Creating and connecting to a TCP server:

use gel_stream::*;
use std::net::*;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use futures::TryStreamExt;

#[tokio::main]
async fn run() -> Result<(), Box<dyn std::error::Error>> {
    // Create a server that listens on all interfaces on a random port.
    let acceptor = Acceptor::new_tcp(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0));
    let mut server = acceptor.bind().await?;
    let addr = server.local_address()?;

    /// When creating servers, clients and servers should be run in separate tasks.
    let task1 = tokio::spawn(async move {
        let mut server_conn = server.try_next().await?.expect("Didn't get a connection");
        server_conn.write_all(b"Hello, world!").await?;
        std::io::Result::Ok(())
    });

    let task2 = tokio::spawn(async move {
        let mut client_conn = Connector::new(Target::new_resolved(addr))?.connect().await?;
        let mut buffer = String::new();
        client_conn.read_to_string(&mut buffer).await?;
        assert_eq!(buffer, "Hello, world!");
        std::io::Result::Ok(())
    });

    task1.await??;
    task2.await??;

    Ok(())
}

# run().expect("failed to run example!");

Creating a TLS server with a given key and certificate, and connecting to it:

use gel_stream::*;
use std::net::*;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use futures::TryStreamExt;

#[tokio::main]
async fn run() -> Result<(), Box<dyn std::error::Error>> {
    // Create a server that listens on all interfaces on a random port.
    let tls_params = TlsServerParameters::new_with_certificate(
        gel_stream::test_keys::SERVER_KEY.clone_key()
    );
    let acceptor = Acceptor::new_tcp_tls(
        SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0),
        TlsServerParameterProvider::new(tls_params),
    );
    let mut server = acceptor.bind().await?;
    let addr = server.local_address()?;

    /// When creating servers, clients and servers should be run in separate tasks.
    let task1 = tokio::spawn(async move {
        let mut server_conn = server.try_next().await?.expect("Didn't get a connection");
        server_conn.write_all(b"Hello, world!").await?;
        std::io::Result::Ok(())
    });

    let task2 = tokio::spawn(async move {
        let mut client_conn = Connector::new(Target::new_resolved_tls(addr, TlsParameters::insecure()))?.connect().await?;
        let mut buffer = String::new();
        client_conn.read_to_string(&mut buffer).await?;
        assert_eq!(buffer, "Hello, world!");
        std::io::Result::Ok(())
    });

    task1.await??;
    task2.await??;

    Ok(())
}

# run().expect("failed to run example!");
Commit count: 0

cargo fmt