WASM compatibility update

Related to: Usage as a lib #8

1.  feature gating of TLS and other features not supported with WASM.
2. updated documentation.
3. creation of AI slop WASM example for verification.
This commit is contained in:
2025-09-08 12:28:44 -07:00
parent 06cd6d0c82
commit f59c28d966
13 changed files with 900 additions and 53 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "socktop_connector"
version = "0.1.2"
version = "0.1.3"
edition = "2024"
license = "MIT"
description = "WebSocket connector library for socktop agent communication"
@@ -47,3 +47,4 @@ protoc-bin-vendored = "3.0"
[features]
default = ["tls"]
tls = ["rustls", "rustls-pemfile"]
wasm = [] # WASM-compatible feature set (no TLS)
+19 -43
View File
@@ -32,18 +32,10 @@ Add this to your `Cargo.toml`:
```toml
[dependencies]
socktop_connector = "0.1"
socktop_connector = "0.1.3"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "net", "time", "macros"] }
```
**WASM Compatibility:** For WASM environments, use minimal features (single-threaded runtime):
```toml
[dependencies]
socktop_connector = "0.1"
tokio = { version = "1", features = ["rt", "time", "macros"] }
```
Note: TLS features (`wss://` connections) are not available in WASM environments.
### Basic Usage
```rust
@@ -348,52 +340,36 @@ The library provides flexible configuration through the `ConnectorConfig` builde
**Note**: Hostname verification only applies to TLS connections (`wss://`). Non-TLS connections (`ws://`) don't use certificates, so hostname verification is not applicable.
## WASM Support
## WASM Compatibility
`socktop_connector` supports WebAssembly (WASM) environments with some limitations:
`socktop_connector` provides **types-only support** for WebAssembly (WASM) environments. The core types and configuration work perfectly in WASM, but networking must be handled through browser WebSocket APIs.
### Supported Features
- Non-TLS WebSocket connections (`ws://`)
- All core functionality (metrics, processes, disks)
- Continuous monitoring examples
### Quick Setup
### WASM Configuration
```toml
[dependencies]
socktop_connector = "0.1"
tokio = { version = "1", features = ["rt", "time", "macros"] }
# Note: "net" feature not needed in WASM - WebSocket connections use browser APIs
socktop_connector = { version = "0.1.3", default-features = false }
wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
```
### WASM Limitations
- **No TLS support**: `wss://` connections are not available
- **No certificate pinning**: TLS-related features are disabled
- **Browser WebSocket API**: Uses browser's native WebSocket implementation
### What Works
- ✅ All types (`ConnectorConfig`, `AgentRequest`, `AgentResponse`)
- ✅ JSON serialization/deserialization
- ✅ Protocol and version configuration
### WASM Example
```rust
use socktop_connector::{connect_to_socktop_agent, AgentRequest, AgentResponse};
### What Doesn't Work
- ❌ Direct WebSocket connections (use browser APIs instead)
- ❌ TLS certificate handling
// Use current_thread runtime for WASM compatibility
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut connector = connect_to_socktop_agent("ws://localhost:3000/ws").await?;
match connector.request(AgentRequest::Metrics).await? {
AgentResponse::Metrics(metrics) => {
// In WASM, you might log to browser console instead of println!
web_sys::console::log_1(&format!("CPU: {}%", metrics.cpu_total).into());
}
_ => unreachable!(),
}
Ok(())
}
```
### Complete WASM Guide
For detailed implementation examples, complete code samples, and a working test environment, see the **[WASM Compatibility Guide](../socktop_wasm_test/README.md)** in the `socktop_wasm_test/` directory.
## Security Considerations
- **Production TLS**: You can hostname verification (`verify_hostname: true`) for production systems, This will add an additional level of production of verifying the hostname against the certificate. Generally this is to stop a man in the middle attack, but since it will be the client who is fooled and not the server, the risk and likelyhood of this use case is rather low. Which is why this is disabled by default.
- **Production TLS**: You can enable hostname verification (`verify_hostname: true`) for production systems, This will add an additional level of production of verifying the hostname against the certificate. Generally this is to stop a man in the middle attack, but since it will be the client who is fooled and not the server, the risk and likelyhood of this use case is rather low. Which is why this is disabled by default.
- **Certificate Pinning**: Use `with_tls_ca()` for self-signed certificates, the socktop agent will generate certificates on start. see main readme for more details.
- **Non-TLS**: Use only for development or trusted networks
@@ -0,0 +1,38 @@
//! Example of using socktop_connector in a WASM environment.
//!
//! This example demonstrates how to use the connector without TLS dependencies
//! for WebAssembly builds.
use socktop_connector::{connect_to_socktop_agent, ConnectorConfig, AgentRequest};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("WASM-compatible socktop connector example");
// For WASM builds, use ws:// (not wss://) to avoid TLS dependencies
let url = "ws://localhost:3000/ws";
// Method 1: Simple connection (recommended for most use cases)
let mut connector = connect_to_socktop_agent(url).await?;
// Method 2: With custom WebSocket configuration
let config = ConnectorConfig::new(url)
.with_protocols(vec!["socktop".to_string()])
.with_version("13".to_string());
let mut connector_custom = socktop_connector::SocktopConnector::new(config);
connector_custom.connect().await?;
// Make a request to get metrics
match connector.request(AgentRequest::Metrics).await {
Ok(response) => {
println!("Successfully received response: {:?}", response);
}
Err(e) => {
println!("Request failed: {}", e);
}
}
println!("WASM example completed successfully!");
Ok(())
}
+16 -7
View File
@@ -3,20 +3,29 @@
use flate2::bufread::GzDecoder;
use futures_util::{SinkExt, StreamExt};
use prost::Message as _;
use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
use rustls::{ClientConfig, RootCertStore};
use rustls::{DigitallySignedStruct, SignatureScheme};
use rustls_pemfile::Item;
use std::io::Read;
use std::{fs::File, io::BufReader, sync::Arc};
use tokio::net::TcpStream;
use tokio_tungstenite::{
Connector, MaybeTlsStream, WebSocketStream, connect_async, connect_async_tls_with_config,
MaybeTlsStream, WebSocketStream, connect_async,
tungstenite::Message, tungstenite::client::IntoClientRequest,
};
use url::Url;
#[cfg(feature = "tls")]
use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
#[cfg(feature = "tls")]
use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
#[cfg(feature = "tls")]
use rustls::{ClientConfig, RootCertStore};
#[cfg(feature = "tls")]
use rustls::{DigitallySignedStruct, SignatureScheme};
#[cfg(feature = "tls")]
use rustls_pemfile::Item;
#[cfg(feature = "tls")]
use std::{fs::File, io::BufReader, sync::Arc};
#[cfg(feature = "tls")]
use tokio_tungstenite::{Connector, connect_async_tls_with_config};
use crate::error::{ConnectorError, Result};
use crate::types::{AgentRequest, AgentResponse, DiskInfo, Metrics, ProcessInfo, ProcessesPayload};
+4 -1
View File
@@ -146,8 +146,11 @@ pub mod types;
pub use connector::{
ConnectorConfig, SocktopConnector, WsStream, connect_to_socktop_agent,
connect_to_socktop_agent_with_config, connect_to_socktop_agent_with_tls,
connect_to_socktop_agent_with_config,
};
#[cfg(feature = "tls")]
pub use connector::connect_to_socktop_agent_with_tls;
pub use error::{ConnectorError, Result};
pub use types::{
AgentRequest, AgentResponse, DiskInfo, GpuInfo, Metrics, NetworkInfo, ProcessInfo,