mu*index
reading
theme
MCCP  [protocol]
Stream compression. Cheap, widely deployed, and the protocol that produced the
most instructive bug in this project's history.
https://www.mudhalla.net/tintin/protocols/mccp/

Measured adoption
  216 of 886 listed games were observed offering it (24.4%)
  /games?protocol=MCCP

  The games not counted here are not games without the protocol. A game is
  counted when we observed its server offering the option in a handshake; the
  rest are servers that did not offer it to us and servers whose handshake we
  have not read, and we cannot tell you which.

  By codebase, of the games we identified
    CoffeeMUD            31 of 32 offered it
    FluffOS              24 of 28 offered it
    ROM                  13 of 55 offered it
    Evennia              11 of 11 offered it
    DikuMUD              8 of 35 offered it
    CircleMUD            4 of 47 offered it
    MUCK                 3 of 24 offered it
    SMAUG                2 of 20 offered it
    AresMUSH             0 of 18 offered it
    CobraMUSH            0 of 2 offered it
    PennMUSH             0 of 34 offered it
    RhostMUSH            0 of 40 offered it
    tbaMUD               0 of 5 offered it
    TinyMUSH             0 of 9 offered it

MCCP compresses the server-to-client stream with zlib. Version 1 is telnet
option 85 and is effectively historical; version 2 is option 86 and is what
modern servers negotiate. After the server sends IAC SB MCCP2 IAC SE, every byte
that follows is part of one continuous zlib stream.

It is a real saving on a text protocol — MUD output compresses extremely well —
and it is common in the Diku and LP families, where roughly a third of the
codebases we surveyed negotiate it.

THE FAILURE MODE, AND WHY IT MATTERS HERE

A client that negotiates MCCP2 and then does not inflate the stream receives
binary garbage from the compression marker onward. Not an error, not a
disconnection: the connect screen arrives as a wall of replacement characters,
and everything after it — the WHO reply, any later MSSP, the whole session — is
lost.

This is not hypothetical. Our own telnet library did exactly that. It negotiated
the option, fired its "compression enabled" callback, and never inflated a byte.
The payload decompressed cleanly with a stock zlib call, which is what made it
unambiguous that the servers were correct and we were not. Thirteen of the
thirty-eight codebases in our survey were affected, and for the duration we
could not observe what those servers negotiated after compression started — so
our record of their capabilities understated them.

It was fixed upstream. A follow-on defect — the inflater being re-created per
read rather than kept for the connection, which fails partway through a large
connect screen — is filed and open, and affects the tail of the largest screens.

Two things a reader should take from this. A protocol figure on this page is a
measurement of our crawler as much as of the hobby, and where we know it has
been wrong we say so. And if you are writing a client: negotiating MCCP is easy
and inflating it correctly is where the work is.

See also
  ROM — /reference/codebases/rom
  DikuMUD — /reference/codebases/dikumud
  GMCP — /reference/protocols/gmcp