Remove Base64 support

This is an older protocol used before browsers got native
support for Websockets.
This commit is contained in:
Pierre Ossman 2017-01-28 14:50:48 +01:00
parent 56a4ccbf74
commit 4099949984
19 changed files with 51 additions and 542 deletions

View File

@ -3,8 +3,6 @@ docs/LICENSE.LGPL-3) with the following exceptions:
include/websock.js : MPL 2.0 include/websock.js : MPL 2.0
include/base64.js : MPL 2.0
include/des.js : Various BSD style licenses include/des.js : Various BSD style licenses
include/web-socket-js/ : New BSD license (3-clause). Source code at include/web-socket-js/ : New BSD license (3-clause). Source code at

View File

@ -33,16 +33,8 @@ href="http://www.twitter.com/noVNC">@noVNC</a> if you do.
### WebSockets binary data ### WebSockets binary data
Starting with websockify 0.5.0, only the HyBi / IETF Starting with websockify 0.5.0, only the HyBi / IETF
6455 WebSocket protocol is supported. 6455 WebSocket protocol is supported. There is no support for the older
Base64 encoded data format.
Websockify negotiates whether to base64 encode traffic to and from the
client via the subprotocol header (Sec-WebSocket-Protocol). The valid
subprotocol values are 'binary' and 'base64' and if the client sends
both then the server (the python implementation) will prefer 'binary'.
The 'binary' subprotocol indicates that the data will be sent raw
using binary WebSocket frames. Some HyBi clients (such as the Flash
fallback and older Chrome and iOS versions) do not support binary data
which is why the negotiation is necessary.
### Encrypted WebSocket connections (wss://) ### Encrypted WebSocket connections (wss://)
@ -77,8 +69,7 @@ and then also to the key with `--key`. Finally, use `--ssl-only` as needed.
The `include/websock.js` Javascript library library provides a Websock The `include/websock.js` Javascript library library provides a Websock
object that is similar to the standard WebSocket object but Websock object that is similar to the standard WebSocket object but Websock
enables communication with raw TCP sockets (i.e. the binary stream) enables communication with raw TCP sockets (i.e. the binary stream)
via websockify. This is accomplished by base64 encoding the data via websockify.
stream between Websock and websockify.
Websock has built-in receive queue buffering; the message event Websock has built-in receive queue buffering; the message event
does not contain actual data but is simply a notification that does not contain actual data but is simply a notification that

View File

@ -1,114 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js
/*jslint white: false, bitwise: false, plusplus: false */
/*global console */
var Base64 = {
/* Convert data (an array of integers) to a Base64 string. */
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''),
base64Pad : '=',
encode: function (data) {
"use strict";
var result = '';
var toBase64Table = Base64.toBase64Table;
var base64Pad = Base64.base64Pad;
var length = data.length;
var i;
// Convert every three bytes to 4 ascii characters.
/* BEGIN LOOP */
for (i = 0; i < (length - 2); i += 3) {
result += toBase64Table[data[i] >> 2];
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
result += toBase64Table[data[i+2] & 0x3f];
}
/* END LOOP */
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
if (length%3) {
i = length - (length%3);
result += toBase64Table[data[i] >> 2];
if ((length%3) === 2) {
result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
result += toBase64Table[(data[i+1] & 0x0f) << 2];
result += base64Pad;
} else {
result += toBase64Table[(data[i] & 0x03) << 4];
result += base64Pad + base64Pad;
}
}
return result;
},
/* Convert Base64 data to a string */
toBinaryTable : [
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
],
decode: function (data, offset) {
"use strict";
offset = typeof(offset) !== 'undefined' ? offset : 0;
var toBinaryTable = Base64.toBinaryTable;
var base64Pad = Base64.base64Pad;
var result, result_length, idx, i, c, padding;
var leftbits = 0; // number of bits decoded, but yet to be appended
var leftdata = 0; // bits decoded, but yet to be appended
var data_length = data.indexOf('=') - offset;
if (data_length < 0) { data_length = data.length - offset; }
/* Every four characters is 3 resulting numbers */
result_length = (data_length >> 2) * 3 + Math.floor((data_length%4)/1.5);
result = new Array(result_length);
// Convert one by one.
/* BEGIN LOOP */
for (idx = 0, i = offset; i < data.length; i++) {
c = toBinaryTable[data.charCodeAt(i) & 0x7f];
padding = (data.charAt(i) === base64Pad);
// Skip illegal characters and whitespace
if (c === -1) {
console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
continue;
}
// Collect data into leftdata, update bitcount
leftdata = (leftdata << 6) | c;
leftbits += 6;
// If we have 8 or more bits, append 8 bits to the result
if (leftbits >= 8) {
leftbits -= 8;
// Append if not padding.
if (!padding) {
result[idx++] = (leftdata >> leftbits) & 0xff;
}
leftdata &= (1 << leftbits) - 1;
}
}
/* END LOOP */
// If there are any bits left, the base64 string was corrupted
if (leftbits) {
throw {name: 'Base64-Error',
message: 'Corrupted base64 string'};
}
return result;
}
}; /* End of Base64 namespace */

View File

@ -5,8 +5,7 @@
* *
* Websock is similar to the standard WebSocket object but Websock * Websock is similar to the standard WebSocket object but Websock
* enables communication with raw TCP sockets (i.e. the binary stream) * enables communication with raw TCP sockets (i.e. the binary stream)
* via websockify. This is accomplished by base64 encoding the data * via websockify.
* stream between Websock and websockify.
* *
* Websock has built-in receive queue buffering; the message event * Websock has built-in receive queue buffering; the message event
* does not contain actual data but is simply a notification that * does not contain actual data but is simply a notification that
@ -15,7 +14,7 @@
*/ */
/*jslint browser: true, bitwise: false, plusplus: false */ /*jslint browser: true, bitwise: false, plusplus: false */
/*global Util, Base64 */ /*global Util */
// Load Flash WebSocket emulator if needed // Load Flash WebSocket emulator if needed
@ -52,7 +51,6 @@ function Websock() {
var api = {}, // Public API var api = {}, // Public API
websocket = null, // WebSocket object websocket = null, // WebSocket object
mode = 'base64', // Current WebSocket mode: 'binary', 'base64'
rQ = [], // Receive queue rQ = [], // Receive queue
rQi = 0, // Receive queue index rQi = 0, // Receive queue index
rQmax = 10000, // Max receive queue size before compacting rQmax = 10000, // Max receive queue size before compacting
@ -154,36 +152,6 @@ function rQwait(msg, num, goback) {
return false; return false;
} }
//
// Private utility routines
//
function encode_message() {
if (mode === 'binary') {
// Put in a binary arraybuffer
return (new Uint8Array(sQ)).buffer;
} else {
// base64 encode
return Base64.encode(sQ);
}
}
function decode_message(data) {
//Util.Debug(">> decode_message: " + data);
if (mode === 'binary') {
// push arraybuffer values onto the end
var u8 = new Uint8Array(data);
for (var i = 0; i < u8.length; i++) {
rQ.push(u8[i]);
}
} else {
// base64 decode and concat to the end
rQ = rQ.concat(Base64.decode(data, 0));
}
//Util.Debug(">> decode_message, rQ: " + rQ);
}
// //
// Public Send functions // Public Send functions
// //
@ -196,7 +164,7 @@ function flush() {
//Util.Debug("arr: " + arr); //Util.Debug("arr: " + arr);
//Util.Debug("sQ: " + sQ); //Util.Debug("sQ: " + sQ);
if (sQ.length > 0) { if (sQ.length > 0) {
websocket.send(encode_message(sQ)); websocket.send((new Uint8Array(sQ)).buffer);
sQ = []; sQ = [];
} }
return true; return true;
@ -227,7 +195,10 @@ function recv_message(e) {
//Util.Debug(">> recv_message: " + e.data.length); //Util.Debug(">> recv_message: " + e.data.length);
try { try {
decode_message(e.data); var u8 = new Uint8Array(e.data);
for (var i = 0; i < u8.length; i++) {
rQ.push(u8[i]);
}
if (rQlen() > 0) { if (rQlen() > 0) {
eventHandlers.message(); eventHandlers.message();
// Compact the receive queue // Compact the receive queue
@ -262,92 +233,27 @@ function on(evt, handler) {
eventHandlers[evt] = handler; eventHandlers[evt] = handler;
} }
function init(protocols, ws_schema) { function init() {
rQ = []; rQ = [];
rQi = 0; rQi = 0;
sQ = []; sQ = [];
websocket = null; websocket = null;
var bt = false,
wsbt = false,
try_binary = false;
// Check for full typed array support
if (('Uint8Array' in window) &&
('set' in Uint8Array.prototype)) {
bt = true;
}
// Check for full binary type support in WebSocket
// Inspired by:
// https://github.com/Modernizr/Modernizr/issues/370
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/websockets/binary.js
try {
if (bt && ('binaryType' in WebSocket.prototype ||
!!(new WebSocket(ws_schema + '://.').binaryType))) {
Util.Info("Detected binaryType support in WebSockets");
wsbt = true;
}
} catch (exc) {
// Just ignore failed test localhost connections
}
// Default protocols if not specified
if (typeof(protocols) === "undefined") {
if (wsbt) {
protocols = ['binary', 'base64'];
} else {
protocols = 'base64';
}
}
// If no binary support, make sure it was not requested
if (!wsbt) {
if (protocols === 'binary') {
throw("WebSocket binary sub-protocol requested but not supported");
}
if (typeof(protocols) === "object") {
var new_protocols = [];
for (var i = 0; i < protocols.length; i++) {
if (protocols[i] === 'binary') {
Util.Error("Skipping unsupported WebSocket binary sub-protocol");
} else {
new_protocols.push(protocols[i]);
}
}
if (new_protocols.length > 0) {
protocols = new_protocols;
} else {
throw("Only WebSocket binary sub-protocol was requested and not supported.");
}
}
}
return protocols;
} }
function open(uri, protocols) { function open(uri, protocols) {
var ws_schema = uri.match(/^([a-z]+):\/\//)[1]; var ws_schema = uri.match(/^([a-z]+):\/\//)[1];
protocols = init(protocols, ws_schema); init();
if (test_mode) { if (test_mode) {
websocket = {}; websocket = {};
} else { } else {
websocket = new WebSocket(uri, protocols); websocket = new WebSocket(uri, protocols);
if (protocols.indexOf('binary') >= 0) {
websocket.binaryType = 'arraybuffer'; websocket.binaryType = 'arraybuffer';
} }
}
websocket.onmessage = recv_message; websocket.onmessage = recv_message;
websocket.onopen = function() { websocket.onopen = function() {
Util.Debug(">> WebSock.onopen"); Util.Debug(">> WebSock.onopen");
if (websocket.protocol) {
mode = websocket.protocol;
Util.Info("Server chose sub-protocol: " + websocket.protocol);
} else {
mode = 'base64';
Util.Error("Server select no sub-protocol!: " + websocket.protocol);
}
eventHandlers.open(); eventHandlers.open();
Util.Debug("<< WebSock.onopen"); Util.Debug("<< WebSock.onopen");
}; };
@ -376,9 +282,8 @@ function close() {
// Override internal functions for testing // Override internal functions for testing
// Takes a send function, returns reference to recv function // Takes a send function, returns reference to recv function
function testMode(override_send, data_mode) { function testMode(override_send) {
test_mode = true; test_mode = true;
mode = data_mode;
api.send = override_send; api.send = override_send;
api.close = function () {}; api.close = function () {};
return recv_message; return recv_message;

View File

@ -42,11 +42,7 @@ new_client = function(client) {
target.on('data', function(data) { target.on('data', function(data) {
//log("sending message: " + data); //log("sending message: " + data);
try { try {
if (client.protocol === 'base64') { client.send(data);
client.send(new Buffer(data).toString('base64'));
} else {
client.send(data,{binary: true});
}
} catch(e) { } catch(e) {
log("Client closed, cleaning up target"); log("Client closed, cleaning up target");
target.end(); target.end();
@ -64,11 +60,7 @@ new_client = function(client) {
client.on('message', function(msg) { client.on('message', function(msg) {
//log('got message: ' + msg); //log('got message: ' + msg);
if (client.protocol === 'base64') { target.write(msg);
target.write(new Buffer(msg, 'base64'));
} else {
target.write(msg,'binary');
}
}); });
client.on('close', function(code, reason) { client.on('close', function(code, reason) {
log('WebSocket client disconnected: ' + code + ' [' + reason + ']'); log('WebSocket client disconnected: ' + code + ' [' + reason + ']');
@ -123,18 +115,6 @@ http_request = function (request, response) {
}); });
}; };
// Select 'binary' or 'base64' subprotocol, preferring 'binary'
selectProtocol = function(protocols, callback) {
if (protocols.indexOf('binary') >= 0) {
callback(true, 'binary');
} else if (protocols.indexOf('base64') >= 0) {
callback(true, 'base64');
} else {
console.log("Client must support 'binary' or 'base64' protocol");
callback(false);
}
}
// parse source and target arguments into parts // parse source and target arguments into parts
try { try {
source_arg = argv._[0].toString(); source_arg = argv._[0].toString();
@ -183,8 +163,7 @@ if (argv.cert) {
webServer = http.createServer(http_request); webServer = http.createServer(http_request);
} }
webServer.listen(source_port, function() { webServer.listen(source_port, function() {
wsServer = new WebSocketServer({server: webServer, wsServer = new WebSocketServer({server: webServer});
handleProtocols: selectProtocol});
wsServer.on('connection', new_client); wsServer.on('connection', new_client);
}); });

View File

@ -13,7 +13,6 @@ require 'openssl'
require 'stringio' require 'stringio'
require 'digest/md5' require 'digest/md5'
require 'digest/sha1' require 'digest/sha1'
require 'base64'
unless OpenSSL::SSL::SSLSocket.instance_methods.index("read_nonblock") unless OpenSSL::SSL::SSLSocket.instance_methods.index("read_nonblock")
module OpenSSL module OpenSSL
@ -92,7 +91,6 @@ Sec-WebSocket-Accept: %s\r
t[:my_client_id] = @@client_id t[:my_client_id] = @@client_id
t[:send_parts] = [] t[:send_parts] = []
t[:recv_part] = nil t[:recv_part] = nil
t[:base64] = nil
puts "in serve, client: #{t[:my_client_id].inspect}" puts "in serve, client: #{t[:my_client_id].inspect}"
@ -151,11 +149,7 @@ Sec-WebSocket-Accept: %s\r
return data return data
end end
def encode_hybi(buf, opcode, base64=false) def encode_hybi(buf, opcode)
if base64
buf = Base64.encode64(buf).gsub(/\n/, '')
end
b1 = 0x80 | (opcode & 0x0f) # FIN + opcode b1 = 0x80 | (opcode & 0x0f) # FIN + opcode
payload_len = buf.length payload_len = buf.length
if payload_len <= 125 if payload_len <= 125
@ -170,7 +164,7 @@ Sec-WebSocket-Accept: %s\r
return [header + buf, header.length, 0] return [header + buf, header.length, 0]
end end
def decode_hybi(buf, base64=false) def decode_hybi(buf)
f = {'fin' => 0, f = {'fin' => 0,
'opcode' => 0, 'opcode' => 0,
'hlen' => 2, 'hlen' => 2,
@ -216,10 +210,6 @@ Sec-WebSocket-Accept: %s\r
f['payload'] = buf[f['hlen']...full_len] f['payload'] = buf[f['hlen']...full_len]
end end
if base64 and [1, 2].include?(f['opcode'])
f['payload'] = Base64.decode64(f['payload'])
end
# close frame # close frame
if f['opcode'] == 0x08 if f['opcode'] == 0x08
if f['length'] >= 2 if f['length'] >= 2
@ -251,13 +241,8 @@ Sec-WebSocket-Accept: %s\r
encbuf = "" encbuf = ""
bufs.each do |buf| bufs.each do |buf|
if t[:version].start_with?("hybi") if t[:version].start_with?("hybi")
if t[:base64]
encbuf, lenhead, lentail = encode_hybi( encbuf, lenhead, lentail = encode_hybi(
buf, opcode=1, base64=true) buf, opcode=2)
else
encbuf, lenhead, lentail = encode_hybi(
buf, opcode=2, base64=false)
end
else else
encbuf, lenhead, lentail = encode_hixie(buf) encbuf, lenhead, lentail = encode_hixie(buf)
end end
@ -302,7 +287,7 @@ Sec-WebSocket-Accept: %s\r
while buf.length > 0 while buf.length > 0
if t[:version].start_with?("hybi") if t[:version].start_with?("hybi")
frame = decode_hybi(buf, base64=t[:base64]) frame = decode_hybi(buf)
if frame['payload'] == nil if frame['payload'] == nil
traffic "}." traffic "}."
@ -359,7 +344,7 @@ Sec-WebSocket-Accept: %s\r
msg = [reason.length, code].pack("na8") msg = [reason.length, code].pack("na8")
end end
buf, lenh, lent = encode_hybi(msg, opcode=0x08, base64=false) buf, lenh, lent = encode_hybi(msg, opcode=0x08)
t[:client].write(buf) t[:client].write(buf)
elsif t[:version] == "hixie-76" elsif t[:version] == "hixie-76"
buf = "\xff\x00" buf = "\xff\x00"
@ -412,7 +397,6 @@ Sec-WebSocket-Accept: %s\r
protocols = h.fetch("sec-websocket-protocol", h["websocket-protocol"]) protocols = h.fetch("sec-websocket-protocol", h["websocket-protocol"])
ver = h.fetch('sec-websocket-version', nil) ver = h.fetch('sec-websocket-version', nil)
if ver
# HyBi/IETF vesrion of the protocol # HyBi/IETF vesrion of the protocol
# HyBi 07 reports version 7 # HyBi 07 reports version 7
@ -424,15 +408,6 @@ Sec-WebSocket-Accept: %s\r
raise EClose, "Unsupported protocol version %s" % [ver] raise EClose, "Unsupported protocol version %s" % [ver]
end end
# choose binary if client supports it
if protocols.include?('binary')
t[:base64] = false
elsif protocols.include?('base64')
t[:base64] = true
else
raise EClose, "Client must support 'binary' or 'base64' sub-protocol"
end
key = h['sec-websocket-key'] key = h['sec-websocket-key']
# Generate the hash value for the accpet header # Generate the hash value for the accpet header
@ -441,44 +416,10 @@ Sec-WebSocket-Accept: %s\r
response = @@Server_handshake_hybi % [accept] response = @@Server_handshake_hybi % [accept]
if t[:base64]
response += "Sec-WebSocket-Protocol: base64\r\n"
else
response += "Sec-WebSocket-Protocol: binary\r\n"
end
response += "\r\n" response += "\r\n"
else
# Hixie vesrion of the protocol (75 or 76)
body = handshake.match(/\r\n\r\n(........)/)
if body
h['key3'] = body[1]
trailer = gen_md5(h)
pre = "Sec-"
t[:version] = "hixie-76"
else
trailer = ""
pre = ""
t[:version] = "hixie-75"
end
# base64 required for Hixie since payload is only UTF-8
t[:base64] = true
response = @@Server_handshake_hixie % [pre, h['origin'], pre,
"ws", h['host'], t[:path]]
if protocols && protocols.include?('base64')
response += "%sWebSocket-Protocol: base64\r\n" % [pre]
else
msg "Warning: client does not report 'base64' protocol support"
end
response += "\r\n" + trailer
end
msg "%s WebSocket connection" % [stype] msg "%s WebSocket connection" % [stype]
msg "Version %s, base64: '%s'" % [t[:version], t[:base64]] msg "Version %s" % [t[:version]]
if t[:path] then msg "Path: '%s'" % [t[:path]] end if t[:path] then msg "Path: '%s'" % [t[:path]] end
#puts "sending reponse #{response.inspect}" #puts "sending reponse #{response.inspect}"

View File

@ -1,29 +0,0 @@
#!/usr/bin/env python
from base64 import b64encode, b64decode
from codecs import (utf_8_encode, utf_8_decode,
latin_1_encode, latin_1_decode)
import random, time
buf_len = 10000
iterations = 10000
print "Generating random input buffer"
r = random.Random()
buf = "".join([chr(r.randint(0, 255)) for i in range(buf_len)])
tests = {'UTF8 encode': lambda: utf_8_encode(unicode(buf, 'latin-1'))[0],
'B64 encode': lambda: b64encode(buf)}
utf8_buf = tests['UTF8 encode']()
b64_buf = tests['B64 encode']()
tests.update({'UTF8 decode': lambda: latin_1_encode(utf_8_decode(utf8_buf)[0])[0],
'B64 decode': lambda: b64decode(b64_buf)})
print "Running tests"
for test in 'UTF8 encode', 'B64 encode', 'UTF8 decode', 'B64 decode':
start = time.time()
for i in range(iterations):
res_buf = tests[test]()
print "%s took %s seconds (result size %s)" % (
test, (time.time() - start), len(res_buf))

View File

@ -1,91 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Native Base64 Tests</title>
<script src="include/util.js"></script>
<script src="include/webutil.js"></script>
<script src="include/base64.js"></script>
</head>
<body>
<h1>Native Base64 Tests</h1>
<br>
Messages:<br>
<textarea id="debug" style="font-size: 9px;" cols=80 rows=25></textarea>
<br>
</body>
<script>
function debug(str) {
console.log(str);
cell = $D('debug');
cell.innerHTML += str + "\n";
cell.scrollTop = cell.scrollHeight;
}
function assertRun(code, result) {
try {
var actual = eval(code);
} catch (exc) {
debug("FAIL: '" + code + "' threw an exception");
fail += 1;
return false;
}
if (actual !== result) {
debug("FAIL: '" + code + "' returned '" + actual + "', expected '" + result + "'");
fail += 1;
return false;
}
debug("PASS: '" + code + "' returned expected '" + result +"'");
pass += 1;
return true;
}
function Base64_decode(data) {
var arr = Base64.decode (data);
return arr.map(function (num) {
return String.fromCharCode(num); } ).join('');
}
window.onload = function() {
var str;
debug('onload');
fail = 0;
pass = 0;
assertRun('window.btoa("hello world")', 'aGVsbG8gd29ybGQ=');
assertRun('window.btoa("a")', 'YQ==');
assertRun('window.btoa("ab")', 'YWI=');
assertRun('window.btoa("abc")', 'YWJj');
assertRun('window.btoa("abcd")', 'YWJjZA==');
assertRun('window.btoa("abcde")', 'YWJjZGU=');
assertRun('window.btoa("abcdef")', 'YWJjZGVm');
assertRun('window.btoa("abcdefg")', 'YWJjZGVmZw==');
assertRun('window.btoa("abcdefgh")', 'YWJjZGVmZ2g=');
assertRun('window.atob("aGVsbG8gd29ybGQ=")', 'hello world');
assertRun('Base64_decode("aGVsbG8gd29ybGQ=")', 'hello world');
assertRun('window.atob("YQ==")', 'a');
assertRun('Base64_decode("YQ==")', 'a');
assertRun('window.atob("YWI=")', 'ab');
assertRun('Base64_decode("YWI=")', 'ab');
assertRun('window.atob("YWJj")', 'abc');
assertRun('Base64_decode("YWJj")', 'abc');
assertRun('window.atob("YWJjZA==")', 'abcd');
assertRun('Base64_decode("YWJjZA==")', 'abcd');
assertRun('window.atob("YWJjZGU=")', 'abcde');
assertRun('Base64_decode("YWJjZGU=")', 'abcde');
assertRun('window.atob("YWJjZGVm")', 'abcdef');
assertRun('Base64_decode("YWJjZGVm")', 'abcdef');
assertRun('typeof window.btoa', 'function');
assertRun('window.btoa("")', '');
assertRun('window.btoa(null)', '');
assertRun('window.atob(window.btoa(window))', window.toString()); // "[object DOMWindow]"
assertRun('window.btoa("\\u0080\\u0081")', 'gIE=');
debug("Tests failed: " + fail);
debug("Tests passed: " + pass);
}
</script>

View File

@ -1,12 +0,0 @@
// The following results in 'hello [MANGLED]'
//
// Filed as https://github.com/ry/node/issues/issue/402
var sys = require("sys"),
buf = new Buffer(1024), len,
str1 = "aGVsbG8g", // 'hello '
str2 = "d29ybGQ=", // 'world'
len = buf.write(str1, 0, 'base64');
len += buf.write(str2, len, 'base64');
sys.log("decoded result: " + buf.toString('binary', 0, len));

View File

@ -4,7 +4,6 @@
<title>WebSockets Echo Test</title> <title>WebSockets Echo Test</title>
<script src="include/util.js"></script> <script src="include/util.js"></script>
<script src="include/webutil.js"></script> <script src="include/webutil.js"></script>
<script src="include/base64.js"></script>
<script src="include/websock.js"></script> <script src="include/websock.js"></script>
<!-- Uncomment to activate firebug lite --> <!-- Uncomment to activate firebug lite -->
<!-- <!--

View File

@ -2,7 +2,6 @@
<head> <head>
<title>WebSockets Latency Test</title> <title>WebSockets Latency Test</title>
<script src="include/base64.js"></script>
<script src="include/util.js"></script> <script src="include/util.js"></script>
<script src="include/webutil.js"></script> <script src="include/webutil.js"></script>
<script src="include/websock.js"></script> <script src="include/websock.js"></script>

View File

@ -4,7 +4,6 @@
<title>WebSockets Load Test</title> <title>WebSockets Load Test</title>
<script src="include/util.js"></script> <script src="include/util.js"></script>
<script src="include/webutil.js"></script> <script src="include/webutil.js"></script>
<script src="include/base64.js"></script>
<script src="include/websock.js"></script> <script src="include/websock.js"></script>
<!-- Uncomment to activate firebug lite --> <!-- Uncomment to activate firebug lite -->
<!-- <!--

View File

@ -90,7 +90,7 @@
} }
uri = scheme + host + ":" + port; uri = scheme + host + ":" + port;
message("connecting to " + uri); message("connecting to " + uri);
ws = new WebSocket(uri, "base64"); ws = new WebSocket(uri);
ws.onmessage = function(e) { ws.onmessage = function(e) {
//console.log(">> WebSockets.onmessage"); //console.log(">> WebSockets.onmessage");

View File

@ -3,7 +3,6 @@
<head> <head>
<title>Websock Simple Client</title> <title>Websock Simple Client</title>
<script src="include/util.js"></script> <script src="include/util.js"></script>
<script src="include/base64.js"></script>
<script src="include/websock.js"></script> <script src="include/websock.js"></script>
</head> </head>

View File

@ -1,19 +0,0 @@
#!/usr/bin/python
'''
Display UTF-8 encoding for 0-255.'''
import sys, os, socket, ssl, time, traceback
from select import select
sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))
from websockify.websocket import WebSocketServer
if __name__ == '__main__':
print "val: hybi_base64 | hybi_binary"
for c in range(0, 256):
hybi_base64 = WebSocketServer.encode_hybi(chr(c), opcode=1,
base64=True)
hybi_binary = WebSocketServer.encode_hybi(chr(c), opcode=2,
base64=False)
print "%d: %s | %s" % (c, repr(hybi_base64), repr(hybi_binary))

View File

@ -18,7 +18,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
import os, sys, time, errno, signal, socket, select, logging import os, sys, time, errno, signal, socket, select, logging
import array, ssl, multiprocessing import array, ssl, multiprocessing
from base64 import b64encode, b64decode from base64 import b64encode
from hashlib import sha1 from hashlib import sha1
from struct import pack, unpack_from from struct import pack, unpack_from
@ -141,7 +141,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
return data.tostring() return data.tostring()
@staticmethod @staticmethod
def encode_hybi(buf, opcode, base64=False): def encode_hybi(buf, opcode):
""" Encode a HyBi style WebSocket frame. """ Encode a HyBi style WebSocket frame.
Optional opcode: Optional opcode:
0x0 - continuation 0x0 - continuation
@ -151,8 +151,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
0x9 - ping 0x9 - ping
0xA - pong 0xA - pong
""" """
if base64:
buf = b64encode(buf)
b1 = 0x80 | (opcode & 0x0f) # FIN + opcode b1 = 0x80 | (opcode & 0x0f) # FIN + opcode
payload_len = len(buf) payload_len = len(buf)
@ -168,7 +166,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
return header + buf, len(header), 0 return header + buf, len(header), 0
@staticmethod @staticmethod
def decode_hybi(buf, base64=False, logger=None, strict=True): def decode_hybi(buf, logger=None, strict=True):
""" Decode HyBi style WebSocket packets. """ Decode HyBi style WebSocket packets.
Returns: Returns:
{'fin' : 0_or_1, {'fin' : 0_or_1,
@ -240,14 +238,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
f['payload'] = buf[(f['hlen'] + f['masked'] * 4):full_len] f['payload'] = buf[(f['hlen'] + f['masked'] * 4):full_len]
if base64 and f['opcode'] in [1, 2]:
try:
f['payload'] = b64decode(f['payload'])
except:
logger.exception("Exception while b64decoding buffer: %s" %
(repr(buf)))
raise
if f['opcode'] == 0x08: if f['opcode'] == 0x08:
if f['length'] >= 2: if f['length'] >= 2:
f['close_code'] = unpack_from(">H", f['payload'])[0] f['close_code'] = unpack_from(">H", f['payload'])[0]
@ -297,10 +287,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
if bufs: if bufs:
for buf in bufs: for buf in bufs:
if self.base64: encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=2)
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=1, base64=True)
else:
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=2, base64=False)
if self.rec: if self.rec:
self.rec.write("%s,\n" % self.rec.write("%s,\n" %
@ -345,7 +332,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.recv_part = None self.recv_part = None
while buf: while buf:
frame = self.decode_hybi(buf, base64=self.base64, frame = self.decode_hybi(buf,
logger=self.logger, logger=self.logger,
strict=self.strict_mode) strict=self.strict_mode)
#self.msg("Received buf: %s, frame: %s", repr(buf), frame) #self.msg("Received buf: %s, frame: %s", repr(buf), frame)
@ -399,17 +386,17 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
""" Send a WebSocket orderly close frame. """ """ Send a WebSocket orderly close frame. """
msg = pack(">H%ds" % len(reason), code, s2b(reason)) msg = pack(">H%ds" % len(reason), code, s2b(reason))
buf, h, t = self.encode_hybi(msg, opcode=0x08, base64=False) buf, h, t = self.encode_hybi(msg, opcode=0x08)
self.request.send(buf) self.request.send(buf)
def send_pong(self, data=''): def send_pong(self, data=''):
""" Send a WebSocket pong frame. """ """ Send a WebSocket pong frame. """
buf, h, t = self.encode_hybi(s2b(data), opcode=0x0A, base64=False) buf, h, t = self.encode_hybi(s2b(data), opcode=0x0A)
self.request.send(buf) self.request.send(buf)
def send_ping(self, data=''): def send_ping(self, data=''):
""" Send a WebSocket ping frame. """ """ Send a WebSocket ping frame. """
buf, h, t = self.encode_hybi(s2b(data), opcode=0x09, base64=False) buf, h, t = self.encode_hybi(s2b(data), opcode=0x09)
self.request.send(buf) self.request.send(buf)
def do_websocket_handshake(self): def do_websocket_handshake(self):
@ -433,15 +420,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
key = h['Sec-WebSocket-Key'] key = h['Sec-WebSocket-Key']
# Choose binary if client supports it
if 'binary' in protocols:
self.base64 = False
elif 'base64' in protocols:
self.base64 = True
else:
self.send_error(400, "Client must support 'binary' or 'base64' protocol")
return False
# Generate the hash value for the accept header # Generate the hash value for the accept header
accept = b64encode(sha1(s2b(key + self.GUID)).digest()) accept = b64encode(sha1(s2b(key + self.GUID)).digest())
@ -449,10 +427,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.send_header("Upgrade", "websocket") self.send_header("Upgrade", "websocket")
self.send_header("Connection", "Upgrade") self.send_header("Connection", "Upgrade")
self.send_header("Sec-WebSocket-Accept", b2s(accept)) self.send_header("Sec-WebSocket-Accept", b2s(accept))
if self.base64:
self.send_header("Sec-WebSocket-Protocol", "base64")
else:
self.send_header("Sec-WebSocket-Protocol", "binary")
self.end_headers() self.end_headers()
# Other requests cannot follow Websocket data # Other requests cannot follow Websocket data
@ -501,8 +475,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.log_message("%s: %s WebSocket connection", client_addr, self.log_message("%s: %s WebSocket connection", client_addr,
self.stype) self.stype)
self.log_message("%s: Version %s, base64: '%s'", client_addr,
self.version, self.base64)
if self.path != '/': if self.path != '/':
self.log_message("%s: Path: '%s'", client_addr, self.path) self.log_message("%s: Path: '%s'", client_addr, self.path)
@ -512,10 +484,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.handler_id) self.handler_id)
self.log_message("opening record file: %s", fname) self.log_message("opening record file: %s", fname)
self.rec = open(fname, 'w+') self.rec = open(fname, 'w+')
encoding = "binary"
if self.base64: encoding = "base64"
self.rec.write("var VNC_frame_encoding = '%s';\n"
% encoding)
self.rec.write("var VNC_frame_data = [\n") self.rec.write("var VNC_frame_data = [\n")
try: try:

View File

@ -220,9 +220,7 @@ Traffic Legend:
class WebSocketProxy(websocket.WebSocketServer): class WebSocketProxy(websocket.WebSocketServer):
""" """
Proxy traffic to and from a WebSockets client to a normal TCP Proxy traffic to and from a WebSockets client to a normal TCP
socket server target. All traffic to/from the client is base64 socket server target.
encoded/decoded to allow binary data to be sent/received to/from
the target.
""" """
buffer_size = 65536 buffer_size = 65536

View File

@ -2,7 +2,6 @@
<head> <head>
<title>IRC Client using WebSockets</title> <title>IRC Client using WebSockets</title>
<script src="include/base64.js"></script>
<script src="include/websock.js"></script> <script src="include/websock.js"></script>
<script src="include/util.js"></script> <script src="include/util.js"></script>
<script src="include/webutil.js"></script> <script src="include/webutil.js"></script>

View File

@ -2,7 +2,6 @@
<head> <head>
<title>Telnet client using WebSockets</title> <title>Telnet client using WebSockets</title>
<script src="include/base64.js"></script>
<script src="include/util.js"></script> <script src="include/util.js"></script>
<script src="include/websock.js"></script> <script src="include/websock.js"></script>
<script src="include/webutil.js"></script> <script src="include/webutil.js"></script>