Typed Skinny Client Control Protocol messages and an asynchronous station server.
The crate separates the phone-facing wire protocol from the call-control
application. [Server] owns station connections and translates inbound
packets into semantic [Event] values. Applications respond through a
cloneable [ServerHandle] using typed [Command] values; no SIP or PBX
policy is built into this crate.
Typical workflow
- Build and validate one or more [
DeviceDefinition] values. - Start [
Server::bind], spawn [Server::run], and retain its [ServerHandle] and event receiver. - Consume events in order. Registration, call input, media acknowledgements, and disconnects all arrive through the same stream.
- Send commands through the handle. Use [
ServerHandle::send_confirmed] when later work depends on the complete frame having reached the station socket; [ServerHandle::send] confirms queue admission only. - Call [
ServerHandle::shutdown] and await the server task during orderly application shutdown.
use sccp_protocol::{
ButtonDefinition, DeviceDefinition, DeviceId, LineAppearance, LineDefinition,
Server, ServerConfig, SoftKeyProfile, StationTransportRequirement, StationUiPolicy,
};
# async fn example() -> Result<(), Box<dyn std::error::Error>> {
let station = DeviceDefinition {
id: DeviceId::new("SEP001122334455")?,
description: "Front desk".into(),
transport: StationTransportRequirement::Either,
signaling_qos: None,
buttons: vec![ButtonDefinition::Line(LineAppearance::new(
1,
LineDefinition {
number: "1001".into(),
display_name: "Reception".into(),
},
))],
soft_keys: SoftKeyProfile::default(),
ui: StationUiPolicy::default(),
};
station.validate()?;
let (server, handle, mut events) = Server::bind(ServerConfig::default(), [station]).await?;
let server_task = tokio::spawn(server.run());
if let Some(event) = events.recv().await {
println!("{event:?}");
}
handle.shutdown().await?;
server_task.await??;
# Ok(())
# }
Choosing an API layer
Most applications use the crate-root re-exports plus [server] and
[types]. [message] exposes framing, message IDs, codecs, and typed wire
models for protocol tools or custom transports. [phone] contains bounded
phone-hosted XML, authentication, service, and provisioning models.
[qos] owns service-node reservation transitions without sharing handset
session state. To supply an externally accepted transport—such as a TLS
stream—construct the server with [Server::with_ingress] and feed streams through
[ServerIngress].