Module unified_async_client

Module unified_async_client 

Source
Expand description

Unified async client with optional TLS and reconnection

This module provides UnifiedAsyncClient, a single async client type that elegantly handles all feature combinations (TLS, reconnection) through internal state management.

§Design Philosophy

Traditional approach would create separate types for each feature combination:

  • TcpAsync, TcpAsyncTls, TcpAsyncReconnect, TcpAsyncTlsReconnect
  • This leads to variant explosion: 2 features = 4 types, 3 features = 8 types, etc.

Our approach: Single UnifiedAsyncClient with optional features:

  • Internal Transport enum: Plain(TcpStream) or Tls(TlsStream)
  • Optional reconnect_config: Option<ReconnectConfig>
  • ✅ Scales linearly with features (not exponentially!)
  • ✅ Easy to add new features (compression, authentication, etc.)
  • ✅ Maintains type safety through builder pattern

§Architecture

UnifiedAsyncClient
├─ transport: Option<Transport>
│  ├─ Plain(TcpStream)     ← Regular TCP
│  └─ Tls(TlsStream)       ← TLS-encrypted TCP
├─ reconnect_config: Option<ReconnectConfig>
│  ├─ None                 ← No auto-reconnection
│  └─ Some(config)         ← Auto-reconnect with backoff
├─ conn_params: ConnectionParams (host, port, TLS config)
└─ verify_crc: bool        ← CRC verification

§Examples

§Plain TCP Connection

use openigtlink_rust::io::unified_async_client::UnifiedAsyncClient;

let client = UnifiedAsyncClient::connect("127.0.0.1:18944").await?;

§TLS-Encrypted Connection

use openigtlink_rust::io::unified_async_client::UnifiedAsyncClient;
use std::sync::Arc;

let tls_config = rustls::ClientConfig::builder()
    .with_root_certificates(rustls::RootCertStore::empty())
    .with_no_client_auth();

let client = UnifiedAsyncClient::connect_with_tls(
    "hospital-server.local",
    18944,
    Arc::new(tls_config)
).await?;

§With Auto-Reconnection

use openigtlink_rust::io::unified_async_client::UnifiedAsyncClient;
use openigtlink_rust::io::reconnect::ReconnectConfig;

let mut client = UnifiedAsyncClient::connect("127.0.0.1:18944").await?;

// Enable auto-reconnection
let reconnect_config = ReconnectConfig::with_max_attempts(10);
client = client.with_reconnect(reconnect_config);

§TLS + Auto-Reconnect (Previously Impossible!)

use openigtlink_rust::io::unified_async_client::UnifiedAsyncClient;
use openigtlink_rust::io::reconnect::ReconnectConfig;
use std::sync::Arc;

let tls_config = rustls::ClientConfig::builder()
    .with_root_certificates(rustls::RootCertStore::empty())
    .with_no_client_auth();

let mut client = UnifiedAsyncClient::connect_with_tls(
    "production-server",
    18944,
    Arc::new(tls_config)
).await?;

// Add auto-reconnection to TLS client
let reconnect_config = ReconnectConfig::with_max_attempts(100);
client = client.with_reconnect(reconnect_config);

§Prefer Using the Builder

While you can create UnifiedAsyncClient directly, it’s recommended to use ClientBuilder for better ergonomics and type safety:

use openigtlink_rust::io::builder::ClientBuilder;
use openigtlink_rust::io::reconnect::ReconnectConfig;
use std::sync::Arc;

let tls_config = rustls::ClientConfig::builder()
    .with_root_certificates(rustls::RootCertStore::empty())
    .with_no_client_auth();

let client = ClientBuilder::new()
    .tcp("production-server:18944")
    .async_mode()
    .with_tls(Arc::new(tls_config))
    .with_reconnect(ReconnectConfig::with_max_attempts(100))
    .verify_crc(true)
    .build()
    .await?;

Structs§

UnifiedAsyncClient
Unified async OpenIGTLink client