Skip to main content

Crate freeswitch_esl_tokio

Crate freeswitch_esl_tokio 

Source
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 task
  • EslEventStream – receive events from a background reader task

§Examples

§Inbound Connection

use freeswitch_esl_tokio::{EslClient, EslError, DEFAULT_ESL_PASSWORD, DEFAULT_ESL_PORT};

#[tokio::main]
async fn main() -> Result<(), EslError> {
    let (client, mut events) = EslClient::connect("localhost", DEFAULT_ESL_PORT, DEFAULT_ESL_PASSWORD).await?;

    let response = client.api("status").await?;
    println!("Status: {}", response.api_result()?);

    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, EventHeader};
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?;
    // HeaderLookup trait provides typed header access via EventHeader enum
    println!("Channel: {}", channel_data.header(EventHeader::ChannelName).unwrap_or("?"));

    client.myevents(EventFormat::Plain).await?;
    client.linger(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 std::time::Duration;
use freeswitch_esl_tokio::{Originate, Endpoint, Application};
use freeswitch_esl_tokio::commands::SofiaGateway;

let cmd = Originate::application(
    Endpoint::SofiaGateway(SofiaGateway::new("my_provider", "18005551234")),
    Application::simple("park"),
)
.cid_name("Outbound Call")
.cid_num("5551234")
.timeout(Duration::from_secs(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

EventSubscription captures format, event types, custom subclasses, and filters as a single reusable unit. Build one from code or deserialize from YAML/JSON, then apply it to any connection:

use freeswitch_esl_tokio::{
    EslClient, EslEventType, EventFormat, EventHeader, EventSubscription,
    HeaderLookup, DEFAULT_ESL_PASSWORD, DEFAULT_ESL_PORT,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Build once, reuse on every (re)connection
    let subscription = EventSubscription::new(EventFormat::Plain)
        .event(EslEventType::ChannelAnswer)
        .event(EslEventType::ChannelHangup)
        .event(EslEventType::Heartbeat)
        .custom_subclass("sofia::register")?
        .filter(EventHeader::CallDirection, "inbound")?;

    let (client, mut events) = EslClient::connect(
        "localhost", DEFAULT_ESL_PORT, DEFAULT_ESL_PASSWORD,
    ).await?;

    client.apply_subscription(&subscription).await?;

    while let Some(Ok(event)) = events.recv().await {
        if let Ok(Some(state)) = event.channel_state() {
            println!("{:?}: {}", event.event_type(), state);
        }
    }

    Ok(())
}

Re-exports§

pub use app::dptools::AppCommand;
pub use bgjob::BgJobResult;
pub use bgjob::BgJobTracker;
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 error::EslError;
pub use error::EslResult;

Modules§

app
Application execution via sendmsg – the dptools family of commands.
bgjob
Background job tracking for bgapi commands.
channel
Channel-related data types extracted from ESL event headers.
commands
Command string builders for api() and bgapi().
connection
Connection management for ESL
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.
prelude
Convenience re-exports for common types and traits.
sofia
Typed Sofia event subclasses and state enums.
variables
Channel variable types: format parsers (ARRAY::, SIP multipart) and typed variable name enums.

Structs§

Application
A single dialplan application with optional arguments.
BridgeDialString
Typed bridge dial string.
ChannelTimetable
Channel timing data from FreeSWITCH’s switch_channel_timetable_t.
CommandBuilder
Builder for custom ESL commands not covered by EslClient methods.
EslArray
Parses FreeSWITCH ARRAY::item1|:item2|:item3 format
EslEvent
ESL Event structure containing headers and optional body
EslHeaders
A flat header store that decodes FreeSWITCH ARRAY and bracket encoding when answering typed SIP header queries.
EslResponse
Response from ESL command execution
EventSubscription
Declarative description of an ESL event subscription.
EventSubscriptionError
Error returned when an EventSubscription builder method receives invalid input.
ExecuteOptions
Options for sendmsg execute commands.
LossyValue
A header whose percent-decoded value was not valid UTF-8. Carries the unparsed on-wire value (the percent-encoded source text, always ASCII) so the app can re-decode it (e.g. as Latin-1) or audit it instead of being stuck with the U+FFFD-substituted string in headers.
LossyValues
Header keys whose percent-decoded value contained invalid UTF-8 and was decoded lossily (U+FFFD substituted). Empty in the normal case.
MultipartBody
Parses variable_sip_multipart ARRAY:: format.
MultipartItem
A single part from a SIP multipart body
Originate
Originate command builder: originate <endpoint> <target> [dialplan] [context] [cid_name] [cid_num] [timeout].
ParseAnswerStateError
Error returned when parsing an invalid answer state string.
ParseCallDirectionError
Error returned when parsing an invalid call direction string.
ParseCallStateError
Error returned when parsing an invalid call state string.
ParseChannelStateError
Error returned when parsing an invalid channel state string.
ParseChannelVariableError
Error for an unrecognized value; displays as unknown channel variable: <input>.
ParseCoreMediaVariableError
Error for an unrecognized value; displays as unknown core media variable: <input>.
ParseDialplanTypeError
Error returned when parsing an invalid dialplan type string.
ParseEventFormatError
Error returned when parsing an invalid event format string.
ParseEventHeaderError
Error for an unrecognized value; displays as unknown event header: <input>.
ParseEventTypeError
Error returned when parsing an invalid event type string.
ParseGatewayPingStatusError
Error returned when parsing an invalid gateway ping status string.
ParseGatewayRegStateError
Error returned when parsing an invalid gateway reg state string.
ParseGroupCallOrderError
Error returned when parsing an invalid group call order string.
ParseHangupCauseError
Error returned when parsing an invalid hangup cause string.
ParsePriorityError
Error returned when parsing an invalid priority string.
ParseSipUserPingStatusError
Error returned when parsing an invalid sip user ping status string.
ParseSofiaEventSubclassError
Error returned when parsing an invalid sofia event subclass string.
ParseTimetableError
Error returned when a timetable header is present but not a valid i64.
SipPassthroughHeader
A FreeSWITCH SIP passthrough header variable name.
SofiaChannelName
Borrowed view of a parsed sofia channel name. No allocation.
UuidAnswer
Answer a channel: uuid_answer <uuid>.
UuidBridge
Bridge two channels: uuid_bridge <uuid> <other_uuid>.
UuidDeflect
Deflect (redirect) a channel to a new SIP URI: uuid_deflect <uuid> <uri>.
UuidGetVar
Get a channel variable: uuid_getvar <uuid> <key>.
UuidHold
Place a channel on hold or take it off hold: uuid_hold [off] <uuid>.
UuidKill
Kill a channel: uuid_kill <uuid> [cause].
UuidSendDtmf
Send DTMF digits to a channel: uuid_send_dtmf <uuid> <digits>.
UuidSetVar
Set a channel variable: uuid_setvar <uuid> <key> <value>.
UuidTransfer
Transfer a channel to a new destination: uuid_transfer <uuid> <dest> [dialplan].
Variables
Ordered set of channel variables with FreeSWITCH escaping.

Enums§

AnswerState
Answer state from the Answer-State header. Wire format is lowercase.
CallDirection
Call direction from the Call-Direction header. Wire format is lowercase.
CallState
Call state from switch_channel_callstate_t – carried in the Channel-Call-State header.
ChannelState
Channel state from switch_channel_state_t – carried in the Channel-State header as a string (CS_ROUTING) and in Channel-State-Number as an integer.
ChannelVariable
Core FreeSWITCH channel variable names (the part after the variable_ prefix).
CoreMediaVariable
RTP media statistics channel variable names (the part after the variable_ prefix).
DialplanType
FreeSWITCH dialplan type for originate commands.
Endpoint
Polymorphic endpoint wrapping all concrete types.
EslArrayError
Errors from EslArray::parse.
EslCommand
ESL command types for the wire protocol.
EslEventPriority
Event priority levels matching FreeSWITCH esl_priority_t
EslEventType
FreeSWITCH event types matching the canonical order from esl_event.h and switch_event.c EVENT_NAMES[].
EventFormat
Event format types supported by FreeSWITCH ESL
EventHeader
Top-level header names that appear in FreeSWITCH ESL events.
GatewayPingStatus
Gateway ping status from sofia::gateway_state events.
GatewayRegState
Gateway registration state from sofia::gateway_state events.
GroupCallOrder
Distribution order for group_call dial strings.
HangupCause
Hangup cause from switch_cause_t (Q.850 + FreeSWITCH extensions).
OriginateError
Errors from originate command parsing or construction.
OriginateTarget
The target of an originate command: either a dialplan extension or application(s) to execute directly.
ReplyStatus
Reply-Text classification per the ESL wire protocol.
RtpStatUnit
Unit of measurement for an RTP statistic channel variable.
SipHeaderPrefix
FreeSWITCH SIP header passthrough variable prefix.
SipUserPingStatus
SIP user ping status from sofia::sip_user_state events.
SofiaEventSubclass
Sofia event subclass values from mod_sofia.h MY_EVENT_* defines.
TimetablePrefix
Header prefix identifying which call leg’s timetable to extract.
VariablesType
Scope for channel variables in an originate command.

Constants§

DEFAULT_ESL_PASSWORD
Default FreeSWITCH ESL password (ClueCon).
DEFAULT_ESL_PORT
Default FreeSWITCH ESL port for inbound connections.
MAX_ARRAY_ITEMS
Maximum items accepted by EslArray::parse.

Traits§

DialString
Common interface for anything that formats as a FreeSWITCH dial string.
HeaderLookup
Trait for looking up ESL headers and channel variables from any key-value store.
VariableName
Trait for typed channel variable name enums.

Functions§

parse_api_body
Parse a FreeSWITCH API response body into a result.