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("[::]: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(event) = events.try_next().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(event) = events.try_next().await? {
        if let 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::AuthMethod;
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 connection::EventOverflow;
pub use error::CommandFailure;
pub use error::EslError;
pub use error::EslResult;
pub use sip_header;
pub use sip_uri;

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.
lossy_values
Types for tracking event headers whose values contained invalid UTF-8.
mock
Scripted FreeSWITCH peer for integration tests (test-util feature).
prelude
Convenience re-exports for common types and traits.
sdp
Converts an SDP offer into a FreeSWITCH codec string and models the codec-string grammar.
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.
BridgeDialStringDisplay
Renders a BridgeDialString for one parser revision. Returned by BridgeDialString::display_with.
ChannelDumpOptions
Options for parse_channel_dump_with_options.
ChannelTimetable
Channel timing data from FreeSWITCH’s switch_channel_timetable_t.
CommandBuilder
Builder for custom ESL commands not covered by EslClient methods.
DialStringTarget
Where a dial string is headed: the command carrying it, the block-parser revision of the switch reading it, and the split cutting that command’s arguments.
EndpointDisplay
Renders an Endpoint for one target. Returned by Endpoint::display_for.
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.
ExecuteOn
An application for an execute_on_* hook such as ChannelVariable::ExecuteOnOriginate.
ExecuteOptions
Options for sendmsg execute commands.
FreeswitchVersion
A FreeSWITCH version in its short form, 1.10.12 or 1.10.13-dev.
HistoryInfo
Parsed History-Info header value (RFC 7044).
HistoryInfoEntry
A single entry from a History-Info header (RFC 7044).
HistoryInfoReason
Parsed RFC 3326 Reason header value extracted from a History-Info URI.
InvalidHeaderName
Error returned when a raw header name is empty or carries a wire terminator.
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].
OriginateDisplay
Renders an Originate for one parser revision. Returned by Originate::display_with.
ParseAnswerStateError
Error returned when parsing an invalid answer state string.
ParseBlockParseError
A BlockParse name this crate does not know. The rejected name is the field.
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 (<n> bytes). The rejected input is the field.
ParseCoreMediaVariableError
Error for an unrecognized value; displays as unknown core media variable (<n> bytes). The rejected input is the field.
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 (<n> bytes). The rejected input is the field.
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.
ParseHoldActionError
Error returned when parsing an invalid hold action string.
ParseLogLevelError
Error returned when parsing an invalid log level string.
ParseMuteActionError
Error returned when parsing an invalid mute action string.
ParsePriorityError
Error returned when parsing an invalid priority string.
ParseSipHeaderAddrError
Error returned when parsing a SIP header address value fails.
ParseSipHeaderError
Error for an unrecognized value; displays as unknown SIP header (<n> bytes). The rejected input is the field.
ParseSipPassthroughError
Error returned when parsing an unrecognized passthrough header variable name.
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.
Secret
Wraps a string so Debug prints [REDACTED] instead of the value.
SipGeolocation
Parsed SIP Geolocation header value (RFC 6442).
SipHeaderAddr
Parsed SIP name-addr (RFC 3261 §25.1) with header-level parameters.
SipPassthroughHeader
A FreeSWITCH SIP passthrough header variable name.
SofiaChannelName
Borrowed view of a parsed sofia channel name. No allocation.
UriInfo
Parsed <absoluteURI> *(SEMI generic-param) header value.
UriInfoEntry
One <uri>;key=value;key=value entry from a URI-info-style header.
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.
VariablesDisplay
Renders a Variables for one target. Returned by Variables::display_for.

Enums§

AnswerState
Answer state from the Answer-State header. Wire format is lowercase.
BlockParse
Which revision of the switch’s bracket-block parser a dial string is rendered for.
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.
CarriedHeader
Relationship between a SofiaVariable and the SIP header behind it.
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).
DialStringCarrier
Which command carries a dial string, and therefore how deeply its variable values must be escaped.
DialplanType
FreeSWITCH dialplan type for originate commands.
Endpoint
Polymorphic endpoint wrapping all concrete types.
EndpointFieldFault
Why an endpoint field cannot reach the switch as written, whatever the escaping.
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.
ExecuteOnFault
What the switch does with an execute_on_* application name or argument that keeps it from reaching the application as written.
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).
HistoryInfoError
Errors from parsing a History-Info header value (RFC 7044).
InvalidArgvSeparator
Why a DialStringTarget takes no argument separator.
LogLevel
Argument of the ESL log command, which sets the level of LOG events the connection receives.
MultipartBodyError
Errors from MultipartBody::parse.
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.
ParseFreeswitchVersionError
Why a string is not a FreeSWITCH short-form version. Names the part at fault, never the input.
ParseHeaderError
The union a caller reaches when ?-ing several typed HeaderLookup accessors into one error type.
ReplyStatus
Reply-Text classification per the ESL wire protocol.
RtpStatUnit
Unit of measurement for an RTP statistic channel variable.
SipGeolocationRef
A reference extracted from a SIP Geolocation header (RFC 6442).
SipHeader
Standard SIP header names with canonical wire casing.
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.
TimetableField
One timetable header, named rather than positional.
TimetablePrefix
Header prefix identifying which call leg’s timetable to extract.
UnvouchedVersion
A FreeSWITCH version BlockParse::for_version cannot vouch for.
UriInfoError
Errors from parsing a URI-info-style header value.
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.
UNDEF_VALUE
What switch_event_serialize writes in place of an empty value, and what uuid_getvar answers for a variable that is not set.
VARIABLE_PREFIX
Header-name prefix a channel variable carries in an event.

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.
SipHeaderLookup
Trait for looking up standard SIP headers from any key-value store.
VariableName
Trait for typed channel variable name enums.

Functions§

case_alias_key
Return a lowercase case-alias for key when case-insensitive aliasing applies.
channel_driver
Endpoint module a channel name belongs to: the segment before the first / (sofia, loopback, null, …).
extract_header
Extract all occurrences of a header from a raw SIP message.
normalize_header_key
Normalize a header key to its canonical form for case-insensitive storage.
parse_api_body
Parse a FreeSWITCH API response body into a result.
parse_channel_dump
Parse a uuid_dump <uuid> body into the CHANNEL_DATA event it is.
parse_channel_dump_with_options
parse_channel_dump with control over lossy UTF-8 decoding.