noVNC/include/web-socket-js
Joel Martin 507b473a2e Test non-base64 (straight UTF-8) encoding.
Also add a wsencoding test client/server program to test send a set of
values between client and server and vice-versa to test encodings.

Not turned on by default.

Add support for encode/decode of UTF-8 in the proxy. This leverages
the browser for decoding the WebSocket stream directly instead of
doing base64 decode in the browser itself.

Unfortunately, in Chrome this has negligible impact (round-trip time
is increased slightly likely due to extra python processing).

In firefox, due to the use of the flash WebSocket emulator the
performance is even worse. This is because it's really annoying to get
the flash WebSocket emulator to properly decode a UTF-8 bytestream.
The problem is that the readUTFBytes and readMultiByte methods of an
ActionScript ByteArray don't treat 0x00 correctly. They return
a string that ends at the first 0x00, but the index into the ByteArray
has been advanced by however much you requested.

This is very silly for two reasons: ActionScript (and Javascript)
strings can contain 0x00 (they are not null terminated) and second,
UTF-8 can legitimately contain 0x00 values. Since UTF-8 is not
constant width there isn't a great way to determine if those methods
in fact did encounter a 0x00 or they just read the number of bytes
requested.

Doing manual decoding using readUTFByte one character at a time slows
things down quite a bit. And to top it all off, those methods don't
support the alternate UTF-8 encoding for 0x00 ("\xc0\x80"). They also
just treat that encoding as the end of string too.

So to get around this, for now I'm encoding zero as 256 ("\xc4\x80")
and then doing mod 256 in Javascript. Still doesn't result in much
benefit in firefox.

But, it's an interesting approach that could use some more exploration
so I'm leaving in the code in both places.
2010-05-28 15:39:38 -05:00
..
flash-src Test non-base64 (straight UTF-8) encoding. 2010-05-28 15:39:38 -05:00
FABridge.js Import web-socket-js: a0fb3933ce5c824bcb882f5a1cf87e46de773ea8 2010-04-17 17:23:31 -05:00
README.txt Import web-socket-js: a0fb3933ce5c824bcb882f5a1cf87e46de773ea8 2010-04-17 17:23:31 -05:00
WebSocketMain.swf Support for SSL/TLS ('wss://') on both sides. 2010-04-30 16:41:09 -05:00
sample.html Import web-socket-js: a0fb3933ce5c824bcb882f5a1cf87e46de773ea8 2010-04-17 17:23:31 -05:00
swfobject.js Import web-socket-js: a0fb3933ce5c824bcb882f5a1cf87e46de773ea8 2010-04-17 17:23:31 -05:00
web_socket.js Fix web-socket-js: encode sent data across FABridge. 2010-05-28 15:34:54 -05:00

README.txt

* How to try

Assuming you have Web server (e.g. Apache) running at http://example.com/ .

- Download web_socket.rb from:
  http://github.com/gimite/web-socket-ruby/tree/master
- Run sample Web Socket server (echo server) in example.com with: (#1)
  $ ruby web-socket-ruby/samples/echo_server.rb example.com 10081
- If your server already provides socket policy file at port 843, modify the file to allow access to port 10081. Otherwise you can skip this step. See below for details.
- Publish the web-socket-js directory with your Web server (e.g. put it in ~/public_html).
- Change ws://localhost:10081 to ws://example.com:10081 in sample.html.
- Open sample.html in your browser.
- After "onopen" is shown, input something, click [Send] and confirm echo back.

#1: First argument of echo_server.rb means that it accepts Web Socket connection from HTML pages in example.com.


* How to debug

If sample.html doesn't work, check these:

- It doesn't work when you open sample.html as local file i.e. file:///.../sample.html. Open it via Web server.
- Make sure port 10081 is not blocked by your server/client's firewall.
- Use Developer Tools (Chrome/Safari) or Firebug (Firefox) to see if console.log outputs any errors.
- Install debugger version of Flash Player available here to see Flash errors:
http://www.adobe.com/support/flashplayer/downloads.html


* Supported environment

I confirmed it works on Chrome 3, Firefox 3.5 and IE 8. It may not work in other browsers.
It requires Flash Player 9 or later (probably).

On Chrome 4 Dev Channel, it just uses native Web Socket implementation.


* Flash socket policy file

This implementation uses Flash's socket, which means that your server must provide Flash socket policy file to declare the server accepts connections from Flash.

If you use web-socket-ruby available at
http://github.com/gimite/web-socket-ruby/tree/master
, you don't need anything special, because web-socket-ruby handles Flash socket policy file request. But if you already provide socket policy file at port 843, you need to modify the file to allow access to Web Socket port, because it precedes what web-socket-ruby provides.

If you use other Web Socket server implementation, you need to provide socket policy file yourself. See
http://www.lightsphere.com/dev/articles/flash_socket_policy.html
for details and sample script to run socket policy file server.

Actually, it's still better to provide socket policy file at port 843 even if you use web-socket-ruby. Flash always try to connect to port 843 first, so providing the file at port 843 makes startup faster.


* Cookie considerations

Cookie is sent if Web Socket host is the same as the origin of JavaScript. Otherwise it is not sent, because I don't know way to send right Cookie (which is Cookie of the host of Web Socket, I heard).

Note that it's technically possible that client sends arbitrary string as Cookie and any other headers (by modifying this library for example) once you place Flash socket policy file in your server. So don't trust Cookie and other headers if you allow connection from untrusted origin.


* Proxy considerations

The WebSocket spec (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol) specifies instructions for User Agents to support proxied connections by implementing the HTTP CONNECT method.

The AS3 Socket class doesn't implement this mechanism, which renders it useless for the scenarios where the user trying to open a socket is behind a proxy. 

The class RFC2817Socket (by Christian Cantrell) effectively lets us implement this, as long as the proxy settings are known and provided by the interface that instantiates the WebSocket. As such, if you want to support proxied conncetions, you'll have to supply this information to the WebSocket constructor when Flash is being used. One way to go about it would be to ask the user for proxy settings information if the initial connection fails.


* How to build WebSocketMain.swf

Install Flex SDK.

$ cd flash-src
$ mxmlc -output=../WebSocketMain.swf WebSocketMain.as


* License

New BSD License.