Subject: [hybi] Multiplex examples & continuations

From: Joakim Erdfelt <[email-masked]>
Date: Wed, 24 Oct 2012 15:06:44 -0700

While parsing the examples at ...

https://tools.ietf.org/html/draft-ietf-hybi-websocket-multiplexing-08#section-10

The 2nd example says:

0x02 0x07 0x01 0x81 "Hello" 0x80 0x06 " world"

      This is a fragmented encapsulating message converying a non-
      fragmented text frame "Hello world" on logical channel 1.

So to translate what I see in this example.

2 WebSocket base frames.

Frame 1) WebSocket Frame #1

OpCode: BINARY (2)
Fin: False
RSV: None set
Masking: Not set
Payload: (7 bytes)
Mux Payload:
   Channel ID: 1
   OpCode: TEXT (1)
   Fin: True  <-- That right?
   RSV: None set
   Payload: "Hello" (UTF8 bytes)

Frame 2) WebSocket Frame #2

OpCode: CONTINUATION (0)
Fin: True
RSV: None set
Masking: Not set
Payload: (6 bytes)
(No mux encapsulation)

Is this behavior for Continuation frames correct?
Assume continuation frames belong to the last encapsulated data frame?
Also, is the first frame supposed to have encapsulated Fin=true?  Shouldn't
that be Fin=false?

Thanks again,

--
Joakim Erdfelt <[email-masked]>

---

From: Takeshi Yoshino <[email-masked]>
Date: Thu, 25 Oct 2012 17:39:47 +0900

Current multiplexing spec is message-based. It's no longer based on
frame-to-frame encapsulation approach. Each WebSocket "message" carries one
original frame.

In this example, the message (fragmented into two frames) carries
0x01(channel 1) 0x81(FIN, TEXT) "Hello world" that was originally 0x81 0x11
"Hello world" on the multiplexed connection (channel 1).

This allows intermediaries that doesn't understand multiplexing to safely
change fragmentation of received data without knowledge of multiplexing.

---

From: Joakim Erdfelt <[email-masked]>
Date: Thu, 25 Oct 2012 06:26:56 -0700

Not sure I understand that response. (sorry)

While from a reading/parsing point of view, this non-encapsulation of
continuations is a trivial nuance to support.
However the writing/generating side of this gets rather confusing.

So let me toss 2 use cases that highlight my concern here.

Use Case #1: Browser, large frames, no intermediary.

The browser has established mux, and has 3 active channels.
Each channel is doing roughly 2 frames a second, with an average payload
length of 1024 bytes.
Channel #3 now receives a big message (10MB), fragmented into 20 parts,
part #1 is 500k.
This message takes a while to send. (let say the connection is a mobile
phone on 3G)
Meanwhile, Channel #2 wants to also send a large message.
However, due to the continuations not being encapsulated or assigned to a
Channel ID, then Channel #2 cannot start to send its message until Channel
#3 has finished sending its Continuation + FIN frame.

Use Case #2: WebSocket + Mux aware corporate proxy.

An advanced web proxy setup at a corporation, handles WebSocket,
understands mux.
If a connection from the proxy out the internet to a web host that supports
mux is detected, then all WAN side websocket traffic, regardless if the WAN
side end point supports mux or not is proxied through this 1 LAN side mux
connection transparently.
In this scenario, channels wanting to send large messages with
continuations, again block all other channels wanting to use large messages.

There are clues in the spec that Use Case #1 can be handled via the various
flow control / send quota / new channel slot techniques in the protocol.
However, even those flow controls don't seem to indicate how to resolve
this large message + non-encapsulated continuations situation.
>From a receiving point of view, the important message details (TEXT+!FIN,
CONT+!FIN, ... , CONT+FIN) is either not preserved with the spec as it is,
or there is a likely scenario of blocking of other channels during large
messages, or I'm reading the spec wrong (the most likely case, heh)

---

From: Takeshi Yoshino <[email-masked]>
Date: Fri, 26 Oct 2012 01:00:45 +0900

> #3 has finished sending its Continuation + FIN frame.
Please take a look at the third example. You can insert the large message
of the Channel #2 between the 500k chunks of the Channel #3.

Each of the 500k chunks are converted into encapsulating messages by
multiplexor like:
(FIN=true, op=Binary) (Mask=false, LEN=500k+2) (channel ID=2) (FIN=false,
op=<type of the message>) <...500kBdata...>
(FIN=true, op=Binary) (Mask=false, LEN=500k+2) (channel ID=2) (FIN=false,
op=continuation) <...500kBdata...>
...
(FIN=true, op=Binary) (Mask=false, LEN=500k+2) (channel ID=2) (FIN=true,
op=continuation) <...500kBdata...>

Channel #2's large message e.g. (FIN=true, op=text) (mask=false, len=100k)
<HelloHelloHello...>
is converted into an encapsulating message:
(FIN=true, op=Binary) (Mask=false, LEN=100k+2) (channel ID=3) (FIN=true,
op=text) <HelloHelloHello...>

So, the following is a valid sequence of encapsulating messages without any
ambiguity:

(FIN=true, op=Binary) (Mask=false, LEN=500k+2) (channel ID=2) (FIN=false,
op=<type of the message>) <...500kBdata...>
(FIN=true, op=Binary) (Mask=false, LEN=100k+2) (channel ID=3) (FIN=true,
op=text) <HelloHelloHello...>
(FIN=true, op=Binary) (Mask=false, LEN=500k+2) (channel ID=2) (FIN=false,
op=continuation) <...500kBdata...>
...
(FIN=true, op=Binary) (Mask=false, LEN=500k+2) (channel ID=2) (FIN=true,
op=continuation) <...500kBdata...>

The second example in the spec is just saying that we can fragment messages
output by multiplexor (Note that here we're manipulating output of
multiplexor. We're not multiplexor. So at this point it's not allowed to
reorder messages to interleave messages encapsulating frames of different
channels.)

Maybe, it was confusing that I placed example #2 (that is just telling that
multiplexor's output is safe to be fragmented) before example #3 that is
explaining how multiplexing is done.

> If a connection from the proxy out the internet to a web host that
> supports mux is detected, then all WAN side websocket traffic, regardless
> if the WAN side end point supports mux or not is proxied through this 1 LAN
> side mux connection transparently.
> There are clues in the spec that Use Case #1 can be handled via the
> various flow control / send quota / new channel slot techniques in the
> protocol.

---

From: Takeshi Yoshino <[email-masked]>
Date: Fri, 26 Oct 2012 16:24:06 +0900

This is revised version of the Examples section to be published as -09.
Changed the order of examples.

10.  Examples

   _This section is non-normative._

   The examples below assume the handshake has already completed and the
   multiplexing extension was negotiated.  Quotes are for clarity.

   Frames of encapsulating messages from client to server MUST be
   masked.  The examples below are not masked for simplicity.

   0x82 0x0d 0x01 0x81 "Hello world"

      This is a non-fragmented text message of "Hello world" on logical
      channel 1 encapsulated into a non-fragmented encapsulating
      message.

   0x82 0x07 0x01 0x01 "Hello" 0x82 0x08 0x01 0x80 " world"

      This is a text message of "Hello world" fragmented into two frames
      of "Hello" and " world" on logical channel 1 encapsulated into two
      non-fragmented encapsulating messages.  A multiplexor may change
      fragmentation of a message before encapsulation like this so that
      frames of other logical channels (including the control channel)
      can be injected in the middle of the message.

   0x82 0x07 0x01 0x01 "Hello" 0x82 0x05 0x02 0x81 "bye" 0x82 0x08 0x01
   0x80 " world"

      This example shows how data for two logical channels are
      interleaved.  There're three non-fragmented encapsulating
      messages.  As explained in the previous example, the text message
      of "Hello world" is split into two frames before encapsulation.
      The first and third frame in this example contain each of the two
      fragments of the text message of "Hello world" on logical channel
      1.  The second frame contains a non-fragmented text message of
      "bye" on logical channel 2.

   0x82 0x04 0x01 0x01 "Te" 0x82 0x04 0x01 0x09 "Pi" 0x82 0x04 0x01 0x80
   "ng" 0x82 0x04 0x01 0x80 "xt"

      A ping message "Ping" is injected in the middle of a text message
      "Text" on the original connection.  The multiplexor fragmented the
      ping message due to some reason into two fragments.

      Encapsulating messages output from the multiplexor can be
      fragmented by intermediaries without knowledge of the Multiplexing

Tamplin & Yoshino        Expires April 29, 2013                [Page 28]
Internet-Draft   A Multiplexing Extension for WebSockets    October 2012

      Extension.  This is an example of a fragmented encapsulating
      message.  It's equivalent to the first example as a message.

   0x82 0x15 0x00 0x01 0x02 0x12 "GET / HTTP/1.1" 0x0d 0x0a 0x0d 0x0a

      This is a message on the control channel carrying one
      AddChannelRequest.  The first two octets are the WebSocket
      headers.  The 3rd octet is logical channel ID field of 0.  The 4th
      octet has opcode, RSV and Enc field.  Objective channel ID is 2.
      The handshake is delta-encoded.