Skip to main content

sccp_protocol/
lib.rs

1//! Typed Skinny Client Control Protocol messages and an asynchronous station server.
2//!
3//! The crate separates the phone-facing wire protocol from the call-control
4//! application. [`Server`] owns station connections and translates inbound
5//! packets into semantic [`Event`] values. Applications respond through a
6//! cloneable [`ServerHandle`] using typed [`Command`] values; no SIP or PBX
7//! policy is built into this crate.
8//!
9//! # Typical workflow
10//!
11//! 1. Build and validate one or more [`DeviceDefinition`] values.
12//! 2. Start [`Server::bind`], spawn [`Server::run`], and retain its
13//!    [`ServerHandle`] and event receiver.
14//! 3. Consume events in order. Registration, call input, media
15//!    acknowledgements, and disconnects all arrive through the same stream.
16//! 4. Send commands through the handle. Use [`ServerHandle::send_confirmed`]
17//!    when later work depends on the complete frame having reached the station
18//!    socket; [`ServerHandle::send`] confirms queue admission only.
19//! 5. Call [`ServerHandle::shutdown`] and await the server task during orderly
20//!    application shutdown.
21//!
22//! ```no_run
23//! use sccp_protocol::{
24//!     ButtonDefinition, DeviceDefinition, DeviceId, LineAppearance, LineDefinition,
25//!     Server, ServerConfig, SoftKeyProfile, StationTransportRequirement, StationUiPolicy,
26//! };
27//!
28//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
29//! let station = DeviceDefinition {
30//!     id: DeviceId::new("SEP001122334455")?,
31//!     description: "Front desk".into(),
32//!     transport: StationTransportRequirement::Either,
33//!     signaling_qos: None,
34//!     buttons: vec![ButtonDefinition::Line(LineAppearance::new(
35//!         1,
36//!         LineDefinition {
37//!             number: "1001".into(),
38//!             display_name: "Reception".into(),
39//!         },
40//!     ))],
41//!     soft_keys: SoftKeyProfile::default(),
42//!     ui: StationUiPolicy::default(),
43//! };
44//! station.validate()?;
45//!
46//! let (server, handle, mut events) = Server::bind(ServerConfig::default(), [station]).await?;
47//! let server_task = tokio::spawn(server.run());
48//!
49//! if let Some(event) = events.recv().await {
50//!     println!("{event:?}");
51//! }
52//!
53//! handle.shutdown().await?;
54//! server_task.await??;
55//! # Ok(())
56//! # }
57//! ```
58//!
59//! # Choosing an API layer
60//!
61//! Most applications use the crate-root re-exports plus [`server`] and
62//! [`types`]. [`message`] exposes framing, message IDs, codecs, and typed wire
63//! models for protocol tools or custom transports. [`phone`] contains bounded
64//! phone-hosted XML, authentication, service, and provisioning models.
65//! [`qos`] owns service-node reservation transitions without sharing handset
66//! session state. To supply an externally accepted transport—such as a TLS
67//! stream—construct the server with [`Server::with_ingress`] and feed streams through
68//! [`ServerIngress`].
69
70#![deny(missing_debug_implementations)]
71
72pub mod message;
73pub mod phone;
74pub mod qos;
75pub mod server;
76pub mod types;
77
78pub use message::capabilities::{
79    CapabilityUpdate, CapabilityUpdateVariant, ConferenceResource, ConferenceServiceResource,
80    CustomPictureFormat, DataCapability, StationMediaCapabilities, VideoCapability,
81    VideoLevelPreference,
82};
83pub use message::catalog::{MessageDirection, MessageId, MessageRoute};
84pub use message::values::{
85    AddParticipantResult, AlarmSeverity, AnnouncementPlayMode, AnnouncementPlayStatus,
86    AuditParticipantResult, BusyLampFieldState, ButtonType, CallForwardKind,
87    CallHistoryDisposition, CallInfoVisibility, CallPriority, CallSecurityState, CallState,
88    CallType, Codec, CodecKind, ConferenceResourceType, CreateConferenceResult,
89    DeleteConferenceResult, DeviceType, Digit, DtmfMode, DynamicCallInfoLayout, EchoCancellation,
90    EncryptionCapability, EncryptionMethod, EndOfAnnouncementAck, G723BitRate, IpAddressType,
91    KeyMode, LampMode, LayoutProfile, MediaPathCapability, MediaPathEvent, MediaPathId,
92    MediaStatus, MediaTransport, MediaType, MessageWaitingResult, MicrophoneMode, MiscCommandType,
93    ModifyConferenceResult, NotificationPriority, PartyInformationRestrictions, PhoneFeatures,
94    ProtocolVersion, QosDirection, QosErrorCode, QosReservationStyle,
95    RFC2833_TELEPHONE_EVENT_PAYLOAD, ReceiveTransmit, ResetType, RingDuration, RingerMode,
96    RsvpErrorCode, SilenceSuppression, SoftKey, SpeakerMode, StationSessionContext,
97    StatisticsProcessing, Stimulus, SubscriptionCause, Tone, ToneDirection, UnregisterStatus,
98    VideoFormat,
99};
100pub use message::wire::{CodecError, Frame, FrameDecoder, MAX_FRAME_SIZE};
101pub use message::{
102    AddParticipantRequest, AddParticipantResponse, AnnouncementEntry, AudioStreamControl,
103    AuditConferenceEntry, AuditConferenceResponse, AuditParticipantResponse, BoundedBytes,
104    BoundedBytesError, ButtonTemplateEntry, CALL_COUNT_REQUEST_EXTENDED_BYTES,
105    CALL_COUNT_RESPONSE_MAX_LINE_ENTRIES, CONNECTION_QUALITY_MAX_BYTES, CallCountLineData,
106    CallCountRequestPayload, CallCountResponse, ChangeParticipantRequest, ClientMessage,
107    ConferenceParticipant, ConferenceParticipantChange, ConfigurationStatus,
108    ConnectionQualityStatistics, ConnectionStatistics, ControlMessage, CreateConferenceRequest,
109    CreateConferenceResponse, DtmfPayloadIdentity, DtmfPayloadRequest, DtmfToneControl,
110    ExtensionDeviceCapabilities, KnownOpaqueMessage, MAX_MULTIMEDIA_PICTURE_FORMATS,
111    MAX_SIGNALING_SERVERS, MEDIA_PORT_LIST_MAX_PORTS, MULTIMEDIA_CAPABILITY_BYTES, MediaCapability,
112    MediaEncryption, MediaEndpointAddress, MediaFailureDetection, MediaPortList,
113    MediaResourceNotification, MediaTransmissionAck, MessageWaitingCounts,
114    MessageWaitingNotification, MiscellaneousCommand, ModifyConferenceRequest,
115    ModifyConferenceResponse, MulticastMediaReception, MulticastMediaTransmission,
116    MultimediaCapabilityError, MultimediaPayload, MultimediaPayloadDescriptor,
117    MultimediaPictureFormat, MultimediaStreamControl, MultimediaVideoCapability,
118    MultimediaVideoCapabilityArm, OpenMultimediaChannel, OpenMultimediaReceiveChannelAck,
119    ParticipantChangeRouting, PortClose, PortEndpoint, PortRequest, QosApplicationIdentifier,
120    QosFlow, QosTrafficSpecification, RawMessage, RegisterTokenMessage, RegistrationMessage,
121    RegistrationWireDetails, RegistrationWireLayout, RtpPayloadNumber, RtpPayloadNumberError,
122    ServerMessage, SessionTransmission, SignalingServerEndpoint, SpcpRegisterTokenMessage,
123    StartMultimediaTransmission, StartMultimediaTransmissionAck, SubscriptionRequest,
124    UserDataMessage, UserDataV1Message, VideoFlowControl, XML_ALARM_CANONICAL_DOCUMENT_BYTES,
125    XML_ALARM_CANONICAL_WIRE_BYTES, XML_ALARM_MAX_WIRE_BYTES, XmlAlarmMessage,
126};
127pub use phone::authentication::{
128    OpaquePhoneAuthenticationResponse, PHONE_AUTHENTICATION_MAX_PASSWORD_BYTES,
129    PHONE_AUTHENTICATION_MAX_QUERY_BYTES, PHONE_AUTHENTICATION_MAX_RESPONSE_BYTES,
130    PHONE_AUTHENTICATION_MAX_USER_ID_BYTES, PhoneAuthenticationError, PhoneAuthenticationPassword,
131    PhoneAuthenticationRequest, PhoneAuthenticationResponse, PhoneAuthenticationUserId,
132};
133pub use phone::service::{
134    CiscoIpPhoneError, CiscoIpPhoneResponse, CiscoIpPhoneResponseItem, PhoneExecuteStatus,
135    PhoneServiceError, PhoneServiceErrorCode, PhoneServiceEvent, PhoneServiceExtendedRouting,
136    PhoneServiceMessageKind, PhoneServicePayload, PhoneServiceRouting, PhoneServiceSubmission,
137    PhoneServiceSubmittedValue, parse_phone_service_payload,
138};
139pub use phone::xml::{
140    CiscoIpPhoneAlarm, CiscoIpPhoneAlarmEntry, CiscoIpPhoneAlarmEnum, CiscoIpPhoneAlarmParameter,
141    CiscoIpPhoneAlarmParameterList, CiscoIpPhoneAlarmString, CiscoIpPhoneBackground,
142    CiscoIpPhoneDirectory, CiscoIpPhoneDirectoryEntry, CiscoIpPhoneExecute,
143    CiscoIpPhoneExecuteItem, CiscoIpPhoneGraphicFileMenu, CiscoIpPhoneGraphicMenu,
144    CiscoIpPhoneIconFileItem, CiscoIpPhoneIconFileMenu, CiscoIpPhoneIconItem, CiscoIpPhoneIconMenu,
145    CiscoIpPhoneIconMenuItem, CiscoIpPhoneIconTitle, CiscoIpPhoneImage, CiscoIpPhoneImageFile,
146    CiscoIpPhoneImageList, CiscoIpPhoneImageListItem, CiscoIpPhoneInput, CiscoIpPhoneInputItem,
147    CiscoIpPhoneKeyItem, CiscoIpPhoneLocationInformation, CiscoIpPhoneMenu, CiscoIpPhoneMenuItem,
148    CiscoIpPhoneOffPremises, CiscoIpPhoneSetBackground, CiscoIpPhoneSetBackgroundPreview,
149    CiscoIpPhoneSetRingTone, CiscoIpPhoneSoftKeyItem, CiscoIpPhoneStatus, CiscoIpPhoneStatusFile,
150    CiscoIpPhoneText, CiscoIpPhoneTouchAreaMenuItem, CiscoIpPhoneWifiLocation,
151    ConferenceListAction, ConferenceListDocument, ConferenceListEntry, ConferenceMenuFamily,
152    ConferenceParticipantActionsDocument, OpaquePhoneAlarm, OpaquePhoneLocation,
153    PHONE_ALARM_MAX_BYTES, PHONE_BACKGROUND_APPLICATION_ID, PHONE_BACKGROUND_CONTROL_MAX_BYTES,
154    PHONE_BACKGROUND_LIST_MAX_BYTES, PHONE_BACKGROUND_LIST_MAX_ITEMS, PHONE_DIRECTORY_MAX_BYTES,
155    PHONE_DIRECTORY_MAX_ENTRIES, PHONE_EXECUTE_MAX_BYTES, PHONE_EXECUTE_MAX_ITEMS,
156    PHONE_GRAPHIC_FILE_MENU_MAX_ITEMS, PHONE_GRAPHIC_MENU_MAX_ITEMS, PHONE_ICON_MENU_MAX_ICONS,
157    PHONE_ICON_MENU_MAX_ITEMS, PHONE_IMAGE_BITMAP_MAX_BYTES, PHONE_IMAGE_MAX_BYTES,
158    PHONE_INPUT_MAX_BYTES, PHONE_INPUT_MAX_ITEMS, PHONE_LOCATION_MAX_BYTES, PHONE_MENU_MAX_BYTES,
159    PHONE_MENU_MAX_ITEMS, PHONE_RINGTONE_APPLICATION_ID, PHONE_RINGTONE_MAX_BYTES,
160    PHONE_STATUS_BITMAP_MAX_BYTES, PHONE_STATUS_MAX_BYTES, PHONE_TEXT_APPLICATION_ID,
161    PHONE_TEXT_LEGACY_MAX_CHARS, PHONE_TEXT_MAX_BYTES, PHONE_TEXT_MAX_CHARS,
162    PHONE_XML_MAX_NESTING_DEPTH, PhoneActionKind, PhoneAlarmKind, PhoneAlarmSummary,
163    PhoneAlarmTelemetry, PhoneBackgroundControlDocument, PhoneBackgroundHttpUrl,
164    PhoneBackgroundTftpUrl, PhoneBitmapData, PhoneBssid, PhoneExecutePriority, PhoneExecuteUrl,
165    PhoneImageDocument, PhoneImageUrl, PhoneInputFlags, PhoneInputParameterName, PhoneKeypadTarget,
166    PhoneLocationKind, PhoneLocationSummary, PhoneLocationTelemetry, PhoneRingtoneUrl,
167    PhoneServicePriority, PhoneSoftKeyPosition, PhoneStatusDocument, PhoneTouchArea, PhoneXmlError,
168    PhoneXmlKey, PhoneXmlRefresh, from_bytes as parse_phone_xml, parse_phone_alarm,
169    parse_phone_location, to_string as serialize_phone_xml,
170};
171pub use qos::{
172    QosReservationController, QosReservationError, QosReservationEvent, QosReservationFailure,
173    QosReservationId, QosReservationLimits, QosReservationPolicy, QosReservationRequest,
174    QosReservationSetup, QosReservationState, QosTransition,
175};
176pub use server::{
177    AnonymousHotlineDefinition, CallSelectionOrder, Command, CommandAction, DeviceEvent,
178    DeviceEventKind, DoNotDisturbButtonMode, DoNotDisturbMode, Event, HandsetAcknowledgement,
179    HandsetStatusMessage, IncomingOfferDelivery, IncomingOfferReceipt, IncomingPresentation,
180    IncomingRing, MAX_REGISTRATION_BACKOFF, MIN_REGISTRATION_BACKOFF, MediaStatisticsSnapshot,
181    MulticastMediaRoute, MultimediaReceiveDescriptor, MultimediaTransmitControl,
182    MultimediaTransmitDescriptor, PARKING_MENU_MAX_ITEMS, ParkingMenuEntry, ReceiveChannelPurpose,
183    ReconfigureResult, RegistrationFallback, RegistrationTokenPolicy, Server, ServerConfig,
184    ServerError, ServerHandle, ServerIngress, SignalingServerRoute, SignalingSocket,
185    SocketQosFailure, SocketQosMark, SocketQosPolicy, SocketQosReport, StationIo,
186    StationSessionTarget, StationSocketQos, TransmitOpenOutcome, VideoPictureReference,
187    VideoPictureReferences, apply_socket_qos,
188};
189pub use types::{
190    AddonModuleDefinition, AppearanceId, AppearanceRingMode, ApplicationId, AudioProcessingPolicy,
191    BlfCallerInfo, BlfSpeedDialDefinition, BlfState, ButtonDefinition, CallDirection, CallId,
192    CallInfo, CallReference, CallerIdOverride, ConferenceId, DEFAULT_AUDIO_MAX_FRAMES_PER_PACKET,
193    DEFAULT_AUDIO_PACKET_MS, DateTemplate, DeviceDefinition, DeviceId, DeviceRegistration,
194    FeatureDefinition, LegacyCodePage, LineAppearance, LineDefinition, LineInstance, MediaEndpoint,
195    MediaTrafficClass, ParticipantId, PassthroughPartyId, ServiceDefinition, SessionGeneration,
196    SignalingQos, SoftKeyProfile, SpeedDialDefinition, StationTransport,
197    StationTransportRequirement, StationUiPolicy, TransactionId,
198};