# chanora_protocol TeamSpeak-compatible protocol adapter. Isolates `tsclientlib` behind a typed boundary so the rest of Chanora is decoupled from the upstream library's types (SAD-067). ## Architecture - **`adapter` module** — wraps `tsclientlib::Connection` into an async `ProtocolClient` handle. Owns the connection task, loss notifier, snapshot probe, and voice channel endpoints. - **`dto` module** — plain-data types (`ServerSnapshot`, `ChannelInfo`, `ClientInfo`, `ClientProfile`, `ChatMessage`) containing only `String`s and primitives. No `tsclientlib` types leak out. - **`poke_limiter`** — rate-limiter for poke messages to prevent spam. ## Public API Summary ### Types | Type | Role | |---|---| | `ProtocolClient` | Async handle owning the TS3 connection task | | `ConnectConfig` | Connection parameters: address, nickname, password, identity, timeout, resolved_address | | `ServerSnapshot` | Full server state: channels, clients, metadata | | `ChannelInfo` / `ClientInfo` | Channel and client DTOs | | `ClientProfile` | Rich per-client profile (unique_id, country, ping, groups, etc.) | | `ChatMessage` | Inbound text message with target enum | | `MessageTarget` | Server / Channel / Client(id) / Poke(id) | | `ProtocolDelta` | Live state changes: client joined/left/moved/updated, channel added/removed/updated | | `ServerActivity` | Server-wide broadcast messages | | `DisconnectReason` | UserRequested / StreamEnded / Error | | `ProtocolError` | Typed error catalogue: Invalid, DnsFailed, Connect, Lost, Identity, Timeout, ServerRejected, FileTransfer | | `PokeLimiter` | Rate-limiting poke sends | ### Key methods on `ProtocolClient` - `connect(cfg)` — dial a server and return a connected client - `snapshot()` — fetch current server state - `client_profile(id)` — rich profile for one client - `send_text_message(msg, target)` — send chat - `move_to_channel(id, password)` — move to a channel - `queue_move_to_channel(id, password)` — async move with typed error reply - `set_muted(input, output)` — server-side mute - `download_avatar(uid)` / `download_icon(id)` — fetch protocol-owned assets - `voice_out()` / `take_voice_in()` — voice packet endpoints - `take_loss_notifier()` — oneshot channel that fires on connection loss - `snapshot_probe()` — watchdog probe handle - `generate_identity()` — create a fresh TS3 identity string - `disconnect()` — clean shutdown ### Re-exports The crate deliberately re-exports `tsproto_packets::packets::{AudioData, CodecType, Direction, InAudioBuf, OutAudio, OutPacket}` — the single permitted exception so `chanora_audio` can build voice packets without a direct `tsclientlib` dependency (SAD-067 performance carve-out). ## Address resolution `chanora_resolver` owns TeamSpeak client address resolution (SRV, TSDNS, DNS fallback). This crate feeds the resulting `SocketAddr` to `tsclientlib::Connection::build`, bypassing tsclientlib's own resolver.