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/base64.js : MPL 2.0
include/des.js : Various BSD style licenses
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
Starting with websockify 0.5.0, only the HyBi / IETF
6455 WebSocket protocol is supported.
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.
6455 WebSocket protocol is supported. There is no support for the older
Base64 encoded data format.
### 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
object that is similar to the standard WebSocket object but Websock
enables communication with raw TCP sockets (i.e. the binary stream)
via websockify. This is accomplished by base64 encoding the data
stream between Websock and websockify.
via websockify.
Websock has built-in receive queue buffering; the message event
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
* enables communication with raw TCP sockets (i.e. the binary stream)
* via websockify. This is accomplished by base64 encoding the data
* stream between Websock and websockify.
* via websockify.
*
* Websock has built-in receive queue buffering; the message event
* does not contain actual data but is simply a notification that
@ -15,7 +14,7 @@
*/
/*jslint browser: true, bitwise: false, plusplus: false */
/*global Util, Base64 */
/*global Util */
// Load Flash WebSocket emulator if needed
@ -52,7 +51,6 @@ function Websock() {
var api = {}, // Public API
websocket = null, // WebSocket object
mode = 'base64', // Current WebSocket mode: 'binary', 'base64'
rQ = [], // Receive queue
rQi = 0, // Receive queue index
rQmax = 10000, // Max receive queue size before compacting
@ -154,36 +152,6 @@ function rQwait(msg, num, goback) {
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
//
@ -196,7 +164,7 @@ function flush() {
//Util.Debug("arr: " + arr);
//Util.Debug("sQ: " + sQ);
if (sQ.length > 0) {
websocket.send(encode_message(sQ));
websocket.send((new Uint8Array(sQ)).buffer);
sQ = [];
}
return true;
@ -227,7 +195,10 @@ function recv_message(e) {
//Util.Debug(">> recv_message: " + e.data.length);
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) {
eventHandlers.message();
// Compact the receive queue
@ -262,92 +233,27 @@ function on(evt, handler) {
eventHandlers[evt] = handler;
}
function init(protocols, ws_schema) {
function init() {
rQ = [];
rQi = 0;
sQ = [];
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) {
var ws_schema = uri.match(/^([a-z]+):\/\//)[1];
protocols = init(protocols, ws_schema);
init();
if (test_mode) {
websocket = {};
} else {
websocket = new WebSocket(uri, protocols);
if (protocols.indexOf('binary') >= 0) {
websocket.binaryType = 'arraybuffer';
}
websocket.binaryType = 'arraybuffer';
}
websocket.onmessage = recv_message;
websocket.onopen = function() {
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();
Util.Debug("<< WebSock.onopen");
};
@ -376,9 +282,8 @@ function close() {
// Override internal functions for testing
// Takes a send function, returns reference to recv function
function testMode(override_send, data_mode) {
function testMode(override_send) {
test_mode = true;
mode = data_mode;
api.send = override_send;
api.close = function () {};
return recv_message;

View File

@ -42,11 +42,7 @@ new_client = function(client) {
target.on('data', function(data) {
//log("sending message: " + data);
try {
if (client.protocol === 'base64') {
client.send(new Buffer(data).toString('base64'));
} else {
client.send(data,{binary: true});
}
client.send(data);
} catch(e) {
log("Client closed, cleaning up target");
target.end();
@ -64,11 +60,7 @@ new_client = function(client) {
client.on('message', function(msg) {
//log('got message: ' + msg);
if (client.protocol === 'base64') {
target.write(new Buffer(msg, 'base64'));
} else {
target.write(msg,'binary');
}
target.write(msg);
});
client.on('close', function(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
try {
source_arg = argv._[0].toString();
@ -183,8 +163,7 @@ if (argv.cert) {
webServer = http.createServer(http_request);
}
webServer.listen(source_port, function() {
wsServer = new WebSocketServer({server: webServer,
handleProtocols: selectProtocol});
wsServer = new WebSocketServer({server: webServer});
wsServer.on('connection', new_client);
});

View File

@ -13,7 +13,6 @@ require 'openssl'
require 'stringio'
require 'digest/md5'
require 'digest/sha1'
require 'base64'
unless OpenSSL::SSL::SSLSocket.instance_methods.index("read_nonblock")
module OpenSSL
@ -92,7 +91,6 @@ Sec-WebSocket-Accept: %s\r
t[:my_client_id] = @@client_id
t[:send_parts] = []
t[:recv_part] = nil
t[:base64] = nil
puts "in serve, client: #{t[:my_client_id].inspect}"
@ -151,11 +149,7 @@ Sec-WebSocket-Accept: %s\r
return data
end
def encode_hybi(buf, opcode, base64=false)
if base64
buf = Base64.encode64(buf).gsub(/\n/, '')
end
def encode_hybi(buf, opcode)
b1 = 0x80 | (opcode & 0x0f) # FIN + opcode
payload_len = buf.length
if payload_len <= 125
@ -170,7 +164,7 @@ Sec-WebSocket-Accept: %s\r
return [header + buf, header.length, 0]
end
def decode_hybi(buf, base64=false)
def decode_hybi(buf)
f = {'fin' => 0,
'opcode' => 0,
'hlen' => 2,
@ -216,10 +210,6 @@ Sec-WebSocket-Accept: %s\r
f['payload'] = buf[f['hlen']...full_len]
end
if base64 and [1, 2].include?(f['opcode'])
f['payload'] = Base64.decode64(f['payload'])
end
# close frame
if f['opcode'] == 0x08
if f['length'] >= 2
@ -251,13 +241,8 @@ Sec-WebSocket-Accept: %s\r
encbuf = ""
bufs.each do |buf|
if t[:version].start_with?("hybi")
if t[:base64]
encbuf, lenhead, lentail = encode_hybi(
buf, opcode=1, base64=true)
else
encbuf, lenhead, lentail = encode_hybi(
buf, opcode=2, base64=false)
end
encbuf, lenhead, lentail = encode_hybi(
buf, opcode=2)
else
encbuf, lenhead, lentail = encode_hixie(buf)
end
@ -302,7 +287,7 @@ Sec-WebSocket-Accept: %s\r
while buf.length > 0
if t[:version].start_with?("hybi")
frame = decode_hybi(buf, base64=t[:base64])
frame = decode_hybi(buf)
if frame['payload'] == nil
traffic "}."
@ -359,7 +344,7 @@ Sec-WebSocket-Accept: %s\r
msg = [reason.length, code].pack("na8")
end
buf, lenh, lent = encode_hybi(msg, opcode=0x08, base64=false)
buf, lenh, lent = encode_hybi(msg, opcode=0x08)
t[:client].write(buf)
elsif t[:version] == "hixie-76"
buf = "\xff\x00"
@ -412,73 +397,29 @@ Sec-WebSocket-Accept: %s\r
protocols = h.fetch("sec-websocket-protocol", h["websocket-protocol"])
ver = h.fetch('sec-websocket-version', nil)
if ver
# HyBi/IETF vesrion of the protocol
# HyBi 07 reports version 7
# HyBi 08 - 12 report version 8
# HyBi 13 and up report version 13
if ['7', '8', '13'].include?(ver)
t[:version] = "hybi-%02d" % [ver.to_i]
else
raise EClose, "Unsupported protocol version %s" % [ver]
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']
# Generate the hash value for the accpet header
accept = Base64.encode64(
Digest::SHA1.digest(key + @@GUID)).gsub(/\n/, '')
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"
# HyBi/IETF vesrion of the protocol
# HyBi 07 reports version 7
# HyBi 08 - 12 report version 8
# HyBi 13 and up report version 13
if ['7', '8', '13'].include?(ver)
t[:version] = "hybi-%02d" % [ver.to_i]
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
raise EClose, "Unsupported protocol version %s" % [ver]
end
key = h['sec-websocket-key']
# Generate the hash value for the accpet header
accept = Base64.encode64(
Digest::SHA1.digest(key + @@GUID)).gsub(/\n/, '')
response = @@Server_handshake_hybi % [accept]
response += "\r\n"
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
#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>
<script src="include/util.js"></script>
<script src="include/webutil.js"></script>
<script src="include/base64.js"></script>
<script src="include/websock.js"></script>
<!-- Uncomment to activate firebug lite -->
<!--

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@
<head>
<title>Websock Simple Client</title>
<script src="include/util.js"></script>
<script src="include/base64.js"></script>
<script src="include/websock.js"></script>
</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 array, ssl, multiprocessing
from base64 import b64encode, b64decode
from base64 import b64encode
from hashlib import sha1
from struct import pack, unpack_from
@ -141,7 +141,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
return data.tostring()
@staticmethod
def encode_hybi(buf, opcode, base64=False):
def encode_hybi(buf, opcode):
""" Encode a HyBi style WebSocket frame.
Optional opcode:
0x0 - continuation
@ -151,8 +151,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
0x9 - ping
0xA - pong
"""
if base64:
buf = b64encode(buf)
b1 = 0x80 | (opcode & 0x0f) # FIN + opcode
payload_len = len(buf)
@ -168,7 +166,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
return header + buf, len(header), 0
@staticmethod
def decode_hybi(buf, base64=False, logger=None, strict=True):
def decode_hybi(buf, logger=None, strict=True):
""" Decode HyBi style WebSocket packets.
Returns:
{'fin' : 0_or_1,
@ -240,14 +238,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
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['length'] >= 2:
f['close_code'] = unpack_from(">H", f['payload'])[0]
@ -297,10 +287,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
if bufs:
for buf in bufs:
if self.base64:
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=1, base64=True)
else:
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=2, base64=False)
encbuf, lenhead, lentail = self.encode_hybi(buf, opcode=2)
if self.rec:
self.rec.write("%s,\n" %
@ -345,7 +332,7 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.recv_part = None
while buf:
frame = self.decode_hybi(buf, base64=self.base64,
frame = self.decode_hybi(buf,
logger=self.logger,
strict=self.strict_mode)
#self.msg("Received buf: %s, frame: %s", repr(buf), frame)
@ -399,17 +386,17 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
""" Send a WebSocket orderly close frame. """
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)
def send_pong(self, data=''):
""" 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)
def send_ping(self, data=''):
""" 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)
def do_websocket_handshake(self):
@ -433,15 +420,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
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
accept = b64encode(sha1(s2b(key + self.GUID)).digest())
@ -449,10 +427,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.send_header("Upgrade", "websocket")
self.send_header("Connection", "Upgrade")
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()
# Other requests cannot follow Websocket data
@ -501,8 +475,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.log_message("%s: %s WebSocket connection", client_addr,
self.stype)
self.log_message("%s: Version %s, base64: '%s'", client_addr,
self.version, self.base64)
if self.path != '/':
self.log_message("%s: Path: '%s'", client_addr, self.path)
@ -512,10 +484,6 @@ class WebSocketRequestHandler(SimpleHTTPRequestHandler):
self.handler_id)
self.log_message("opening record file: %s", fname)
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")
try:

View File

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

View File

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

View File

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