[undertow-dev] websocket per-message compression & design q

Stuart Douglas sdouglas at redhat.com
Wed Aug 12 00:51:58 EDT 2015



----- Original Message -----
> From: "peter royal" <peter.royal at pobox.com>
> To: undertow-dev at lists.jboss.org
> Sent: Tuesday, 11 August, 2015 4:31:52 AM
> Subject: [undertow-dev] websocket per-message compression & design q
> 
> Hi!
> 
> I'm trying to debug the problems I've encountered after enabling
> per-message compression on websockets in 1.2,
> https://issues.jboss.org/browse/UNDERTOW-508
> 
> One thing I've noticed is that there's an entirely different code path
> used inside of WebSocket07FrameSinkChannel whenever extensions are
> enabled. I was trying to think of how to refactor how extensions are
> applied so that it would be a path that is always-on, and thus hopefully
> subject to more scrutiny and use.

A refactor of this code has been on my TODO list for a while, but I have not got to it.

> 
> Conceptually, extensions are transformations to the ByteBuffer that
> makes up a message payload. I think the internals might be a bit clearer
> if they were treated as that, and then always applied. (the
> ExtensionByteBuffer class is something I'd want to eliminate).

Agreed

> 
>  From an internal API point of view, calls to write on a websocket are
> mostly made via the WebSockets class, and then a couple of places that
> use the StreamSinkFrameChannel (SSFC) over a longer period of time for
> partial messages and streams in the WS JSR implementation.
> 
> For sending, the GatheringByteChannel APIs are used to represent writing
> a message. A collection of writes to a single SSFC will result in 1..n
> WS message fragments depending on how large the buffers returned from
> the allocator are. When using extensions, there are a bunch of
> ergonomics regarding the return value from write and remaining bytes in
> the provided buffers to enable
> 
> For the WebSockets send methods, all the data to send is already in
> memory, and the methods just spin or wait over the SSFC writing
> fragments until all the data is sent. Then there are the blocking APIs
> in the JSR that send a single fragment and wait for it to be flushed.
> 
> I think it might be cleaner to push some of that responsibility from the
> WebSockets utility class into the WebSocket07FrameSinkChannel. For the
> non-blocking cases, that'd be merging the following two lines from
> WebSockets into a single call,
> 
>      StreamSinkFrameChannel channel = wsChannel.send(type, totalData);
>      WebSockets.sendData(data, wsChannel, callback, channel, null,
> timeoutmillis);

Something we have been talking about for a while is the introduction of a
different underlying API than the XNIO Channel, probably taking a form
similar to send(Pooled<ByteBuffer> buff), where the caller basically just
transfers 'ownership' of the buffer to the underlying sender.

For websockets this would definitely make the extension implementation much
easier.

> 
> The channel can then apply the extensions to data and do the appropriate
> thing. Similar changes would happen to the blocking methods.
> 
> I realize this is a bit ramble-y, but I wanted to at least get some of
> my thoughts out there. I'm eager to get WS extensions working fully, and
> thought that re-architecting how the sending of WS messages happen might
> make the code less brittle and easier to maintain

I have not looked at this code in a while, I will try and get to your WS bug some time this week.

Stuart

> 
> -pete
> 
> 
> 
> --
> (peter.royal|osi)@pobox.com - http://fotap.org/~osi
> _______________________________________________
> undertow-dev mailing list
> undertow-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/undertow-dev
> 


More information about the undertow-dev mailing list