Subject: [hybi] Retitled: Poor Use of subprotocol; Probably should be supraprotocol (or client protocol)

From: "Bob Gezelter" <[email-masked]>
Date: Tue, 23 Aug 2011 03:17:33 -0700

Brian,

For clarity, I am combining my response to your messages from 0457Z and
0520Z today into a single message. I have correspondingly merged the
CC'courtesy lists.

Your posting crystallized an issue that has long disturbed me about the
WebSocket protocol specification, the co-characterization of what are
deemed protocol extensions (e.g., John's multiplexing draft) with user
applications protocols. In architectural terms, one (multiplexing) is a
horizontal technology, applicable to all protocol users; the other is a
vertical, useful to to a discrete, far smaller audience.

By this token, I also respectfully disagree with Bruce's comment about
reassigning op codes.

This commingling produces the appearance of cross-connections where
there are truly none. It is also not necessary.

The binary/text dichotomy is an artifact of the original conception. I
agree (emphasis: AGREE) that the programmer's ability to send text
messages FROM THE WEBSOCKET API (WSAPI) SHOULD REMAIN UNCHANGED
[apologies for the capitalization, but there is no other way to show
emphasis in US ASCII-7]. 

Recently, it was observed that the desired state was to be able to
interleave, on a message-to-message basis, text and binary messages on a
single channel. The precise reference was to text control messages, and
a binary version of a JSON object. This example is reasonable, but it
also illuminates my point: There must be far more agreement between the
respective communicating entities than the text/binary dichotomy.

I forget the message, but it was also raised that imposing the
UTF-8/binary transformation on the programmer is unreasonable. Once
again, I agree with the statement, but NOT WITH THE END RESULT. 

The present Structure is:

Client WSAPI
  |
Client WebSocket Protocol (text/binary records)
  |
Server WebSocket Protocol (text/binary records)
  |
Server WSAPI 

What I am proposing is:

Client WSAPI
  |
Client WSAPI App (text/binary records)
     |
   Client WebSocket Protocol (binary records)
     |
   Server WebSocket Protocol (binary records)
     |
Server WSAPI App (text/binary records)
  |
Server WSAPI 

Despite the change in the structure diagram, I must emphasize that this
change is almost completely an editorial change in documentation. There
are no needs for additional layers of code. All code already exists in
WSAPI. The one change is the elimination of the text/binary dichotomy at
the level of the WebSocket protocol and the corresponding change in a
handful of parameter lists and data structures. User code that runs
today before the change runs tomorrow after the change.

You put it well, that the purpose of WebSockets (the API) is to enable
JavaScript programmers to easily develop browser-based communications.
None of the changes that I am proposing will have any effect on those
JavaScript programmers.

It will have a positive effect however, on the wide-range of developers
who need to develop tools and devices where a thorough understanding of
the protocol is essential to ensure correct operation.

- Bob Gezelter, http://www.rlgsc.com

---

From: Brian <[email-masked]>
Date: Tue, 23 Aug 2011 04:52:35 -0700

I get what you're saying here, but how can today's code (separate text vs.
binary opcodes) interoperate with "tomorrow's" spec (only a binary opcode)?
 JavaScript code using the WebSocket API could remain unchanged, yes, but in
order to perform the separation you're suggesting, there would have to be
some kind of preamble in the application data section of the binary frame to
indicate whether to interpret the data as UTF-8, and according to your
suggestion as I understand it, that preamble would be under the purview of a
separate specification.  And to what end really?

This is all so simple and straightforward already I really don't see the
point of the extra bureaucratic nonsense required to perform such an
extraction.  I would be opposed to based on the extra red-tape, delays (no
matter how short you feel they might be), and the formation of yet another
working group to build yet another specification.  I can't imagine that
could all get done in any less 6 months, optimistically speaking.  The
concept of separating out the tagging of "content-type" is a fine idea on
its own, but given that we're all getting really antsy for this protocol to
be released, it's incredibly depressing to think about doing something like
that for such a simple two-case scenario, especially when we're so close to
the finish line.

It's not like we support arbitrary content types or text encodings.  The
understanding of how to interpret the contents of text or binary messages,
whether to expect text messages, binary messages, or both, is all up to the
end-user of the WebSocket API when he defines the subprotocol for his
individual specific application.  Most such developers will simply use JSON
in "text" messages because it's easy, and users that want to use a binary
format will define which serialization format to use for their newly-minted
"SuperUltraChat" subprotocol as they please.  We really don't need any kind
of content-type encoding or tagging in this protocol (or the
meta-application-protocol you're suggesting) at all except for the one
convenience case.  I don't think I'd even want it to get any more complex
than utf-8 vs. raw binary.  The simplicity of that limitation is what makes
it so convenient for so many things.

The thing is.. there really are only two types of messages.  It's not that
hard.  And since utf-8 is "The One True Encoding," there is no need for
misdirection in talking about antiquated problems like character set
conversions or line-ending mangling or anything else of that sort.  The text
frame is a simple additional case that's really not that hard to comprehend
in the specification's current format.  I got through building my Websocket
client & server implementation with shockingly few questions, and had none
about the distinction between text or binary messages, or when to use or not
to use utf-8.

The formality of separating all that into its own specification, like many
other things discussed on this working group, could absolutely be done in a
later revision of the protocol, where the "text" message would be deprecated
in favor of using only the "binary" message type in conjunction with the new
meta-application-level protocol that you're suggesting.  I feel
exceptionally strongly against holding up the release of WebSockets for this
issue.

Cheers,
Brian

---

From: Brian <[email-masked]>
Date: Tue, 23 Aug 2011 05:14:42 -0700

One more comment.. All this over-engineering business about separating out
the existing super-simple text vs. binary distinction reminds me
frighteningly of the famous hammer factory factories in this classic rant on
the Joel on Software forums here:
http://discuss.joelonsoftware.com/default.asp?joel.3.219431

---

From: Bruce Atherton <[email-masked]>
Date: Tue, 23 Aug 2011 09:46:10 -0700

> vertical, useful to to a discrete, far smaller audience.

I agree that these are different things, but if by "co-characterization" 
you mean the spec mixes these two concepts, I disagree. There is a 
reason that there are two separate headers, one for extensions and one 
for the application protocol.

On this list in the past there have been people who wondered at the 
difference between the two and asked why they could not be merged 
together, so I would agree that the two concepts could be more clearly 
defined and separated in the spec as it currently exists. I disagree a 
separate document is required.

> By this token, I also respectfully disagree with Bruce's comment about

Fair enough, but perhaps you could explain why. I use application 
protocols in my native client that do not benefit from a binary/text 
split. If one recognizes the Javascript layer in a browser as an 
application layer (which becomes obvious when using native clients with 
a defined protocol header) then it becomes clear that the binary/text 
definition is a feature of the base application protocol required in a 
browser.

There are enough opcodes for my needs so I don't actually need to reuse 
the binary and text opcodes, but I don't see why it shouldn't be allowed 
for other situations. Once you allow that the binary and text opcodes 
are part of an application protocol, it naturally falls out that they 
can be reused.

> there are truly none. It is also not necessary.

Perhaps you could expand on the commingling and the cross-connections. 
Where do you see that happening?

---

From: John Tamplin <[email-masked]>
Date: Tue, 23 Aug 2011 12:50:00 -0400

On Tue, Aug 23, 2011 at 12:46 PM, Bruce Atherton <[email-masked]>wrote:

> Fair enough, but perhaps you could explain why. I use application protocols
> in my native client that do not benefit from a binary/text split. If one
> recognizes the Javascript layer in a browser as an application layer (which
> becomes obvious when using native clients with a defined protocol header)
> then it becomes clear that the binary/text definition is a feature of the
> base application protocol required in a browser.
>

If you allow subprotocols to change the meaning of the framing, then you
essentially have an extension not a subprotocol, as it means no intermediary
can do anything with your frame if it doesn't understand it, a MUX extension
can't aggregate frames in a different subprotocol, etc.  What exactly does
the subprotocol benefit from being on WebSocket if it change the base
framing?

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

---

From: Bruce Atherton <[email-masked]>
Date: Tue, 23 Aug 2011 10:48:06 -0700

On 23/08/2011 9:50 AM, John Tamplin wrote:
> If you allow subprotocols to change the meaning of the framing, then 
> you essentially have an extension not a subprotocol, as it means no 
> intermediary can do anything with your frame if it doesn't understand 
> it, a MUX extension can't aggregate frames in a different subprotocol, 
> etc.  What exactly does the subprotocol benefit from being on 
> WebSocket if it change the base framing?

I'm not talking about changing the framing. I am talking about using the 
opcode field that is already there, but allowing different subprotocols 
to define how to interpret it. I guess changing the definition of the 
binary and text opcodes could be seen as changing the framing given how 
the spec is currently written, but that could be changed editorially 
with no impact to anyone. Just identify those opcodes as being defined 
that way when no subprotocol is specified or when subprotocols are 
defined but need to differentiate binary and text messages (ie. all 
subprotocols used in the browser). That would solve the issue that Bob 
and Iñaki have with application protocol issues getting into the base 
spec, and it wouldn't require a separate document. Or leave it alone as 
a bit of leakage of application level concerns into the base spec, but 
let subprotocols define the other reserved opcodes.

Looking through the spec, though, I see that there is no reference to 
allowing a subprotocol to use reserved opcodes. I thought they were 
available for use by both extensions and subprotocols. My mistake for 
making that assumption. I guess my question now is, why not? The opcode 
is a useful way to determine how to handle different message types, as 
the example for handling binary and text in Javascript shows. I can tell 
you from experience that it comes in handy for other application 
protocols as well.

I don't understand your claim that a subprotocol defining opcodes 
disallows the aggregation of frames. The opcode is only used on the 
first frame of a message in any case. Are you thinking that an 
intermediary or MUX extension will merge frames from different messages 
somehow? If not, then why would it matter if the intermediary or MUX 
extension understands the opcode for a particular subprotocol? That 
would be an application-only concern.

---

From: John Tamplin <[email-masked]>
Date: Tue, 23 Aug 2011 14:02:33 -0400

On Tue, Aug 23, 2011 at 1:48 PM, Bruce Atherton <[email-masked]> wrote:

> opcode field that is already there, but allowing different subprotocols to
> define how to interpret it. I guess changing the definition of the binary
> and text opcodes could be seen as changing the framing given how the spec is
> currently written, but that could be changed editorially with no impact to
> anyone.
>

I think that is changing the framing -- imagine an intermediary that scans
text frames for company secrets leaving the building or looking for dirty
words etc.  You decide that instead of TEXT you want to send some arbitrary
binary data.  The intermediary will likely choke.

I do not believe you should be allowed to do that with a subprotocol.
 Others on the list (hi Greg) believe that even extensions should not be
able to change the framing, only define things that were previously
reserved.

> available for use by both extensions and subprotocols. My mistake for making
> that assumption. I guess my question now is, why not? The opcode is a useful
> way to determine how to handle different message types, as the example for
> handling binary and text in Javascript shows. I can tell you from experience
> that it comes in handy for other application protocols as well.
>

My understanding is the subprotocol is intended to be a "next layer up"
protocol.  Of course, it is free to use binary frames and define whatever it
likes for the content, including having the first byte of the binary frame
payload identify a subprotocol frame.  Likewise, it could define that all
text frames are JSON encoded, with a fixed tag to identify the message type.

> I don't understand your claim that a subprotocol defining opcodes disallows
> the aggregation of frames. The opcode is only used on the first frame of a
> message in any case. Are you thinking that an intermediary or MUX extension
> will merge frames from different messages somehow? If not, then why would it
> matter if the intermediary or MUX extension understands the opcode for a
> particular subprotocol? That would be an application-only concern.
>

As long as your reuse of opcodes still follows the same rules as what is
currently spec'd, in particular the opcode of the first frame defines that
of the message, messages can be arbitrarily fragmented, and continuation
fragments have a continuation opcde -- then yes, it could still do it.  But
if you aren't changing any of those things, what exactly do you get by
redefining the opcodes?

---

From: Bruce Atherton <[email-masked]>
Date: Tue, 23 Aug 2011 11:33:47 -0700

On 23/08/2011 11:02 AM, John Tamplin wrote:
>
> I think that is changing the framing -- imagine an intermediary that 
> scans text frames for company secrets leaving the building or looking 
> for dirty words etc.  You decide that instead of TEXT you want to send 
> some arbitrary binary data.  The intermediary will likely choke.

Hmm. Ok, I guess that could be a usecase for maintaining the text opcode 
in all application protocols. I don't find it terribly compelling, but I 
can see why might want that.

The only reason I have for reusing the binary and text opcodes is to 
make it clear that they are defined strictly for application purposes. 
If you think it is worth breaking that boundary so that intermediaries 
can have visibility into application data, then that is fine with me. I 
was just trying to resolve the issues that Bob and Iñaki have with 
minimal impact. Note that any move to an all binary format as suggested 
by Bob would also remove the ability for intermediaries to depend on 
their ability to interpret the application data.

>
>     Looking through the spec, though, I see that there is no reference
>     to allowing a subprotocol to use reserved opcodes. I thought they
>     were available for use by both extensions and subprotocols. My
>     mistake for making that assumption. I guess my question now is,
>     why not? The opcode is a useful way to determine how to handle
>     different message types, as the example for handling binary and
>     text in Javascript shows. I can tell you from experience that it
>     comes in handy for other application protocols as well.
>
>
> My understanding is the subprotocol is intended to be a "next layer 
> up" protocol.  Of course, it is free to use binary frames and define 
> whatever it likes for the content, including having the first byte of 
> the binary frame payload identify a subprotocol frame.  Likewise, it 
> could define that all text frames are JSON encoded, with a fixed tag 
> to identify the message type.

I am not being clear enough. Let me give a concrete, although made-up, 
example with a protocol that everyone here understands.

Suppose you wanted to implement the HTTP protocol in Websockets, and you 
are only going to use native clients. To make this more Websockety, let 
us say that both endpoints can send and receive both requests and responses.

You are going to want to present two types of messages to your 
application: requests and responses. You may even go a bit more 
fine-grained and split the request message into different types for the 
different HTTP methods.

Whether a message is text or binary is not an issue at the Websockets 
layer. The application protocol defines it with a Content-Type header. 
What is useful is to have different opcodes for requests and responses, 
so that the data can be fed into the appropriate message type for 
parsing and for presenting an interface to the rest of the application. 
This way you can determine message types without having to artificially 
add a prefix or envelope to the data.

To me, identifying the message type is exactly what the opcode field is for.

>
> As long as your reuse of opcodes still follows the same rules as what 
> is currently spec'd, in particular the opcode of the first frame 
> defines that of the message, messages can be arbitrarily fragmented, 
> and continuation fragments have a continuation opcde -- then yes, it 
> could still do it.  But if you aren't changing any of those things, 
> what exactly do you get by redefining the opcodes?

The ability to define different message types that are relevant for the 
application protocol. But as I say, if the binary and text opcodes stay 
static that is just a bit of wastage that doesn't bother me too much. To 
be fair to Bob and Iñaki though, it _is_ leaking application concerns 
into the base protocol.

---

From: Greg Wilkins <[email-masked]>
Date: Wed, 24 Aug 2011 09:41:15 +1000

On 24 August 2011 03:48, Bruce Atherton <[email-masked]> wrote:
> that assumption. I guess my question now is, why not?

This WG appears to have a phobia about negotiating anything in the
protocol layer.

With only a handful of reserved opcode and bits, the allocation of
them to extensions and sub protocols needs to be dynamically
negotiated if we are to avoid de facto assignment (eg google-mux takes
0x7 opcode, making it pretty tough for anybody else to use that opcode
in the face of googles market share).   Yet every attempt to suggest
even the simplest mechanism to negotiate usage of these resources has
been met with rejection due to the apparent complexities of it.     So
without a mechanism to allocate them, we are left holding them in
reserve for future versions of the protocol or to be assigned by
request to IANA.

regards

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Wed, 24 Aug 2011 13:50:19 +0200

2011/8/23 Bruce Atherton <[email-masked]>:
> anyone. Just identify those opcodes as being defined that way when no
> subprotocol is specified or when subprotocols are defined but need to
> differentiate binary and text messages (ie. all subprotocols used in the
> browser). That would solve the issue that Bob and Iñaki have with
> application protocol issues getting into the base spec, and it wouldn't
> require a separate document. Or leave it alone as a bit of leakage of
> application level concerns into the base spec, but let subprotocols define
> the other reserved opcodes.
>

Hi. I don't like the layer mixing you are suggesting. opcode is a
frame field, not a message field. WS Application layer is supposed to
work with WS messages and use a simple API to close connection, send
frame ping for keepalive and not much more.

So I imagine a WS Framming layer (this is how I name it in my server)
which receives frames and passes WS messages (full message or via
streaming) to the WS Application which just receives the WS message
and *nothing* else.

An analogy of what you suggest would be an HTTP server inspecting TCP
packet bits. That's wrong.

But of course, I have no doubt that all these discussions exist due to
the not very "standard" WS protocol design. No doubt at all. When a
protocol is well designed and provides logical layers, the whole
picture is easier to understand and implement. In WS draft lot of stuf
is unclear, for example:

- If my WS server receives a ping frame, should my "primary" WS
Framming layer reply pong? or should it pass to my WS Application
layer?

- Some question in case my WS server receives a close frame.

- If my WS Application must send a very long WS message, should the WS
Application layer itself split it and pass it to the WS Framming layer
(which would require informing about FIN bit and so, ugly for an API)?
or should the WS Framming layer receive the full (or via straming)
message and decide whether to fragment it or not in N frames?

- Should the WS Application layer read RSV bits or extensions data
from the frame?, which frame in case a message has been splitted in N
frames???, or should the WS Framming be the only concerned layer about
that?

So from my point of view, the spec should clearly talk about a
framming layer and application layer, setting limits and interaction
between them. But it does not so all gets mixed and people then
suggests things like the WS message receiver reading frame bits (which
means no layers at all).

Indicating layers in a protocol specification does NOT make it over
engineered. Instead it would avoid 70% of daily discussions in this
maillist.

Just to give a personal example, recently I've coded a SIP
proxy/server. SIP protocol (RFC 3261) is 100000 times more complex
than WebSocket, but layers are very well specified within the RFC. So
I spent more of the time coding specific parsing, timers and message
passing mechanism, but the rsulting code is very clear as it
implements the layers as stated in the RFC.

In contrast, I've started a WS server recently. Parsing/framing stuf
is already done but now I've terrible doubts about WS logic (i.e. the
above given list of questions) and I don't like too much the resulting
code as it's unclear where the responsibility is.

Regards.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Bruce Atherton <[email-masked]>
Date: Wed, 24 Aug 2011 09:06:57 -0700

> frame ping for keepalive and not much more.

Opcode is a message field. It is set only on the first frame of a 
message. All other frames have a continuation opcode. It is only a frame 
field in the sense that it is stored in the header of the first frame of 
the message.

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Wed, 24 Aug 2011 18:13:04 +0200

2011/8/24 Bruce Atherton <[email-masked]>:
> Opcode is a message field. It is set only on the first frame of a message.
> All other frames have a continuation opcode. It is only a frame field in the
> sense that it is stored in the header of the first frame of the message.

Yes, sorry, my mistake. In fact, my WS Framming layer pass also the
opcode (just text or binary) to the WS Application layer along with
the message itself.

-- 
Iñaki Baz Castillo
<[email-masked]>