how/ - how things work (terrain generation, command system) why/ - design philosophy (telnet-first, text worlds) lessons/ - things we learned the hard way (charset vs mtts) Removes notes/ — DAYDREAMING.txt became DREAMBOOK.md, charset-vs-mtts expanded into docs/lessons/ with the connect_maxwait fix documented.
72 lines
2.5 KiB
Text
72 lines
2.5 KiB
Text
charset negotiation vs mtts: why tintin++ says WILL then REJECTED
|
|
=================================================================
|
|
|
|
the problem
|
|
-----------
|
|
|
|
telnetlib3 defaults to connect_maxwait=4.0, waiting for CHARSET encoding
|
|
negotiation to resolve. MUD clients like tintin++ reject CHARSET but advertise
|
|
encoding support through MTTS instead. result: 4 seconds of dead air on every
|
|
connection.
|
|
|
|
the fix (our side)
|
|
------------------
|
|
|
|
pass connect_maxwait=0.5 to create_server(). the actual option negotiation
|
|
finishes in ~500ms. CHARSET gets rejected almost immediately but telnetlib3
|
|
doesn't have a fallback path — it just waits for the timeout. 0.5s is plenty.
|
|
|
|
server = await telnetlib3.create_server(
|
|
host="127.0.0.1", port=PORT, shell=shell, connect_maxwait=0.5
|
|
)
|
|
|
|
the upstream fix (telnetlib3)
|
|
-----------------------------
|
|
|
|
when CHARSET is rejected, telnetlib3 could check MTTS bit 3 for UTF-8 support
|
|
and resolve encoding immediately instead of running out the clock. this would
|
|
be a good contribution. the data is already there:
|
|
|
|
MTTS 2825 → bit 3 set → client supports UTF-8
|
|
|
|
what happens on the wire
|
|
------------------------
|
|
|
|
telnetlib3 sends DO CHARSET. tintin++ responds WILL CHARSET ("i know what that
|
|
is") then immediately REJECTED ("but i don't want to use it"). this is normal
|
|
for MUD clients — they prefer MTTS.
|
|
|
|
+0.000 server send DO CHARSET
|
|
+0.100 client recv WILL CHARSET
|
|
+0.100 server send SB CHARSET REQUEST UTF-8 ... US-ASCII
|
|
+0.200 client recv SB CHARSET REJECTED
|
|
|
|
meanwhile, in the same negotiation, tintin++ already told us via MTTS:
|
|
|
|
ttype3: MTTS 2825
|
|
bit 0 (1) = ANSI color
|
|
bit 3 (8) = UTF-8
|
|
bit 8 (256) = 256 colors
|
|
bit 9 (512) = OSC color palette
|
|
bit 11 (2048) = true color
|
|
|
|
two protocols, one answer. MTTS (via TTYPE round 3) is what the MUD ecosystem
|
|
uses. RFC 2066 CHARSET is technically correct but practically ignored.
|
|
|
|
will echo and mud clients
|
|
-------------------------
|
|
|
|
related discovery: telnetlib3 intentionally skips WILL ECHO for detected MUD
|
|
clients. tintin++ is in the MUD_TERMINALS fingerprint list. MUD clients
|
|
interpret WILL ECHO as "password mode" and mask input, so the server avoids
|
|
sending it. the client handles its own local echo.
|
|
|
|
this means will_echo is always False for tintin++, and that's correct. don't
|
|
try to fight it or wait for it.
|
|
|
|
see also
|
|
--------
|
|
|
|
- MTTS spec: https://tintin.mudhalla.net/protocols/mtts/
|
|
- RFC 2066: CHARSET option
|
|
- telnetlib3 source: server.py _negotiate_echo(), fingerprinting.py _is_maybe_mud()
|