# freeswitch-types
[](https://crates.io/crates/freeswitch-types)
[](https://docs.rs/freeswitch-types)
FreeSWITCH protocol types and general-purpose SIP header parser. No async
runtime dependency.
Includes `SipHeaderAddr`, a standalone RFC 3261 `name-addr` parser with
header-level parameters — usable in any SIP project, not just FreeSWITCH.
With `default-features = false`, the only dependencies are `sip-uri` and
`percent-encoding`.
Also provides FreeSWITCH ESL types (channel state, events, commands,
variables) for CDR parsing, config generation, command building, or
channel variable validation without pulling in tokio.
For async ESL transport (connecting to FreeSWITCH, sending commands, receiving
events), see [`freeswitch-esl-tokio`](https://crates.io/crates/freeswitch-esl-tokio)
which re-exports everything from this crate.
## What's included
| `sip_header_addr` | `SipHeaderAddr` — RFC 3261 `name-addr` parser with header-level parameters |
| `channel` | `ChannelState`, `CallState`, `AnswerState`, `CallDirection`, `HangupCause`, `ChannelTimetable` |
| `headers` | `EventHeader` enum (typed event header names) |
| `lookup` | `HeaderLookup` trait (typed accessors for any key-value store) |
| `variables` | `ChannelVariable`, `SofiaVariable`, `EslArray`, `MultipartBody` |
| `event` | `EslEvent`, `EslEventType`, `EventFormat`, `EslEventPriority` *(requires `esl` feature)* |
| `commands` | `Originate`, `BridgeDialString`, `UuidKill`, `UuidBridge`, endpoint types *(requires `esl` feature)* |
| `conference_info` | RFC 4575 `conference-info+xml` types *(requires `conference-info` feature)* |
## Features
- **`esl`** (enabled by default) — ESL event and command types (`EslEvent`,
`Originate`, `Variables`, etc.). Pulls in `indexmap` for ordered header
storage. Disable if you only need `SipHeaderAddr` or channel state enums.
- **`serde`** (enabled by default) — adds `Serialize`/`Deserialize` impls for
all public types. Disable with `default-features = false` if you only need
wire-format parsing (`Display`/`FromStr`) without pulling in serde.
- **`conference-info`** — enables `ConferenceInfo::from_xml()`/`to_xml()` for
parsing RFC 4575 `application/conference-info+xml` documents (pulls in
`quick-xml`). Type definitions are always available without this feature.
## Usage
```toml
[dependencies]
freeswitch-types = "1"
```
SIP header parsing only (no FreeSWITCH dependencies):
```toml
[dependencies]
freeswitch-types = { version = "1", default-features = false }
```
### SIP header address parsing
`SipHeaderAddr` parses the `(name-addr / addr-spec) *(SEMI generic-param)`
production from SIP headers like `From`, `To`, `Contact`, and `Refer-To`.
It replaces `sip_uri::NameAddr` (deprecated since sip-uri 0.2.0) by
handling header-level parameters that follow the URI. General-purpose SIP
— no FreeSWITCH dependency.
```rust
use freeswitch_types::SipHeaderAddr;
let addr: SipHeaderAddr =
r#""Alice" <sip:alice@example.com>;tag=abc123"#.parse().unwrap();
assert_eq!(addr.display_name(), Some("Alice"));
assert_eq!(addr.tag(), Some("abc123"));
assert_eq!(addr.sip_uri().unwrap().user(), Some("alice"));
```
### Command builders (requires `esl` feature)
```rust
use std::time::Duration;
use freeswitch_types::commands::*;
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));
// All builders implement Display, producing the FreeSWITCH wire format
assert!(cmd.to_string().starts_with("originate sofia/gateway/"));
// All builders implement FromStr for round-trip parsing
let parsed: Originate = cmd.to_string().parse().unwrap();
assert_eq!(parsed.to_string(), cmd.to_string());
```
### Typed event accessors
```rust
use freeswitch_types::{HeaderLookup, EventHeader, ChannelVariable};
// HeaderLookup works with any key-value store, not just EslEvent
struct MyHeaders(std::collections::HashMap<String, String>);
impl HeaderLookup for MyHeaders {
fn header_str(&self, name: &str) -> Option<&str> {
self.0.get(name).map(|s| s.as_str())
}
fn variable_str(&self, name: &str) -> Option<&str> {
self.0.get(&format!("variable_{}", name)).map(|s| s.as_str())
}
}
// Now MyHeaders has all typed accessors:
// h.channel_state(), h.call_direction(), h.hangup_cause(),
// h.header(EventHeader::UniqueId), h.variable(ChannelVariable::ReadCodec), etc.
```
### Serde support (requires `serde` feature, enabled by default)
All builder types implement `Serialize`/`Deserialize` for config-driven usage:
```rust
use freeswitch_types::Originate;
let json = r#"{
"endpoint": {"sofia_gateway": {"gateway": "carrier", "destination": "18005551234"}},
"application": {"name": "park"},
"timeout_secs": 30
}"#;
let cmd: Originate = serde_json::from_str(json).unwrap();
println!("{}", cmd);
```
### Variable parsers
```rust
use freeswitch_types::variables::{EslArray, MultipartBody};
```
## Relationship to freeswitch-esl-tokio
This crate contains all domain types extracted from the
[`freeswitch-esl-tokio`](https://crates.io/crates/freeswitch-esl-tokio)
workspace. The ESL crate re-exports everything, so users of `freeswitch-esl-tokio`
don't need to depend on this crate directly.
Depend on `freeswitch-types` directly when you need FreeSWITCH types without
async transport (CDR processors, config validators, CLI tools, test harnesses).
## License
MIT OR Apache-2.0