MCCP and OnPluginPacketReceived

Posted by Worstje on Tue 16 Sep 2008 02:43 PM — 5 posts, 15,718 views.

Netherlands #0
So, I ran into some issues getting a plugin of mine working with a friend. 15 minutes of debugging and a 'Debug packets' later showed me that MCCP was being negotiated. I myself didn't even recall ever turning it off for my own settings (and all other worlds were copied off this one, so I never ran into it again), but I found out I was trying to apply negotiation protocols to uncompressed data. Well, that makes for some awesome fireworks once you start replacing certain bytes.

I read the MCCP spec just now and the following cropped up:

Quote:
Once compression is established, all normal telnet communication takes place "within" the compressed stream. That is, instead of communicating directly with the network, the telnet implementation should communicate with the compression system. Telnet command sequences (IAC ...) are compressed like any other data. IAC bytes within the resulting compressed stream are not escaped in any way.


Source: http://mccp.smaugmuds.org/protocol.html

Part of me doesn't think it is wise to start decrypting all the compressed data manually when MUSHclient is doing it already. That and it would be slowish and all that too, I reckon.

For the time being, I've told my friend to just select the Disable Compression setting... but in the long term, it would be nice if there was a step inbetween the 'raw packet data' and 'executing triggers': the step that goes 'decompressed packet data'.

.. Does that make any sense at all? I blame sleep.:)
Netherlands #1
Bump-a-dump. Nick, did you miss this post per chance? :)
Australia Forum Administrator #2
Sorry, it's been a hectic week.

What actually happens in OnPluginPacketReceived is that you get the decompressed data. However there is a catch. There is one, and only one, packet which may have a combination. Here is how it works:


< uncompressed data > < turn on MCCP > < compressed data >


Prior to this packet arriving, you get the raw packets, and can change them as you like. After this packet, you get the decompressed data, and again can change it as you like.

However on this one packet, if you do some sort of global change (eg. change linefeeds into carriage-return linefeed) and there happens to be what looks like a linefeed in the compressed stream, then it will corrupt the compressed data, and decompression will fail.

This probably isn't normally a problem if you are finding stuff like prompts, and adding a newline, because something that looks like a prompt probably won't occur in that problem packet.

I'm not sure of a fantastically good workaround. One would be:

  • If you know that you will eventually get compressed data, don't do any replacements until you detect compression is on (GetInfo (103)). However unless it is for a particular MUD, you won't necessarily know to wait.
  • If compression is off, don't do replacements in any packet which has the telnet sequence in it to turn it on - this would be the problem packet I described.


Netherlands #3
Okay. I'll see how I'll modify this plugin to deal with these nasty situations. I take it I can use utils.decompress(compressed_text) for every packet?

Edit: And sorry if I seemed impatient. I had seen you reply in other topics and you generally don't skip them. Thanks for all the good work! ^_^
Amended on Fri 19 Sep 2008 06:14 AM by Worstje
Australia Forum Administrator #4
You were right to remind me, with all the stuff that is going on, I responded to the ones I could answer quickly, and yours slipped off the radar.

Quote:

I take it I can use utils.decompress(compressed_text) for every packet?


No, you can't. The decompression algorithm takes the compressed text as a whole stream, not on a packet-by-packet basis. That way, any word that occurs frequently (eg. "dungeon") will be compressed more favourably later on, even if the earlier occurrences were hours ago.

Whilst it is the same algorithm (zlib) you can't selectively apply it, in much the same way that you can't take part of a .zip file and decompress it. For one thing, zlib actually has different algorithms and the header of the compressed stream specifies which algorithm (or variant) is in use.

Your only real recourse is to defer processing (if the processing involves replacement) until compression has started up. This is usually very early in the MUD startup. Another approach is to simply test for the "start compression" telnet sequence, and simply ignore that one packet that has it, but process all the others (if compression is currently off).