Expand description
FreeSWITCH Event Socket Library (ESL) client for Rust
This crate provides an async Rust client for FreeSWITCH’s Event Socket Library (ESL), allowing applications to connect to FreeSWITCH, execute commands, and receive events.
§Architecture
The library uses a split reader/writer design:
EslClient(Clone + Send) — send commands from any taskEslEventStream— receive events from a background reader task
§Examples
§Inbound Connection
use freeswitch_esl_tokio::{EslClient, EslError};
#[tokio::main]
async fn main() -> Result<(), EslError> {
let (client, mut events) = EslClient::connect("localhost", 8021, "ClueCon").await?;
let response = client.api("status").await?;
println!("Status: {}", response.body().unwrap_or("No body"));
Ok(())
}§Outbound Mode
In outbound mode, FreeSWITCH connects to your application via the
socket
dialplan application. You run a TCP listener and accept connections:
use freeswitch_esl_tokio::{EslClient, EslError, AppCommand, EventFormat, HeaderLookup};
use tokio::net::TcpListener;
#[tokio::main]
async fn main() -> Result<(), EslError> {
let listener = TcpListener::bind("0.0.0.0:8040").await
.map_err(EslError::from)?;
let (client, mut events) = EslClient::accept_outbound(&listener).await?;
// First command must be connect_session — establishes the session
// and returns all channel variables as headers.
let channel_data = client.connect_session().await?;
println!("Channel: {}", channel_data.channel_name().unwrap_or("?"));
client.myevents(EventFormat::Plain).await?;
client.linger_timeout(None).await?; // keep socket open after hangup
client.resume().await?; // resume dialplan on disconnect
client.send_command(AppCommand::answer()).await?;
client.send_command(AppCommand::playback("ivr/ivr-welcome.wav")).await?;
while let Some(Ok(event)) = events.recv().await {
println!("{:?}", event.event_type());
}
Ok(())
}Configure FreeSWITCH to connect to your app:
<action application="socket" data="127.0.0.1:8040 async full"/>See docs/outbound-esl-quirks.md
for protocol details and command availability by mode.
§Command Builders
Typed builders for common API commands — no raw string assembly needed:
use freeswitch_esl_tokio::{Originate, Endpoint, ApplicationList, Application};
let cmd = Originate {
endpoint: Endpoint::SofiaGateway {
uri: "18005551234".into(),
profile: None,
gateway: "my_provider".into(),
variables: None,
},
applications: ApplicationList(vec![
Application::new("park", None::<&str>),
]),
dialplan: None,
context: None,
cid_name: Some("Outbound Call".into()),
cid_num: Some("5551234".into()),
timeout: Some(30),
};
// Use with client.api(&cmd.to_string()) or client.bgapi(&cmd.to_string())
assert!(cmd.to_string().contains("sofia/gateway/my_provider/18005551234"));See the commands module for Originate, UuidBridge, UuidTransfer,
and other builders.
§Event Subscription
use freeswitch_esl_tokio::{EslClient, EslEventType, EventFormat};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (client, mut events) = EslClient::connect("localhost", 8021, "ClueCon").await?;
client.subscribe_events(EventFormat::Plain, &[
EslEventType::ChannelAnswer,
EslEventType::ChannelHangup
]).await?;
while let Some(Ok(event)) = events.recv().await {
println!("Received event: {:?}", event.event_type());
}
Ok(())
}Re-exports§
pub use app::dptools::AppCommand;pub use bgjob::BgJobResult;pub use bgjob::BgJobTracker;pub use channel::AnswerState;pub use channel::CallDirection;pub use channel::CallState;pub use channel::ChannelState;pub use channel::ChannelTimetable;pub use channel::ParseTimetableError;pub use channel::TimetablePrefix;pub use commands::Application;pub use commands::ApplicationList;pub use commands::ConferenceDtmf;pub use commands::ConferenceHold;pub use commands::ConferenceMute;pub use commands::DialplanType;pub use commands::Endpoint;pub use commands::HoldAction;pub use commands::MuteAction;pub use commands::Originate;pub use commands::OriginateError;pub use commands::UuidAnswer;pub use commands::UuidBridge;pub use commands::UuidDeflect;pub use commands::UuidGetVar;pub use commands::UuidHold;pub use commands::UuidKill;pub use commands::UuidSendDtmf;pub use commands::UuidSetVar;pub use commands::UuidTransfer;pub use commands::Variables;pub use commands::VariablesType;pub use connection::ConnectionMode;pub use connection::ConnectionStatus;pub use connection::DisconnectReason;pub use connection::EslClient;pub use connection::EslConnectOptions;pub use connection::EslEventStream;pub use constants::DEFAULT_ESL_PORT;pub use error::EslError;pub use error::EslResult;pub use event::EslEvent;pub use event::EslEventPriority;pub use event::EslEventType;pub use event::EventFormat;pub use headers::EventHeader;pub use headers::ParseEventHeaderError;pub use lookup::HeaderLookup;pub use variables::ChannelVariable;pub use variables::EslArray;pub use variables::MultipartBody;pub use variables::MultipartItem;pub use variables::ParseChannelVariableError;
Modules§
- app
- Application execution via
sendmsg— the dptools family of commands. - bgjob
- Background job tracking for
bgapicommands. - channel
- Channel-related data types extracted from ESL event headers.
- commands
- Command string builders for
api()andbgapi(). - connection
- Connection management for ESL
- constants
- Protocol constants and configuration values
- error
- Error types for FreeSWITCH ESL operations.
- event
- ESL event types and structures
- headers
- Typed event header names for FreeSWITCH ESL events.
- lookup
- Shared trait for typed header lookups from any key-value store.
- variables
- Channel variable types: format parsers (
ARRAY::, SIP multipart) and typed variable name enums.
Structs§
- Command
Builder - Builder for custom ESL commands not covered by
EslClientmethods. - EslResponse
- Response from ESL command execution
Enums§
- Reply
Status - Reply-Text classification per the ESL wire protocol.
Functions§
- parse_
api_ body - Parse an API response body, handling
+OK/-ERR/-USAGEprefixes.