Subject: Re: [hybi] Binary/Text Distinction

From: "Bob Gezelter" <[email-masked]>
Date: Wed, 17 Aug 2011 11:44:45 -0700

John,

Ok, I mis-read what you had written. However, you envision a connection
where some messages will be text, and other messages will be binary, to
wit:

   Message 1 (Text)
   Message 2 (Text)
   Message 3 (Binary)
   Message 4 (Text)

Correct?

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

> -------- Original Message --------
> Subject: Re: [hybi] Binary/Text Distinction
> From: John Tamplin <[email-masked]>
> Date: Wed, August 17, 2011 11:38 am
> To: Bob Gezelter <[email-masked]>
> Cc: Bjoern Hoehrmann <[email-masked]>, [email-masked]
> 
> 
> On Wed, Aug 17, 2011 at 2:22 PM, Bob Gezelter <[email-masked]> wrote:
> 
> > From this message below, it would appear that you are reading the
> > specification to describe a protocol where frames within a message are a
> > mix of text and binary frames, to wit:
> >
> >    Message 1 Frame 0  Text
> >    Message 1 Frame 1  Text
> >    Message 1 Frame 2  Binary
> >    Message 1 (FIN Bit) Frame 3 Text
> >
> > Am I interpreting your comments correctly?
> 
> 
> No, message 1 might be binary and message 2 might be text.  Within a
> message, the opcode is only on the first frame, so all frames of one message
> must be of the same type.
> 
> -- 
> John A. Tamplin
> Software Engineer (GWT), Google

---

From: John Tamplin <[email-masked]>
Date: Wed, 17 Aug 2011 14:49:50 -0400

> where some messages will be text, and other messages will be binary, to

Yes.  Consider a hypothetical chat app:

most messages are JSON-encoded chat data, status notifies, etc
file transfers are done as binary

If the connection has to be one or the other, then obviously it has to be
binary, which means JS needs some way to encode its text as binary so it can
be serialized into a combined message, and a way to extract UTF8 text from a
piece of a binary message.

That can certainly be done, but that would require a lot more effort
crossing multiple groups to make that work.

---

From: Bruce Atherton <[email-masked]>
Date: Thu, 18 Aug 2011 09:26:34 -0700

On 17/08/2011 11:49 AM, John Tamplin wrote:
> On Wed, Aug 17, 2011 at 2:44 PM, Bob Gezelter <[email-masked] 
> <mailto:[email-masked]>> wrote:
>
> If the connection has to be one or the other, then obviously it has to 
> be binary, which means JS needs some way to encode its text as binary 
> so it can be serialized into a combined message, and a way to extract 
> UTF8 text from a piece of a binary message.
>

I think John's example and Bob's previous statement:

> As has been observed, the WebSocket protocol is payload-agnostic.
> Regardless of the politics, it is thus emphatically NOT an applications
> protocol.

can be resolved when one realizes that in the absence of a subprotocol 
header to define the application protocol, a default application-level 
subprotocol is in use. It is this default subprotocol that John wants to 
support the intermixing of UTF8 and binary messages differentiated by 
opcodes.

Other subprotocols may mix binary and text in a single message and may 
differentiate different types of messages with different opcodes or 
message headers, but since browsers are unlikely to support anything 
other than the default subprotocol for some time to come, allowing them 
to choose to send either raw UTF8 or raw binary messages in the default 
subprotocol makes a lot of sense to me.

---

From: Stephen Williams <[email-masked]>
Date: Thu, 18 Aug 2011 09:56:12 -0700

On 8/18/11 9:26 AM, Bruce Atherton wrote:
>> On Wed, Aug 17, 2011 at 2:44 PM, Bob Gezelter <[email-masked] <mailto:[email-masked]>> wrote:
>>
>> If the connection has to be one or the other, then obviously it has to be binary, which means JS needs some way to encode its 
>> text as binary so it can be serialized into a combined message, and a way to extract UTF8 text from a piece of a binary message.
>>
>
> can be resolved when one realizes that in the absence of a subprotocol header to define the application protocol, a default 
> application-level subprotocol is in use. It is this default subprotocol that John wants to support the intermixing of UTF8 and 
> binary messages differentiated by opcodes.
>
> Other subprotocols may mix binary and text in a single message and may differentiate different types of messages with different 
> opcodes or message headers, but since browsers are unlikely to support anything other than the default subprotocol for some time 
> to come, allowing them to choose to send either raw UTF8 or raw binary messages in the default subprotocol makes a lot of sense to me.

There are few well-designed message-oriented applications that wouldn't have a header (text or binary) on every message, with the 
payload being text, binary, or both.  Going down the "we have to denote text in the protocol so the JS API is simpler / more 
efficient" path seems to lead to explicitly delineating header+type & body+type.  Otherwise, while header(text)+body(text) is easy, 
header(text)+body(binary) forces the app JS to find and parse header(text) out of a binary payload anyway.  The result either 
defeats the purpose of payload typing, or it puts pressure on app protocol construction to have pure text or binary message streams.

In the example above, is the application sending a text message to "set up" the binary transfer, then just sending raw blocks of 
data?  Or does each block of data have a header?  If you don't reuse channels, you could just keep allocating new channels for raw 
transfer.  Is that the intention?  Is it right to cause the application designer to make that kind of decision because of a 
"limitation" of the protocol and API?

Assuming a message can have multiple frames, as the spec indicates, and each frame could be text or binary, having per-frame 
text/binary opcodes/flag would probably work well enough for byte-aligned data.  Having 4 byte opcode+length is larger than it needs 
to be, but not terribly expensive for typical applications.

sdw

---

From: Bruce Atherton <[email-masked]>
Date: Thu, 18 Aug 2011 10:58:18 -0700

On 18/08/2011 9:56 AM, Stephen Williams wrote:
>
> There are few well-designed message-oriented applications that 
> wouldn't have a header (text or binary) on every message, with the 
> payload being text, binary, or both.

Right. And in Websockets, that header can be the binary opcode. Or it 
can be an identifier within the payload. Or it can be a combination of both.

In the default subprotocol, it will probably be a combination in many 
cases. The opcode indicates a broad category for interpreting the 
message (UTF8 or binary) and if further identification of the message 
type is needed it can be included in the message itself by the 
application. Given the constraints within the browser, this seems like a 
reasonable solution to use for the default.

>   Going down the "we have to denote text in the protocol so the JS API 
> is simpler / more efficient" path seems to lead to explicitly 
> delineating header+type & body+type.  Otherwise, while 
> header(text)+body(text) is easy, header(text)+body(binary) forces the 
> app JS to find and parse header(text) out of a binary payload anyway.

Which may well be the reason many people choose not to do things that 
way. Or they may decide that the complication is worth it. It is very 
hard to design a generic default application protocol that is all things 
to all people. This is always going to be a compromise.

>   The result either defeats the purpose of payload typing, or it puts 
> pressure on app protocol construction to have pure text or binary 
> message streams.

If they want to use the default subprotocol then they are probably best 
to stick to pure text or pure binary with this scheme, yes.

Do you have a suggestion that would allow things to be more flexible and 
allow interweaving text and binary in a single message? The only way I 
can see it is if browsers all supported some sort of IDL for messages, 
and that seems like a major complication that is not even in the domain 
of this WG.

>
> In the example above, is the application sending a text message to 
> "set up" the binary transfer, then just sending raw blocks of data?  
> Or does each block of data have a header?  If you don't reuse 
> channels, you could just keep allocating new channels for raw 
> transfer.  Is that the intention?  Is it right to cause the 
> application designer to make that kind of decision because of a 
> Assuming a message can have multiple frames, as the spec indicates, 
> and each frame could be text or binary, having per-frame text/binary 
> opcodes/flag would probably work well enough for byte-aligned data.  
> Having 4 byte opcode+length is larger than it needs to be, but not 
> terribly expensive for typical applications.

I don't know if I am understanding you correctly. Are you saying that if 
an application-level protocol wants to combine text and binary in a 
single message, it should somehow indicate to the Websockets layer how 
it should do fragmentation?

If so, then even if I thought the leakage between layers was worth it, I 
don't see the point. In browsers where the default subprotocol is most 
important, the message is going to be delivered to the application layer 
as a single entity. Who cares how it was transported?

---

From: Stephen Williams <[email-masked]>
Date: Thu, 18 Aug 2011 12:47:48 -0700

On 8/18/11 10:58 AM, Bruce Atherton wrote:
>> ...
>>   The result either defeats the purpose of payload typing, or it puts pressure on app protocol construction to have pure text or 
>> binary message streams.
>
> If they want to use the default subprotocol then they are probably best to stick to pure text or pure binary with this scheme, yes.
>
> Do you have a suggestion that would allow things to be more flexible and allow interweaving text and binary in a single message? 
> The only way I can see it is if browsers all supported some sort of IDL for messages, and that seems like a major complication 
> that is not even in the domain of this WG.

IDL, in general, is bad IMHO.  Not needed here either.  Since we've (thankfully) agreed that text=UTF8, a text frame and a binary 
frame containing UTF8 should have the same data.  Signaling that a frame is text is just an optimization indicating that the frame 
should be valid UTF8.  That is typing a range of data, not necessarily bounding a logical section of data.

Some versions of the specification say something to the effect of: "a message is made up of one or more frames", and elsewhere that 
frames can be text or binary.  Fragments of a frame all need to be of the same type I believe.  However, it would make sense for 
multiple frames that are part of a message to be of different types.  An application should only do this for big sections 
(header/body, chat text/image), not every other small field.  Perhaps the default subprotocol don't need to care about messages vs. 
frames, although allowing an application to indicate logical message boundaries has all kinds of potential usage (logging, stats, 
routing/load balancing).  But, doable in a layered / different subprotocol also.

All of this is getting close to W3C EXI (Efficient XMl Interchange), a proposed standard and a group I was with in a deep way for 
several years.  At this point, EXI would be nice to layer onto a very simple hybi/ws protocol.  It solves the efficient data object 
representation / packaging problem well.  While adding WS support to Javascript, "we" should consider integrating EXI for easy usage 
too.  (Preferably with my extensions.  ;-) )  And the N-tuple/RDF case needs to be solved well soon also.

>> data?  Or does each block of data have a header?  If you don't reuse channels, you could just keep allocating new channels for 
>> raw transfer.  Is that the intention?  Is it right to cause the application designer to make that kind of decision because of a 
>> text/binary opcodes/flag would probably work well enough for byte-aligned data.  Having 4 byte opcode+length is larger than it 
>> needs to be, but not terribly expensive for typical applications.
>
> I don't know if I am understanding you correctly. Are you saying that if an application-level protocol wants to combine text and 
> binary in a single message, it should somehow indicate to the Websockets layer how it should do fragmentation?

I was thinking that a app could say, in some fashion: start message, text frame, binary frame, end message.

>
> If so, then even if I thought the leakage between layers was worth it, I don't see the point. In browsers where the default 
> subprotocol is most important, the message is going to be delivered to the application layer as a single entity. Who cares how it 
> was transported?
>
Since UTF8(text) == UTF8(binary) at the byte level, the flagging is only an optimization of the API/library/language, right?  Is 
there any difference in "transport" of text vs. binary other than the type flag?  Other than a 1007 error if the "text" turns out 
not to be valid UTF8, don't see anything in the spec.  Rather than a query/parse request/response, the API can simply put the text 
into a string / JSON-based object tree / DOM / etc. before the application asks.

sdw
-- 
Stephen D. Williams [email-masked] [email-masked] LinkedIn: http://sdw.st/in V:650-450-UNIX (8649) V:866.SDW.UNIX 
V:703.371.9362 F:703.995.0407 AIM:sdw Skype:StephenDWilliams Yahoo:sdwlignet Resume: http://sdw.st/gres Personal: http://sdw.st 
facebook.com/sdwlig twitter.com/scienteer

---

From: Scott Ferguson <[email-masked]>
Date: Thu, 18 Aug 2011 13:30:58 -0700

> text frame, binary frame, end message.

But that breaks the whole concept of the message/frame in WebSockets.

Messages have semantic content (i.e. are meaningful to the application.)

Frames do not have semantic content. They're just a pragmatic 
requirement due to buffering requirements. Since they are invisible to 
the application, the application cannot use frames to split a message up 
into parts like multipart mime.

If an application needs binary/text in chunks, it either needs to send 
multiple messages, or one big message encoded using its own 
multipart-mime equivalent.
>
> Since UTF8(text) == UTF8(binary) at the byte level, the flagging is 
> only an optimization of the API/library/language, right?  Is there any 
> difference in "transport" of text vs. binary other than the type 
> flag?  Other than a 1007 error if the "text" turns out not to be valid 
> UTF8, don't see anything in the spec.

Well, as a pragmatic matter, the UTF-8 hard requirement has value in 
itself, because encoding issues always come up when you have a 
binary-only layers. And avoiding those issues beforehand is a good thing.

If you have text=UTF-8, the discussion ends.

If you don't, each application tries to invent encoding types like 
application/iso-8859-1 vs application/utf-8 or a CORBA-like per-message 
encodings in a misguided attempt at efficiency or flexibility. Or more 
likely, something like the PHP nightmare of not realizing that US-ASCII 
isn't sufficient.

Strictly speaking the text/binary distinction isn't necessary, but many 
years of painful, purposeless text-encoding code over many projects 
suggests setting a fixed utf-8 encoding up front is a very nice, easy 
decision. Since it's not strictly necessary, I'd be okay with 
binary-only -- it does simplify my API. But text messages and the utf-8 
encoding does have value.

-- Scott

---

From: Takeshi Yoshino <[email-masked]>
Date: Fri, 19 Aug 2011 05:40:49 +0900

> piece of a binary message.

Serialization from DOMString to binary message can be done just by
overloading send() interface as the current API spec does. The problems is
receiving. Without text/binary distinction in protocol, MessageEvent.data
has to be binary object. The server need to signal the application layer of
the client side whether a certain frame contains data should be interpreted
as text or binary in advance like this:

var handle_as_binary = false;
onmessage = function(evt) {
  if (handle_as_binary) {
    // Read evt.data as Blob/TypedArray directly and handle it.
    // If it indicates the next message is also binary, keep
handle_as_binary true. Otherwise set it to false.
  } else {
    // e.g. assume evt.data contains text by default and handle it.
    var text = ConvertToString(evt.data);  // This can be .as_text() or
something as David suggested
    // If it indicates the next message is binary, set handle_as_binary to
true.
  }
}

or we might embed some additional header in payload to switch handling

onmessage = function(evt) {
  var tmp_view = new Uint8Array(evt.data);
  if (tmp_view[0] & 0x01 == 0x00) {  // e.g. LSB indicates type. Here it's
Text
    // Convert the rest of tmp_view to DOMString
    var text = ConvertToString(evt.data.slice(1));
  } else {  // Binary
    // Handle as binary event
  }
}

Yes, it works.

As it's cumbersome for text only users to perform conversion, we'd
extend binaryType to receiveType and add "text" type (or let binaryType ==
null mean "text") to force received data decoded as text into DOMString and
specify it as default. And ask those who are interested in binary to set
receiveType to "blob" or "arraybuffer" and write some code like above.

----

That said, I agree with Greg.

On Tue, Aug 16, 2011 at 09:10, Greg Wilkins <[email-masked]> wrote:

> The cost now is just the allocation of an opcode and a bit of split
> personality in the APIs - which is a price that I'm prepared to pay to
> avoid another round of design by war of attrition.
>

+1

Removal of text opcode

- complicates JS code for text/binary mixed use case
- delays UTF-8 decoding and requires unnecessary allocation of
Blob/TypeArray object (if we take as_text() approach, not object but
allocation of memory for holding non-decoded data) for text/binary mixed use
case
- requires rearrangement of opcode (maybe revoke 0x02 and let 0x01 generic
data frame type) (this change is not so painful for those who haven't
exposed binary API)
- (API side change may kept minimal by making binaryType = null to force
decoding as text.)

while just saving one opcode space (sorry if i'm missing something else
important already discussed. there're too much traffic on the list recently)

I'd prefer just taking in text opcode as a predefined/convenient content
type indication method out of application layer.

Thanks,
Takeshi

---

From: Bruce Atherton <[email-masked]>
Date: Thu, 18 Aug 2011 15:37:08 -0700

On 18/08/2011 12:47 PM, Stephen Williams wrote:
>
> Some versions of the specification say something to the effect of: "a 
> message is made up of one or more frames", and elsewhere that frames 
> can be text or binary.  Fragments of a frame all need to be of the 
> same type I believe.

There are no fragments of frames visible to Websockets, although you 
could argue that TCP packets fill that role. Rather, frames are 
fragments of messages.

It would be more correct to say that messages are text or binary, rather 
than frames. Frames within a message have only one text/binary opcode 
defined on the first frame, and the rest of the frames in a message have 
the continuation opcode. At least that is how it is currently defined.

>   However, it would make sense for multiple frames that are part of a 
> message to be of different types.  An application should only do this 
> for big sections (header/body, chat text/image), not every other small 
> field.  Perhaps the default subprotocol don't need to care about 
> messages vs. frames, although allowing an application to indicate 
> logical message boundaries has all kinds of potential usage (logging, 
> stats, routing/load balancing).  But, doable in a layered / different 
> subprotocol also.

Not sure what you mean about an application indicating logical message 
boundaries. That is how the spec is currently defined. The application 
layer sends and receives messages.

Perhaps it is my use of the definition of subprotocol which is 
confusing, because so far as I know I'm one of the few who uses this 
feature of Websockets. The default subprotocol as defined for browsers 
is very simple to allow the layering of further application protocols on 
top, ones which are not identified by the subprotocol header but are 
defined implicitly by the application.

So you can have a chat protocol, a video streaming protocol, a 
conference calling protocol, almost anything at all sitting on top of 
the default subprotocol, and the only way to differentiate between these 
is based on how the application is implemented. This is how things have 
to work in the browser.

In contrast, if you control both the client and the server you can 
declare a subprotocol on the connection and provide for marshalling and 
unmarshalling specific types of messages based on the subprotocol 
declared. I don't know if anyone other than myself does this.

So if I wanted raw types similar to the default subprotocol, I might 
define utf8-message, utf8-stream, binary-message, and binary-stream as 
subprotocols. If I wanted either binary or text in the same connection, 
I might have mixed-message and mixed-stream, where the opcode 
differentiated between the types. The default protocol in browsers is 
equivalent to mixed-message.

In my case the message types are much more specific, of course.

>
> All of this is getting close to W3C EXI (Efficient XMl Interchange),

This looks like it would make a good application-level protocol if you 
wanted to send a SAX-like stream across Websockets in an efficient way. 
Apologies if I am mischaracterizing EXI, I have just glanced at it now.

If you use a custom client, you could define an EXI subprotocol and have 
a message type that is an EXI stream. If you want to use a browser 
client you need to use the default subprotocol, and since EXI requires 
bit manipulation you would probably use a binary message. Then you could 
encode/decode between the binary message and the EXI stream with 
Javascript on the client and any way you wanted on the server.

Your examples of N-Tuples and RDF could also be subprotocols or layered 
on the default subprotocol. All that is needed is to implement them.

>> I don't know if I am understanding you correctly. Are you saying that 
>> if an application-level protocol wants to combine text and binary in 
>> a single message, it should somehow indicate to the Websockets layer 
>> how it should do fragmentation?
>

Right, but frames are not visible at the application level. They 
disappear by then. Better to have a sequence of Websocket messages that 
the application aggregates back into the larger message structure you want.

---

From: John Tamplin <[email-masked]>
Date: Thu, 18 Aug 2011 19:09:22 -0400

On Thu, Aug 18, 2011 at 6:37 PM, Bruce Atherton <[email-masked]> wrote:

> Right, but frames are not visible at the application level. They disappear
> by then. Better to have a sequence of Websocket messages that the
> application aggregates back into the larger message structure you want.
>

And more importantly, framing is allowed to be changed beneath the
application.  An intermediary may refragment (such as when mutliplexing), or
the WebSocket layer may send a message in arbitrary frames as it sees fit.

---

From: Stephen Williams <[email-masked]>
Date: Thu, 18 Aug 2011 17:12:45 -0700

Thanks for the clarification.

It's somewhat bad for applications to be required to have all-text or all-binary messages or streams.  Sophisticated apps will just 
go all binary most likely.

Binary bit twiddling is possible with Javascript, java, etc.  It's the bulk operations that are important to be intrinsic in some 
fashion, like load these bytes into a string or parse as JSON/XML/base65, etc.

It seems like a mistake to confine browser / web server usage of websockets to a single "default subprotocol".  Why wouldn't or 
shouldn't a particular Javascript web application be able to use a different subprotocol?  Of course layering should work even over 
the default subprotocol.

I have no problem hiding low-level and fragment frames from applications.  However, if there's going to be typing of or in messages, 
it might not be bad to have sub-messages / message segments that have individual type but are considered a single message.  With the 
current API, it seems that an application that has both text and binary needs should either A) send everything as binary and parse 
out the segments or B) send separate actual messages for the segments of actual messages that may be text vs. binary.

sdw

On 8/18/11 3:37 PM, Bruce Atherton wrote:
>> Some versions of the specification say something to the effect of: "a message is made up of one or more frames", and elsewhere 
>> that frames can be text or binary.  Fragments of a frame all need to be of the same type I believe.
>
> There are no fragments of frames visible to Websockets, although you could argue that TCP packets fill that role. Rather, frames 
> are fragments of messages.
>
> It would be more correct to say that messages are text or binary, rather than frames. Frames within a message have only one 
> text/binary opcode defined on the first frame, and the rest of the frames in a message have the continuation opcode. At least that 
> is how it is currently defined.
>
>>   However, it would make sense for multiple frames that are part of a message to be of different types.  An application should 
>> only do this for big sections (header/body, chat text/image), not every other small field.  Perhaps the default subprotocol don't 
>> need to care about messages vs. frames, although allowing an application to indicate logical message boundaries has all kinds of 
>> potential usage (logging, stats, routing/load balancing).  But, doable in a layered / different subprotocol also.
>
> Not sure what you mean about an application indicating logical message boundaries. That is how the spec is currently defined. The 
> application layer sends and receives messages.
>
> Perhaps it is my use of the definition of subprotocol which is confusing, because so far as I know I'm one of the few who uses 
> this feature of Websockets. The default subprotocol as defined for browsers is very simple to allow the layering of further 
> application protocols on top, ones which are not identified by the subprotocol header but are defined implicitly by the application.
>
> So you can have a chat protocol, a video streaming protocol, a conference calling protocol, almost anything at all sitting on top 
> of the default subprotocol, and the only way to differentiate between these is based on how the application is implemented. This 
> is how things have to work in the browser.
>
> In contrast, if you control both the client and the server you can declare a subprotocol on the connection and provide for 
> marshalling and unmarshalling specific types of messages based on the subprotocol declared. I don't know if anyone other than 
> myself does this.
>
> So if I wanted raw types similar to the default subprotocol, I might define utf8-message, utf8-stream, binary-message, and 
> binary-stream as subprotocols. If I wanted either binary or text in the same connection, I might have mixed-message and 
> mixed-stream, where the opcode differentiated between the types. The default protocol in browsers is equivalent to mixed-message.
>
> This looks like it would make a good application-level protocol if you wanted to send a SAX-like stream across Websockets in an 
> efficient way. Apologies if I am mischaracterizing EXI, I have just glanced at it now.
>
> If you use a custom client, you could define an EXI subprotocol and have a message type that is an EXI stream. If you want to use 
> a browser client you need to use the default subprotocol, and since EXI requires bit manipulation you would probably use a binary 
> message. Then you could encode/decode between the binary message and the EXI stream with Javascript on the client and any way you 
> wanted on the server.
>
> Your examples of N-Tuples and RDF could also be subprotocols or layered on the default subprotocol. All that is needed is to 
> implement them.
>
> Right, but frames are not visible at the application level. They disappear by then. Better to have a sequence of Websocket 
> messages that the application aggregates back into the larger message structure you want.
>

---

From: Tobias Oberstein <[email-masked]>
Date: Fri, 19 Aug 2011 03:26:50 -0700

I would like to attempt at a concrete use case:

"exchange WebGL scene data via WebSockets"

to  gain more insight.

==

>From the WebGL spec:

5.12 ArrayBuffer and Typed Arrays

Vertex, index, texture, and other data is transferred to the WebGL implementation using the ArrayBuffer and views defined in the Typed Array specification [TYPEDARRAYS]. All of the typed array views except Float64Array may be used in conjunction with WebGL; OpenGL ES 2.0, and therefore WebGL, does not support double-precision floating-point data.

http://www.khronos.org/registry/webgl/specs/1.0/#5.12

==

Consider the following

            var scene = {};
            scene.objects = [];
            scene.objects[0] = {id: 100, label: "tiger", vertices: new ArrayBuffer(4 * 3 * 5) };

            var view = new Float32Array(scene.objects[0].vertices);
            for (i = 0; i < view.length; ++i) view[i] = 100 * i;

            console.log(scene);
            console.log(JSON.stringify(scene));

a "fake scene" with a vertex list containing 5 triples of floats (bare with me .. it's fake, but
I guess you get what I mean).

Ideally, I would for sending just do

websocket.send(JSON.stringify(scene))

and for receiving

onmessage(e) {
scene = JSON.parse(e.data);
}

to roundtrip, and be done.

==

That won't work today .. the output of JSON.stringify(scene)

Firefox

{"objects":[{"id":100,"label":"tiger","vertices":{}}]}

Chrome

{"objects":[{"id":100,"label":"tiger","vertices":{"byteLength":60}}]}

Apparantly, the JSON object behaves differently when marshaling JS ArrayBuffers.
Both behaviors of course are somewhat insufficient at what we try.

==

Here are 2 options:

1)
Extend JSON (the serialization format) for having a "binary string" type (i.e. base64 encoded string, but enclosed in brackets, like

<TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vd>

vs

"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vd"

The former could be used to automatically marshal/demarshal JavaScript ArrayBuffer's

This has nothing to do with WebSockets, but with JSON (the format) and with how the JSON (the JS object) in JS works.

2)
Marshal/demarshal JS ArrayBuffers as

{"ArrayBuffer": "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vd"}

and have some magic built into the JS JSON object so that it can do the right thing when it encounters
a JSON dict with a single key that is equal to "ArrayBuffer".

Again, that has nothing to do with WebSockets, but only how the JSON object in JS works.

==

I think the use case is valid, but it should not be solved in the WebSockets protocol by introducing
"mixed text/binary" / "structured" messages.