Subject: [hybi] Regarding "what parts of a frame should be masked"

From: Philipp Serafin <[email-masked]>
Date: Wed, 30 Mar 2011 21:16:28 +0200

Hello everyone,

in the HYBI session yesterday, there was a discussion about whether the
whole part of a WS frame should be masked or only payload and extension
data. The question was then moved to the mailing list.
I'm a CS student who is following this list out of interest (so please
forgive me if I say something stupid - I'll try not to :) ) and I
started roughly implementing the current draft to play around with the
technology.

I noticed that implementing the masking becomes somewhat easier if the
length field is not masked. Because the masking key changes with each
frame, you obviously need to know the length of the frame before you can
unmask anything past the header. If the header (particularly the length
field) is masked as well, this means you need a separate unmasking
routine for the header. In contrast, if the length is unmasked, you can
simply read the whole frame into a buffer and then unmask it in one go.

Both options are definitely "I can live with it". However, since there
didn't seem to be any strong points for or against either option in the
meeting, I'd like to give implementation complexity as an argument in
favour of "don't mask the header".

Regards,
Philipp Serafin

---

From: Andy Green <[email-masked]>
Date: Wed, 30 Mar 2011 20:41:21 +0100

> favour of "don't mask the header".

I agree with you.

It's worth reviewing this thread from 8th March

http://www.ietf.org/mail-archive/web/hybi/current/msg06796.html

which clearly sets out that and other views so you can understand the 
environment around the issue as well as the issue itself.

-Andy

---

From: Brian McKelvey <[email-masked]>
Date: Wed, 30 Mar 2011 13:47:41 -0700

Yeah.  As I've stated before, I'm strongly in favor of masking only the payload.

Relatedly, as others have also discovered, while implementing the deflate-stream extension in my client, it became obvious that having a separate and random masking key for each frame drastically reduces the effectiveness of the deflate-stream extension.  Has anyone given much thought to a deflate extension that operates on the data before masking?  That would allow us to use a larger sliding window and substantially improve the compression ratio on a large class of data.  Libwebsockets for example uses an 8-bit window size, which is pretty limited compared to the zlib default, but that makes sense given that none of the data from previous frames is likely to be usable in a larger window because of the masking.  I seem to recall some discussion of this before but my memory is a bit fuzzy.  (as an interesting implementation note, java's JZlib and subsequently the AS3 port as3zlib have a minimum allowed window size of 9 for deflate, not 8 as in C zlib)

Brian

Sent from my iPhone

On Mar 30, 2011, at 12:41 PM, Andy Green <[email-masked]> wrote:

> which clearly sets out that and other views so you can understand the environment around the issue as well as the issue itself.
> 
> -Andy
> _______________________________________________
> hybi mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/hybi

---

From: John Tamplin <[email-masked]>
Date: Wed, 30 Mar 2011 16:58:23 -0400

On Wed, Mar 30, 2011 at 4:47 PM, Brian McKelvey <[email-masked]>wrote:

> Relatedly, as others have also discovered, while implementing the
> deflate-stream extension in my client, it became obvious that having a
> separate and random masking key for each frame drastically reduces the
> effectiveness of the deflate-stream extension.  Has anyone given much
> thought to a deflate extension that operates on the data before masking?
>  That would allow us to use a larger sliding window and substantially
> improve the compression ratio on a large class of data.  Libwebsockets for
> example uses an 8-bit window size, which is pretty limited compared to the
> zlib default, but that makes sense given that none of the data from previous
> frames is likely to be usable in a larger window because of the masking.  I
> seem to recall some discussion of this before but my memory is a bit fuzzy.
>  (as an interesting implementation note, java's JZlib and subsequently the
> AS3 port as3zlib have a minimum allowed window size of 9 for deflate, not 8
> as in C zlib)
>

Yes, there were discussions of better compression algorithms --
"deflate-stream" was included as a better-than-nothing case nobody objected
to that also served as an example extension.  However, I don't think
anything else is going to happen before the spec is finished, so other
compression schemes will be extensions defined later.

Personally, I think an effective compression scheme has to include some way
of not compressing incompressible data, which means it has to be on a
per-message basis (however, hopefully you would maintain compression state
across the stream) that would avoid framing data cluttering up the
compression dictionary.  There also needs to be consideration of memory
requirements on the server, which means restricting the compression
parameter choices on the client so the server doesn't have to keep large
compression state for each of many simultaneous connections.

-- 
John A. Tamplin
Software Engineer (GWT), Google

---

From: Greg Wilkins <[email-masked]>
Date: Thu, 31 Mar 2011 09:09:29 +1100

Brian,

This is a good reason that masking should be treated as a mandatory
extension applied only to the payload.
As an extension, it could be ordered against other extensions so we
could have per frame compression applied to the payload before masking
is applied.

regards

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Thu, 31 Mar 2011 00:14:40 +0200

* John Tamplin wrote:
>compression dictionary.

Could you elaborate on this problem? A deflate stream, whether in a gzip
or zlib container or not, is composed of a number of blocks which an en-
coder can make up as it sees fit. There are three block types, one with
dynamic codes, one with pre-defined codes, and one using no compression;
whichever you choose, incompressible data is stored reasonably well; if
you make the worst possible encoder, there is a low maximum overhead of
somewhere around 15% as I understand it. If you want Deflate blocks and
Websocket frames to synchronize, things might be a bit worse, but in ge-
neral I am not sure I understand the problem here.
-- 
Björn Höhrmann · mailto:[email-masked] · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

---

From: Brian McKelvey <[email-masked]>
Date: Wed, 30 Mar 2011 16:39:22 -0700

The problem is that the compression state, which is maintained across frames, is polluted with unusable data from previous frames.  It's unusable because the per-frame masking Is applied before the deflate processor.  Because every frame is obfuscated with a different key, the chances of being able to use compression state from previous frames to help compress subsequent frames are very low.

If the compression was applied to the payload data before masking, we would be able to use a lot more data from previous frames in the compression.

I'm ok with leaving it as-is for the initial release and defining a new, more efficient compression extension in the future to alleviate this problem.  Just wanted to see what others had thought about on the topic.

Also, this problem only applies to data sent client->server, since the server-sent data is not masked.  The only nit to pick there, as was mentioned, is the framing header data cluttering up the compression state, but that's probably not a very big deal comparatively.

Brian

Sent from my iPhone

On Mar 30, 2011, at 3:14 PM, Bjoern Hoehrmann <[email-masked]> wrote:

> Björn Höhrmann ·mailto:[email-masked] ·http://bjoern.hoehrmann.de
> Am Badedeich 7 · Telefon:+49(0)160/4415681 ·http://www.bjoernsworld.de

---

From: "Martin J. Dürst" <[email-masked]>
Date: Thu, 31 Mar 2011 09:40:37 +0900

It's totally obvious that randomizing first and then trying to compress 
later is totally the wrong way round. I'm fine with doing it the right 
way in a second round if there are enough hooks in the current spec that 
it isn't impossible.

Regards,   Martin.

---

From: Patrick McManus <[email-masked]>
Date: Thu, 31 Mar 2011 08:24:00 +0200

On 3/31/11 2:40 AM, "Martin J. Dürst" wrote:
> It's totally obvious that randomizing first and then trying to 
> compress later is totally the wrong way round. I'm fine with doing it 
> the right way in a second round if there are enough hooks in the 
> current spec that it isn't impossible.
we don't even need a second round of the whole protocol - just publish a 
doc for the local-compression extension and define it this other way. 
deflate-stream is just a (well known) extension negotiated at handshake 
time like every other potential extension.

---

From: Andy Green <[email-masked]>
Date: Thu, 31 Mar 2011 07:57:56 +0100

On 03/30/2011 11:09 PM, Somebody in the thread at some point said:

Hi -

> could have per frame compression applied to the payload before masking

This is a very good point.  Architecturally, it would simplify the issue 
into just precedence between compression and masking extensions that 
otherwise are nicely contained in individual domain-specific extension code.

At the moment with masking not even subordinate to the framing action, 
it just blasts in there dumping keys and munging data right in the code 
that writes out frames.

-Andy