4

I've written a WebSocket in C# and am trying to implement the permessage-deflate extension. It seems that the C# DeflateStream is unable to decompress message payloads sent from Chrome (Version 36.0.1985.143 m) - the only one I've tried so far. I am getting the "Block length does not match with its complement" message when trying to decompress. It's not the RFC 1950, RFC 1951 2 byte header problem.

I've used the DeflateStream in C# to compress the same data (the string 'Hello'), in an attempt to see the difference in the compressed data. Oddly enough the compressed Chrome payload and C# compressed data is exactly the same except for the first byte! The first byte of the Chrome payload is always 1 less than the first byte, even when changing the sample compression string from 'hello' to anything else. I can simply add 1 to the first byte and the payload decompresses.

I found a Compression Extensions for WebSocket draft that discusses this issue but does not solve the problem for C#.

Section 8.2.3.1 uses the 'Hello' sample string and shows the correct compressed payload: 0xf2 0x48 0xcd 0xc9 0xc9 0x07 0x00

Section 8.2.3.4 then goes on to discuss using a Deflate block with BFINAL set to 1 which produces: 0xf3 0x48 0xcd 0xc9 0xc9 0x07 0x00 0x00

The 0xf3 data is what the C# DeflateStream compresses and decompresses without problems. It seems that there is a deflation option in the algorithm that involves BFINAL and that C# does not offer this setting?

I'm hoping someone might be familiar with this problem or know how to work around the issue. I'd prefer not to link in a 3rd party lib if possible.

Thanks.

Community
  • 1
  • 1
Michael
  • 53
  • 1
  • 5

2 Answers2

2

It's using the PPP protocol, which drops 0x00 0x00 0xff 0xff from the end of the deflate stream before transmitting. Just append those four bytes before feeding it to the decompressor.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
1

I develop a Websocket component in C# that supports deflate compression.

First of all, you cannot compress the full connection, because how DeflateStream buffers data. You can compress messages. In other words, it won't support context take over, and you have to indicate so in the HTTP negotiation.

Also, when you are done flusing your DeflateStream you must write a byte 0 to the stream. Please check my source code involved in writting compressed messages.

In the Deflate WebSocketListener extension you can find examples of how is:

vtortola
  • 34,709
  • 29
  • 161
  • 263