5 releases
Uses new Rust 2024
new 0.1.25 | Apr 17, 2025 |
---|---|
0.1.24 | Apr 17, 2025 |
0.1.23 | Apr 17, 2025 |
0.1.22 | Apr 17, 2025 |
0.1.21 | Apr 17, 2025 |
#337 in HTTP server
378 downloads per month
20KB
283 lines
🛰️ Jambonz WebSocket Server Framework
A lightweight, extensible WebSocket framework built with Actix Web for building voice and media applications using the Jambonz protocol. It allows dynamic routing and state-aware handling of WebSocket messages, such as call hooks and audio recordings.
✨ Features
- 🔧 Register Jambonz-style WebSocket routes (e.g., hooks, recordings)
- 🧠 Share application state across handlers
- 📡 Auto-negotiated subprotocol headers (
ws.jambonz.org
,audio.jambonz.org
) - 🚀 Async-first with Actix runtime and WebSocket support
- ⚙️ Minimal setup and extensible architecture
📝 TODO
- Receive REST web hooks
- Basic Auth
🔧 Quick Start
1. Define Your App State
#[derive(Clone)]
pub struct AppState {
pub message: String,
}
2. Define Your Handlers
🎙️ Recording Handler
use cal_jambonz::ws::{JambonzRequest, RecordingRequest};
let recording_handler = register_handler(|mut ctx: HandlerContext<AppState>| async move {
match ctx.request {
JambonzRequest::Recording(RecordingRequest::SessionNew(session)) => {
println!("Started recording session: {:?}", session);
}
JambonzRequest::Recording(RecordingRequest::Binary(bytes)) => {
println!("Received audio bytes: {} bytes", bytes.len());
}
JambonzRequest::Recording(RecordingRequest::Close) => {
println!("Recording session closed");
}
_ => {}
}
});
🔁 Hook Handler (Expanded Match)
use cal_jambonz::verbs::{Verbs, Say};
use cal_jambonz::ws::{JambonzRequest, WebsocketRequest};
let hook_handler = register_handler(|mut ctx: HandlerContext<AppState>| async move {
match ctx.request {
JambonzRequest::Hook(req) => {
match req {
WebsocketRequest::SessionNew(new_session) => {
let ack = Verbs::new(&new_session.msgid)
.say(Say::new("Welcome! Please wait while we find an agent.".to_string()))
.as_ack_reply()
.json();
let _ = ctx.session.text(ack).await;
}
WebsocketRequest::SessionRedirect(redirect) => {
println!("Session redirected: {:?}", redirect);
}
WebsocketRequest::SessionReconnect(reconnect) => {
println!("Session reconnected: {:?}", reconnect);
}
WebsocketRequest::CallStatus(status) => {
println!("Call status update: {:?}", status);
}
WebsocketRequest::VerbHook(hook) => {
println!("Verb hook event: {:?}", hook);
}
WebsocketRequest::Close => {
println!("Session closed");
}
}
}
_ => {
println!("Received non-hook request on hook handler");
}
}
});
3. Register Routes and Start Server
use your_crate::{JambonzRoute, JambonzRouteType, JambonzWebServer};
let server = JambonzWebServer::new(AppState {
message: "stateful message".into(),
})
.with_bind_ip("127.0.0.1")
.with_bind_port(3000)
.add_route(JambonzRoute {
path: "/hook".into(),
ws_type: JambonzRouteType::Hook,
handler: hook_handler,
})
.add_route(JambonzRoute {
path: "/recording".into(),
ws_type: JambonzRouteType::Recording,
handler: recording_handler,
});
server.start();
📦 JambonzRequest Explained
The core WebSocket message types are represented using the JambonzRequest
enum:
pub enum JambonzRequest {
Hook(WebsocketRequest),
Recording(RecordingRequest),
}
🔁 Hook Events
pub enum WebsocketRequest {
SessionNew(SessionNew),
SessionRedirect(SessionRedirect),
SessionReconnect(SessionReconnect),
CallStatus(SessionCallStatus),
VerbHook(SessionVerbHook),
Close,
}
These represent various control and lifecycle events during a live call.
🎙️ Recording Events
pub enum RecordingRequest {
SessionNew(SessionRecording),
Binary(Vec<u8>),
Close,
}
Used for handling real-time audio streams and recording metadata.
🧰 Handler Context
Each handler receives a HandlerContext<T>
containing:
pub struct HandlerContext<T> {
pub uuid: Uuid, // Unique per-session ID
pub session: Session, // WebSocket session object
pub request: JambonzRequest, // Incoming parsed request
pub state: Data<T>, // Your app state
}
Use ctx.session.text(...)
to respond directly to the WebSocket client.
✅ Requirements
- Rust 1.70+
- Actix Web ecosystem
- Features from:
actix-web
,actix-ws
,uuid
,serde
,futures
, etc.
🧱 Contributing
PRs and issues are welcome. Whether it's bug fixes, new features, or documentation improvements — let's build together.
📄 License
MIT
Dependencies
~19–30MB
~519K SLoC