- function-inventory: complete public API for 10 Rust crates + 56 Dart files - coverage-analysis: 312 Rust tests, 221 Dart tests, doc coverage gaps - doc-quality-analysis: duplications, broken refs, useless content audit - link-coverage-report: all internal/external links validated - external/teaspeak: TeaSpeak voice server architecture & protocol - external/respeak: ReSpeak org, tsclientlib, tsproto, crypto docs - external/yatqa-en/de: yat.qa admin tool (English + German) - reviews/: cross-validation reports for all analyses All documentation only, no code changes.
281 lines
10 KiB
Markdown
281 lines
10 KiB
Markdown
# ReSpeak Project Knowledge Base
|
|
|
|
> **Source**: https://github.com/ReSpeak/tsclientlib
|
|
> **Last synced**: 2026-06-13
|
|
> **License**: MIT OR Apache-2.0
|
|
|
|
## Overview
|
|
|
|
ReSpeak is an open-source project that provides a Rust implementation of the **TeamSpeak 3 protocol**. The primary goal is to enable building TeamSpeak clients and bots in Rust. The project is **not** an official TeamSpeak product — it was created for fun and to gain features/bugfixes not available in the official client.
|
|
|
|
The organization maintains a single monorepo (`ReSpeak/tsclientlib`) containing multiple crates that layer from low-level protocol handling up to a high-level client library.
|
|
|
|
**Key principle**: ReSpeak does **not** publish server-side code. They earn revenue by selling servers and ReSpeak respects that business model.
|
|
|
|
## Repository Map
|
|
|
|
| Crate | Path | Purpose | Version |
|
|
|-------|------|---------|---------|
|
|
| `tsclientlib` | `tsclientlib/` | High-level client/bot library | 0.2.0 |
|
|
| `tsproto` | `tsproto/` | Low-level TeamSpeak 3 protocol implementation | 0.2.0 |
|
|
| `ts-bookkeeping` | `utils/ts-bookkeeping/` | Server state tracking (clients, channels) | 0.1.x |
|
|
| `tsproto-packets` | `utils/tsproto-packets/` | Packet and command parsing/serialization | 0.1.x |
|
|
| `tsproto-types` | `utils/tsproto-types/` | Core types, enums, crypto primitives | 0.1.x |
|
|
| `tsproto-structs` | `utils/tsproto-structs/` | Generated structs from tsdeclarations | 0.1.x |
|
|
|
|
**External dependency**: [tsdeclarations](https://github.com/ReSpeak/tsdeclarations) — machine-readable TeamSpeak protocol declarations (embedded as git submodule).
|
|
|
|
## tsclientlib
|
|
|
|
### Architecture
|
|
|
|
`tsclientlib` is the **top-level crate** — the one consumers use. It provides:
|
|
|
|
- `Connection` struct: manages a single connection to a TeamSpeak server
|
|
- Async API built on `tokio` + `futures`
|
|
- DNS SRV resolution for server discovery (`resolver.rs`)
|
|
- Audio handling via `audiopus` (Opus codec) behind the `audio` feature flag
|
|
- Sync wrapper (`sync.rs`) for non-async contexts
|
|
- Prelude module for convenient imports
|
|
|
|
### Features
|
|
|
|
| Feature | Default | Description |
|
|
|---------|---------|-------------|
|
|
| `audio` | yes | Opus encode/decode, `AudioHandler` for jitter buffer + mixing |
|
|
| `unstable` | no | Expose internal protocol API (may break on minor releases) |
|
|
| `default-tls` | yes | reqwest with default TLS for HTTP/HTTPS |
|
|
| `bundled` | no | Bundle SDL2 |
|
|
| `static-link` | no | Statically link SDL2 |
|
|
| `audiopus-unstable` | no | Extended audiopus API from Flakebi's fork |
|
|
|
|
### Key Dependencies
|
|
|
|
- `tsproto` — protocol layer
|
|
- `ts-bookkeeping` — state management
|
|
- `tsproto-packets` — packet parsing
|
|
- `tsproto-types` — types + crypto
|
|
- `tokio` — async runtime
|
|
- `hickory-proto` / `hickory-resolver` — DNS resolution
|
|
- `reqwest` — HTTP client
|
|
- `audiopus` — Opus codec (optional)
|
|
|
|
### Source Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `lib.rs` | Core types, re-exports, `Connection` entry point |
|
|
| `audio.rs` | Audio subsystem — Opus encode/decode, `AudioHandler` |
|
|
| `resolver.rs` | DNS SRV resolution for TeamSpeak servers |
|
|
| `sync.rs` | Synchronous wrapper API |
|
|
| `prelude.rs` | Convenience re-exports |
|
|
| `tests.rs` | Integration tests |
|
|
|
|
### Examples
|
|
|
|
- `simple.rs` — minimal async client
|
|
- `simple-sync.rs` — minimal sync client
|
|
- `audio.rs` — audio streaming client
|
|
- `audio-latency.rs` — latency measurement
|
|
- `channeltree.rs` — channel navigation
|
|
- `many.rs` / `sync.rs` — stress tests
|
|
|
|
## tsproto
|
|
|
|
### Architecture
|
|
|
|
`tsproto` implements the **low-level TeamSpeak 3 protocol**:
|
|
|
|
- Connection establishment and handshake
|
|
- UDP packet delivery with reliability (resend logic)
|
|
- Packet encryption and compression
|
|
- Command parsing
|
|
|
|
### Source Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `algorithms.rs` | Packet splitting, encryption/decryption, compression, hash cash |
|
|
| `client.rs` | Client-side connection logic |
|
|
| `connection.rs` | Connection state machine, packet queuing |
|
|
| `packet_codec.rs` | Packet encoding/decoding codec |
|
|
| `resend.rs` | Reliable packet delivery with retransmission |
|
|
| `license.rs` | License system implementation |
|
|
| `log.rs` | Logging utilities |
|
|
| `utils.rs` | Helper functions |
|
|
|
|
### Protocol Details
|
|
|
|
#### Packet Types
|
|
|
|
| Type | Description |
|
|
|------|-------------|
|
|
| `Command` | High-priority commands |
|
|
| `CommandLow` | Low-priority commands |
|
|
| `Voice` | Voice data |
|
|
| `VoiceWhisper` | Whisper voice data |
|
|
| `Ack` / `AckLow` | Acknowledgments |
|
|
| `Ping` / `Pong` | Keepalive |
|
|
| `Init` | Connection initialization |
|
|
|
|
#### Packet Limits
|
|
|
|
- **Max UDP packet size**: 1500 bytes (ethernet MTU)
|
|
- **Max command packet size**: 500 bytes (including header)
|
|
- **Max fragments length**: 40960 bytes
|
|
- **Max decompressed size**: 2 MiB (for large servers with 2000+ channels)
|
|
- **Max out-of-order queue**: 200 packets
|
|
|
|
#### Compression
|
|
|
|
- Uses **QuickLZ** level 1 for command packets
|
|
- Compression only applied if result is smaller than original
|
|
- Fragmentation occurs when compressed data exceeds 500 bytes
|
|
|
|
### Cryptography
|
|
|
|
#### Key Types
|
|
|
|
| Type | Curve | Usage |
|
|
|------|-------|-------|
|
|
| `EccKeyPubP256` | P-256 (secp256r1) | Public identity key |
|
|
| `EccKeyPrivP256` | P-256 | Private identity key |
|
|
| `EccKeyPubEd25519` | Ed25519 | Public ephemeral key (handshake) |
|
|
| `EccKeyPrivEd25519` | Ed25519 | Private ephemeral key (handshake) |
|
|
|
|
#### Encryption Algorithm
|
|
|
|
1. **Key derivation**: `SHA-256(packet_type || generation_id || shared_iv)` → 16-byte key + 16-byte nonce
|
|
2. **Cipher**: AES-128 in EAX mode with 8-byte MAC
|
|
3. **Key caching**: Derived keys are cached per generation to avoid recomputation
|
|
4. **Packet ID mixing**: `key[0] ^= (packet_id >> 8)`, `key[1] ^= (packet_id & 0xff)`
|
|
|
|
#### Shared IV Computation (`compute_iv_mac`)
|
|
|
|
1. ECDH shared secret via Ed25519
|
|
2. `shared_iv = SHA-512(shared_secret)`
|
|
3. XOR with `alpha` (10 bytes) and `beta` (54 bytes) from handshake
|
|
4. `shared_mac = SHA-1(shared_iv)[..8]`
|
|
|
|
#### Hash Cash (Identity Proof-of-Work)
|
|
|
|
- Identity level = number of leading zero bits in `SHA-1(public_key_string || counter)`
|
|
- `upgrade_level(target)` iterates counter until desired level is reached
|
|
- Default target level: 8
|
|
|
|
#### Identity Format
|
|
|
|
```
|
|
Format: counter || 'V' || base64(private_key)
|
|
Example: "2792354VMG8DAgeAAgEgAiEA..."
|
|
```
|
|
|
|
#### Fake Encryption
|
|
|
|
- Used for unencrypted packet types (voice, ack, ping, etc.)
|
|
- Fixed key: `c:\windows\syste` (16 bytes)
|
|
- Fixed nonce: `m\firewall32.cpl` (16 bytes)
|
|
|
|
## ts-bookkeeping
|
|
|
|
Tracks the **server state** by processing incoming commands:
|
|
|
|
- Maintains client list, channel tree, server info
|
|
- Generates events from state changes
|
|
- Provides methods to create outgoing command packets
|
|
- Main struct: `data::Connection`
|
|
|
|
## tsproto-packets
|
|
|
|
Handles **packet serialization/deserialization**:
|
|
|
|
- `packets.rs` — packet structures (`InPacket`, `OutPacket`, `OutAck`, etc.)
|
|
- `commands.rs` — TeamSpeak command parsing
|
|
- Header constants: `C2S_HEADER_LEN`, `S2C_HEADER_LEN`
|
|
|
|
## tsproto-types
|
|
|
|
Core **types and primitives**:
|
|
|
|
- `crypto.rs` — ECC key types (P-256, Ed25519), ECDH, signatures, identity obfuscation
|
|
- `versions.rs` — TeamSpeak version strings
|
|
- `errors.rs` — Protocol error codes
|
|
|
|
### Key Crypto Functions
|
|
|
|
| Function | Description |
|
|
|----------|-------------|
|
|
| `EccKeyPrivP256::create()` | Generate new P-256 keypair |
|
|
| `EccKeyPrivP256::import_str()` | Import from base64/tomcrypt/obfuscated formats |
|
|
| `EccKeyPrivP256::create_shared_secret()` | ECDH with P-256 |
|
|
| `EccKeyPrivP256::sign()` | ECDSA signature |
|
|
| `EccKeyPubP256::verify()` | ECDSA verification |
|
|
| `EccKeyPubP256::get_uid()` | `base64(SHA-1(ts_encoded_key))` |
|
|
| `encode_password()` | `base64(SHA-1(password))` |
|
|
| `EccKeyPrivEd25519::create_shared_secret()` | ECDH with Ed25519 |
|
|
|
|
### Identity Obfuscation
|
|
|
|
TeamSpeak stores identities XOR'd with a static 128-byte pattern + SHA-1 hash of trailing data. ReSpeak implements both obfuscation and deobfuscation.
|
|
|
|
## How Chanora Uses ReSpeak
|
|
|
|
Chanora depends on **four crates** from the ReSpeak monorepo, all pinned to revision `04aa2491`:
|
|
|
|
### Dependency Chain
|
|
|
|
```
|
|
chanora_protocol/
|
|
├── tsclientlib (rev 04aa2491, features=["audio"])
|
|
├── tsproto-packets (rev 04aa2491)
|
|
├── tsproto-types (rev 04aa2491)
|
|
└── ts-bookkeeping (rev 04aa2491)
|
|
|
|
chanora_audio/
|
|
└── tsclientlib (rev 04aa2491, features=["audio"])
|
|
```
|
|
|
|
### Architectural Constraint (SAD-067 / SysDes-011 / SysDes-029)
|
|
|
|
Chanora's `chanora_protocol` crate acts as an **isolation boundary**:
|
|
|
|
> No tsclientlib types may cross out of this crate.
|
|
|
|
This prevents ReSpeak API changes from cascading through Chanora's codebase.
|
|
|
|
### Patched Fork
|
|
|
|
Chanora patches `tsproto-types` to fix **P-256 short coordinate padding**:
|
|
|
|
```toml
|
|
[patch."https://github.com/ReSpeak/tsclientlib.git"]
|
|
tsproto-types = { git = "https://github.com/EdisonJwa/tsclientlib.git", branch = "fix/p256-short-coordinate-pad" }
|
|
```
|
|
|
|
This handles cases where P-256 coordinates are shorter than 32 bytes and need left-padding.
|
|
|
|
### Key Usage Points
|
|
|
|
1. **Protocol connection**: `tsclientlib::Connection` for TeamSpeak server connections
|
|
2. **Audio handling**: `AudioHandler` from tsclientlib for decode, jitter buffer, mixing
|
|
3. **Packet types**: `tsproto-packets` for `OutAudio`, `InAudioBuf`, `AudioData`, `CodecType`, `Direction`
|
|
4. **State tracking**: `ts-bookkeeping` for server state management
|
|
|
|
## External References
|
|
|
|
- **Qint** (https://github.com/ReSpeak/Qint) — Cross-platform TeamSpeak client built on tsclientlib (not yet ready)
|
|
- **SimpleBot** (https://github.com/ReSpeak/SimpleBot) — Example chat bot
|
|
- **tsdeclarations** (https://github.com/ReSpeak/tsdeclarations) — Machine-readable protocol declarations
|
|
- **TSIdentityTool** (https://github.com/landave/TSIdentityTool) — Identity deobfuscation reference (MIT)
|
|
|
|
## Performance Benchmarks
|
|
|
|
From i7-5280K @ 3.6 GHz (single-threaded):
|
|
|
|
| Operation | Time | Throughput |
|
|
|-----------|------|------------|
|
|
| Connection creation | 199 ms | 6.5 conn/sec |
|
|
| Message send | 189 µs | 5300 msg/sec |
|
|
|
|
Bottleneck: RSA puzzle solving at connection time. Use `--features rug` for efficient big integer implementation.
|