MUME / play-mume

Modern web client for MUME using DecafMUD
https://mume.org/play/browser
GNU General Public License v2.0
2 stars 2 forks source link

Support MCCP2 Compression #3

Closed nschimme closed 2 years ago

nschimme commented 2 years ago

Consider porting from: https://github.com/dak/discworld/blob/master/lib/mudkit.js

Tiger-Tom commented 2 years ago

Possible fix in my fork: https://github.com/Tiger-Tom/DecafMUD MUME appears to have a malformed Zlib heading or something similar, as some characters are replaced with \u0, and most Zlib ports I try will refuse to decompress the data, but other Telnet MUD servers appear to work just fine.

gustavh commented 2 years ago

I'm somewhat sure MUME's implementation of MCCP2 does the right thing. Immediately following IAC SB MCCP2 IAC SE, you will get a (raw) zlib stream, without any additional header. For example in Python you can deflate it using zlib.decompressobj().decompress(binarydata) which will return the telnet (rfc854) stream.

Tiger-Tom commented 2 years ago

No matter what I do, it seems that random characters are removed, and when I try some of it in Python (the rest of the chunk, right after IAC SB COMPRESSv2 IAC SE), it results in error -3, incorrect header check. I really am quite stumped, do you have any ideas @gustavh ?

Tiger-Tom commented 2 years ago

The IAC sequences seem to work just fine as well, it's just that some characters seem to be being replaced by \0 in the Javascript one. Again, when I try it in Python, it just fails completely. This is in the newer version that I just uploaded to my repository, but I have run into this issue many times.

gustavh commented 2 years ago

Note that the compressed stream should contain no gzip-like header. The following Python3 script works for me:

import asyncio
import zlib

async def client():
    reader, writer = await asyncio.open_connection(
        'mume.org', 4242)

    # IAC DO MCCP2
    writer.write(b'\xff\xfd\x56')

    # CR LF + CR LF will close the connection
    writer.write(b'\r\n\r\n')
    await writer.drain()

    data = await reader.read()

    # split on IAC SB MCCP2 IAC SE
    raw, zip = data.split(b'\xff\xfa\x56\xff\xf0')

    zip = zlib.decompressobj().decompress(zip)

    print(f"RAW:\n{raw!r}\n\n")
    print(f"ZIP:\n{zip!r}\n")

asyncio.run(client())
Tiger-Tom commented 2 years ago

Thanks, hopefully I've got it working now!

Tiger-Tom commented 2 years ago

Should be fixed, thanks for the help!

nschimme commented 2 years ago

Implemented thanks to @Tiger-Tom in https://github.com/MUME/DecafMUD/pull/2