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.
5.9 KiB
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