----- Original Message -----
From: "peter royal" <peter.royal(a)pobox.com>
To: undertow-dev(a)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)(a)pobox.com -
http://fotap.org/~osi
_______________________________________________
undertow-dev mailing list
undertow-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/undertow-dev