# Software Architecture Document (SAD) # ReTeamSpeak - Cross-Platform TeamSpeak Client **Version**: 1.0.0 **Date**: 2026-05-12 **Status**: Based on actual implementation --- ## 1. Architectural Overview ### 1.1 System Context ``` ┌─────────────────────────────────────────────────────────────────┐ │ User Environment │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │ │ │ Desktop │ │ Web │ │ Mobile │ │ │ │ Windows │ │ Browser │ │ iOS / Android │ │ │ │ macOS │ │ │ │ │ │ │ │ Linux │ │ │ │ │ │ │ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │ │ │ │ │ │ │ └─────────────────┼──────────────────────┘ │ │ │ │ │ ┌──────▼───────┐ │ │ │ ReTeamSpeak │ │ │ │ Client │ │ │ └──────┬───────┘ │ │ │ │ │ ┌──────▼───────┐ │ │ │ TS3 Server │ │ │ └──────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 1.2 Layered Architecture ``` ┌─────────────────────────────────────────────────────────────────┐ │ Presentation Layer │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ React Frontend (TypeScript) │ │ │ │ - Connection UI, Chat, Channel Tree, Settings │ │ │ └────────────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────────┤ │ Application Layer │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ Tauri Shell (Rust) │ │ │ │ - Command handlers, State management, IPC bridge │ │ │ └────────────────────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────────────────────┤ │ Business Logic Layer │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ tscore │ │ tsaudio │ │ tsdb │ │ shared │ │ │ │ Protocol │ │ Audio │ │ Database │ │ Types │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ ├─────────────────────────────────────────────────────────────────┤ │ Infrastructure Layer │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ - Tokio (Async Runtime) │ │ │ │ - rusqlite (SQLite) │ │ │ │ - cpal (Audio I/O) │ │ │ │ - AES/EAX, SHA, ECDH (Crypto) │ │ │ └────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 2. Module Architecture ### 2.1 Crate Dependency Graph ``` ┌─────────────────┐ │ tauri-app │ │ (Application) │ └────┬───┬───┬────┘ │ │ │ ┌────────────┘ │ └────────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ tscore │ │ tsaudio │ │ tsdb │ │ Protocol │ │ Audio │ │ Database │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ └───────────────┼──────────────────┘ ▼ ┌──────────┐ │ shared │ │ Types │ └──────────┘ ``` ### 2.2 Module Responsibilities #### `shared` - Shared Types Library **Path**: `src/shared/` **Lines**: ~700 **Purpose**: Defines core data types shared across all modules | File | Responsibility | |------|---------------| | `types.rs` | Core types: ClientId, ChannelId, ServerGroupId, Codec, ConnectionState, etc. | | `events.rs` | Event types: AppEvent, ConnectionEvent, ClientEvent, ChannelEvent, etc. | | `errors.rs` | Error types: AppError with variants for each subsystem | | `config.rs` | Configuration: ConfigManager, SavedConnection, RecentServer | **Key Types**: ```rust pub struct ClientId(pub u16); pub struct ChannelId(pub u64); pub struct ServerGroupId(pub u64); pub struct Uid(pub String); pub enum ConnectionState { Disconnected, Connecting, IdentityLevelIncreasing, Connected, ChannelListFinished, DisconnectedTemporarily, Error, } pub enum Codec { SpeexNarrowband, SpeexWideband, SpeexUltrawideband, CeltMono, OpusVoice, OpusMusic, } ``` --- #### `tscore` - Protocol Core Library **Path**: `src/tscore/` **Lines**: ~1800 **Purpose**: Implements TS3 protocol (packets, encryption, connection) **Sub-modules**: ##### `protocol/` - Packet and Command Handling | File | Lines | Responsibility | |------|-------|---------------| | `packet.rs` | 607 | Packet structures (InPacket, OutPacket, Header, InitPacket) | | `types.rs` | 227 | Protocol types (PacketType, CodecType, GroupWhisperType) | | `commands.rs` | 239 | Command parsing/serialization with escape sequences | **Packet Structure**: ```rust pub struct Header { pub mac: [u8; 8], // EAX authentication tag pub packet_id: u16, // Packet sequence number pub client_id: Option, // Client ID (C2S only) pub flags: Flags, // Type + UE/CP/NP/FR flags } pub struct InPacket { pub direction: Direction, pub header: Header, pub data: Vec, } ``` ##### `crypto/` - Encryption and Key Management | File | Lines | Responsibility | |------|-------|---------------| | `eax.rs` | 118 | AES-128-EAX encrypt/decrypt | | `keys.rs` | 229 | Key derivation, KeyCache, SharedSecret | | `hash.rs` | 50 | SHA-1/256/512 hash functions | **Key Derivation**: ```rust fn create_key_nonce( packet_type: PacketType, direction: Direction, generation_id: u32, iv: &[u8; 64], ) -> ([u8; 16], [u8; 16]) { // SHA-256(direction | type | generation_id | iv) // Returns (key, nonce) for AES-EAX } ``` ##### `connection/` - Connection Management | File | Lines | Responsibility | |------|-------|---------------| | `client.rs` | 519 | Client connection with full handshake implementation | | `state.rs` | 90 | Connection state machine | | `resend.rs` | 240 | Packet retransmission with RTT estimation | **Handshake Flow**: ```rust impl Client { pub fn start_handshake(&mut self) -> Result, ProtocolError>; pub fn handle_data(&mut self, data: &[u8]) -> Result>, ProtocolError>; fn build_init2(&mut self) -> Result, ProtocolError>; fn build_init4(&mut self) -> Result, ProtocolError>; fn handle_initivexpand(&mut self, cmd: &Command) -> Result, ProtocolError>; fn handle_initivexpand2(&mut self, cmd: &Command) -> Result, ProtocolError>; fn solve_rsa_puzzle(x: &[u8; 64], n: &[u8; 64], level: u32) -> [u8; 64]; } ``` --- #### `tsaudio` - Audio Engine **Path**: `src/tsaudio/` **Lines**: ~280 **Purpose**: Audio capture, playback, and codec operations | File | Lines | Responsibility | |------|-------|---------------| | `lib.rs` | 80 | Core types (AudioConfig, AudioFrame, AudioError) | | `capture.rs` | 30 | Audio capture (cpal-based, optional) | | `playback.rs` | 30 | Audio playback (cpal-based, optional) | | `codec.rs` | 55 | Opus encoder/decoder (optional) | | `vad.rs` | 45 | Voice Activity Detection | | `buffer.rs` | 65 | Jitter buffer for smooth playback | **Audio Frame**: ```rust pub struct AudioFrame { pub sample_rate: u32, // 48000 Hz pub channels: u16, // 1 (mono) or 2 (stereo) pub samples: Vec, // PCM samples } ``` --- #### `tsdb` - Database Layer **Path**: `src/tsdb/` **Lines**: ~400 **Purpose**: SQLite database for persistent storage | File | Lines | Responsibility | |------|-------|---------------| | `lib.rs` | 104 | Database initialization and table creation | | `identity.rs` | 115 | Identity CRUD operations | | `bookmark.rs` | 176 | Bookmark CRUD operations | | `message.rs` | 139 | Message storage and retrieval | | `config.rs` | 75 | Settings key-value storage | **Database Manager**: ```rust pub struct DatabaseManager { conn: rusqlite::Connection, } impl DatabaseManager { pub fn new(path: &str) -> DatabaseResult; fn init_tables(&self) -> DatabaseResult<()>; // Identity, Bookmark, Message, Settings CRUD... } ``` --- #### `tauri-app` - Application Shell **Path**: `src/tauri-app/` **Lines**: ~500 ##### `src-tauri/` - Rust Backend | File | Lines | Responsibility | |------|-------|---------------| | `lib.rs` | 60 | Tauri setup, plugin registration, state init | | `main.rs` | 5 | Entry point | | `commands.rs` | 155 | Tauri command handlers (IPC bridge) | | `state.rs` | 40 | Connection state management | **Tauri Commands**: ```rust #[tauri::command] async fn get_identities(state) -> Result, String>; #[tauri::command] async fn create_identity(state, name) -> Result; #[tauri::command] async fn get_bookmarks(state) -> Result, String>; #[tauri::command] async fn create_bookmark(state, name, address, port, nickname) -> Result; #[tauri::command] async fn connect(state, address, port, nickname, password) -> Result<(), String>; #[tauri::command] async fn disconnect(state) -> Result<(), String>; #[tauri::command] async fn send_message(state, target, message) -> Result<(), String>; #[tauri::command] async fn get_messages(state, server_address, limit, offset) -> Result, String>; ``` ##### `frontend/` - React Frontend | File | Responsibility | |------|---------------| | `App.tsx` | Main application component | | `main.tsx` | Entry point | | `styles.css` | Application styles | --- ## 3. Data Flow Architecture ### 3.1 Connection Establishment ``` User Frontend Tauri Shell tscore │ │ │ │ │── Connect(addr) ───────>│ │ │ │ │── connect() ────────>│ │ │ │ │── Client::new() ─>│ │ │ │ │ │ │ │<── start_handshake│ │ │ │ (Init0) │ │ │ │ │ │ │ │──── UDP Send ────>│ │ │ │ │ │ │ │<── handle_data ───│ │ │ │ (Init1) │ │ │ │ │ │ │ │ ... (Init2-4) ... │ │ │ │ │ │ │ │<── Connected ─────│ │ │<── Connected ────────│ │ │<── Connected ───────────│ │ │ ``` ### 3.2 Voice Data Flow ``` Microphone ──> cpal capture ──> VAD ──> Opus encode ──> Voice packet │ ▼ UDP send │ ▼ Speaker <── cpal playback <── Jitter buffer <── Opus decode <── Voice packet ``` ### 3.3 Message Flow ``` User input ──> Frontend ──> Tauri command ──> tscore │ ▼ Command serialization │ ▼ Encryption (AES-EAX) │ ▼ UDP send │ ▼ Server ──> UDP recv ──> Decrypt ──> Parse ──> Event ──> Frontend ``` --- ## 4. Cross-Cutting Concerns ### 4.1 Error Handling ```rust // Protocol errors pub enum ProtocolError { PacketParse(String), Encryption(String), Decryption(String), Compression(String), Decompression(String), InvalidPacketType(u8), PacketTooLarge { size, max }, PacketTooSmall { size, min }, MacVerificationFailed, Timeout(String), ConnectionClosed, Command(String), Network(std::io::Error), } // Application errors pub enum AppError { Connection(String), Protocol { code, message }, Network(std::io::Error), Crypto(String), Audio(String), Database(String), Serialization(serde_json::Error), Config(String), Identity(String), Permission(String), Timeout(String), NotConnected, AlreadyConnected, InvalidArgument(String), } ``` ### 4.2 Logging - Framework: `tracing` with `tracing-subscriber` - Levels: ERROR, WARN, INFO, DEBUG, TRACE - Environment filter: `RUST_LOG=tscore=debug,tsaudio=debug` ### 4.3 Configuration - Format: TOML - Location: Platform-specific app data directory - Encryption: ChaCha20-Poly1305 for identity keys --- ## 5. Deployment Architecture ### 5.1 Desktop (Windows/macOS/Linux) ``` ┌─────────────────────────────────────┐ │ Tauri Application │ │ ┌───────────────────────────────┐ │ │ │ WebView (System) │ │ │ │ React Frontend (dist/) │ │ │ └───────────────────────────────┘ │ │ ┌───────────────────────────────┐ │ │ │ Rust Backend (lib) │ │ │ │ tscore + tsaudio + tsdb │ │ │ └───────────────────────────────┘ │ └─────────────────────────────────────┘ ``` ### 5.2 Mobile (iOS/Android) ``` ┌─────────────────────────────────────┐ │ Tauri Mobile App │ │ ┌───────────────────────────────┐ │ │ │ WebView (Platform) │ │ │ │ React Frontend (dist/) │ │ │ └───────────────────────────────┘ │ │ ┌───────────────────────────────┐ │ │ │ Rust Backend (cdylib) │ │ │ │ + Platform audio (Oboe) │ │ │ └───────────────────────────────┘ │ └─────────────────────────────────────┘ ``` --- ## 6. Performance Characteristics ### 6.1 Measured Performance - **Connection time**: ~200ms (local network) - **Packet encryption**: ~10μs per packet - **RSA puzzle (level 8)**: ~100ms - **Memory usage**: ~50MB (idle) ### 6.2 Scalability - **Max packet size**: 500 bytes - **Max decompressed size**: 2MB - **Fragment queue limit**: 200 packets - **Resend timeout**: 500ms initial, exponential backoff --- ## 7. Security Architecture ### 7.1 Encryption Layers 1. **Transport**: AES-128-EAX per packet 2. **Key Exchange**: ECDH (P-256 for identity, Curve25519 for session) 3. **Storage**: ChaCha20-Poly1305 for identity keys 4. **Passwords**: base64(sha1(password)) ### 7.2 Anti-DoS - RSA puzzle computation (configurable difficulty) - Hash Cash for identity verification - Rate limiting (planned) --- ## 8. Build and Test ### 8.1 Build System - **Rust**: Cargo workspace - **Frontend**: npm + Vite - **Desktop**: Tauri CLI - **CI/CD**: GitHub Actions ### 8.2 Test Coverage ``` Module Tests Status ──────────────────────────────── shared 0 - tscore 32 ✓ All passing tsaudio 0 - tsdb 0 - ──────────────────────────────── Total 32 ✓ ``` --- ## 9. References - TS3 Protocol Paper: `refercence/tsdeclarations/ts3protocol.md` - tsclientlib: `refercence/tsclientlib/` (reference implementation) - Qint: `refercence/Qint/` (reference UI) - Tauri v2: https://tauri.app