Mark TODO-059 (auto-reconnect) and TODO-062 (DNS chain) as verified complete with evidence. Revise TODO-063 from implementation to verification task (tsclientlib handles encoding). Create protocol implementation traps doc with 13 traps from YaTQA/ReSpeak/TeaSpeak.
140 lines
5.9 KiB
Markdown
140 lines
5.9 KiB
Markdown
# Protocol Implementation Traps — Developer Notes
|
|
|
|
**Date:** 2026-06-11
|
|
**Purpose:** Compile protocol quirks and gotchas from YaTQA, ReSpeak, and TeaSpeak references that could cause bugs if not handled.
|
|
|
|
---
|
|
|
|
## 1. Icon ID Signedness (HIGH)
|
|
|
|
**What:** Icon IDs are `i32` (signed), not `u32`. Read contexts return signed values; write contexts may expect unsigned.
|
|
|
|
**Why it's a trap:** Negative icon IDs from permlist/clientinfo will be misinterpreted as large positive numbers if stored as u32.
|
|
|
|
**How to handle:** Use `i32` for all icon ID fields. When displaying, convert to absolute value or handle negative as "no icon".
|
|
|
|
**Source:** YaTQA §1.4
|
|
|
|
## 2. Avatar Flag = MD5 Hash (HIGH)
|
|
|
|
**What:** `client_flag_avatar` is an MD5 hash string, not a boolean.
|
|
|
|
**Why it's a trap:** Treating it as a boolean (present/absent) loses the identity reference. Avatar filename is derived from Global ID, not from the flag.
|
|
|
|
**How to handle:** Store avatar flag as a string. Use Global ID → Base64 → `[a-p]` encoding for filename (YaTQA §1.5).
|
|
|
|
**Source:** YaTQA §1.5
|
|
|
|
## 3. Channel Subscription = ONE at a Time (MEDIUM)
|
|
|
|
**What:** `channelsubscribe` command subscribes to exactly ONE channel. No array parameter exists.
|
|
|
|
**Why it's a trap:** Attempting to subscribe to multiple channels in one command will fail silently or error.
|
|
|
|
**How to handle:** Send individual subscribe commands per channel. Track subscription state client-side.
|
|
|
|
**Source:** YaTQA §3.1
|
|
|
|
## 4. Line Terminator = 0x0A 0x0D (MEDIUM)
|
|
|
|
**What:** TS3 protocol line terminator is `0x0A 0x0D` (reversed Windows `\n\r`).
|
|
|
|
**Why it's a trap:** Standard `\r\n` (0x0D 0x0A) will cause parse failures. Max line length: 9203 bytes (excluding terminator).
|
|
|
|
**How to handle:** Use `\n\r` (0x0A 0x0D) for all command protocol messages. tsclientlib handles this internally.
|
|
|
|
**Source:** YaTQA §1.3
|
|
|
|
## 5. UCS-2 vs UTF-8 Encoding (HIGH)
|
|
|
|
**What:** TS3 claims UTF-8 but actually uses UCS-2 (BMP only). Mobile apps use CESU-8. Server 3.2.0+ adds partial SIP support (emoji ranges).
|
|
|
|
**Why it's a trap:** Characters outside BMP (emoji, rare CJK) may not round-trip correctly. tsclientlib uses `str::from_utf8()` — if server sends UCS-2, it will error.
|
|
|
|
**How to handle:** tsclientlib/tsproto handles encoding at the protocol layer. If encoding bugs are found, fix in the EdisonJwa/tsclientlib fork. Document any encoding-related issues here.
|
|
|
|
**Source:** YaTQA §1.3, ReSpeak §1.8.3
|
|
|
|
## 6. IPv6 Canonicalization Bug (LOW)
|
|
|
|
**What:** TS3 server 3.1.6-3.1.7 has IPv6 canonicalization bug in Blacklist2 protocol.
|
|
|
|
**Why it's a trap:** Connecting to older servers via IPv6 may trigger false blacklist matches.
|
|
|
|
**How to handle:** Be aware when connecting to older servers. Not actionable from client side.
|
|
|
|
**Source:** YaTQA §8.7
|
|
|
|
## 7. Channel Icon Semi-Permanent (MEDIUM)
|
|
|
|
**What:** `channel_icon_id` changes via `channeledit` are semi-permanent (lost on server restart).
|
|
|
|
**Why it's a trap:** Icon changes appear to succeed but revert after restart. Users may think their changes are persistent.
|
|
|
|
**How to handle:** Document this limitation in UI. Don't rely on channel icon persistence for critical features.
|
|
|
|
**Source:** YaTQA §4.2
|
|
|
|
## 8. Avatar Filename from Global ID (MEDIUM)
|
|
|
|
**What:** Avatar filename is derived from Global ID (not from avatar flag). Algorithm: Base64-decode Global ID → 20 bytes → display with `[a-p]` instead of `[0-9a-f]`.
|
|
|
|
**Why it's a trap:** Using the avatar flag directly as a filename will fail to find the cached avatar.
|
|
|
|
**How to handle:** Implement the Global ID → filename conversion. Store avatars in `cache/clients/` directory.
|
|
|
|
**Source:** YaTQA §1.5, §1.7
|
|
|
|
## 9. Snapshot SHA1 Hash Format (LOW)
|
|
|
|
**What:** Snapshot file starts with SHA1 hash of remaining UTF-8 data (excluding trailing newline). Internally runs Query commands when deploying.
|
|
|
|
**Why it's a trap:** Modifying snapshot data without recalculating the hash will cause deploy failure.
|
|
|
|
**How to handle:** If implementing snapshot import/export, always recalculate SHA1 after modification.
|
|
|
|
**Source:** YaTQA §1.6
|
|
|
|
## 10. BBCode Stack Limits (LOW)
|
|
|
|
**What:** BBCode max stack size 20, 10 tags can be active simultaneously. Self-closing `[hr]` doesn't count toward stack but can't be used at 20.
|
|
|
|
**Why it's a trap:** Complex channel descriptions with nested BBCode may be silently truncated or rejected.
|
|
|
|
**How to handle:** Validate BBCode depth before sending. Truncate if exceeding limits.
|
|
|
|
**Source:** YaTQA §1.8
|
|
|
|
## 11. Anti-Flood Server-Configurable (HIGH)
|
|
|
|
**What:** Anti-flood thresholds are server-configurable, not fixed. Key variables:
|
|
- `AntifloodPointsTickReduce` — points deducted per 0.5-second tick (TeaSpeak default: 25)
|
|
- `AntifloodPointsToCommandBlock` — threshold to block commands (TeaSpeak default: 150)
|
|
- `AntifloodPointsToIpBlock` — threshold to block IP (TeaSpeak default: 300)
|
|
|
|
**Why it's a trap:** Hardcoding flood thresholds will cause either over-aggressive throttling or server bans.
|
|
|
|
**How to handle:** Read flood config from `serverinfo` response. Use conservative defaults. Implement client-side flood tracking (TODO-064).
|
|
|
|
**Source:** YaTQA §5.1, ReSpeak §vars, TeaSpeak §vars
|
|
|
|
## 12. TeaSpeak Query Newline Divergence (INFO)
|
|
|
|
**What:** TeaSpeak changed ServerQuery line terminator from `\n\r` to `\n` in 1.4.14-beta6. TS3 uses `0x0A 0x0D`.
|
|
|
|
**Why it matters:** If Chanora ever adds ServerQuery support, must detect server type.
|
|
|
|
**How to handle:** Not relevant for voice client path (Chanora uses voice protocol, not query). Note for future reference.
|
|
|
|
**Source:** TeaSpeak §divergence-2
|
|
|
|
## 13. TeaSpeak Strict UTF-8 Mode (MEDIUM)
|
|
|
|
**What:** TeaSpeak has `strict_utf8_mode` config option that may reject non-UTF-8 strings.
|
|
|
|
**Why it's a trap:** Strings that pass through TS3 servers may be rejected by TeaSpeak servers.
|
|
|
|
**How to handle:** Ensure all outbound strings are valid UTF-8. Rust's `String` type guarantees this, but verify at protocol boundaries.
|
|
|
|
**Source:** TeaSpeak §config
|