Commit fc003a13 authored by Joel Martin's avatar Joel Martin

Revert "Pull in latest websockify."

This reverts commit 4dd1bb1e.
parent ca6b3f4c
...@@ -61,8 +61,6 @@ function Websock() { ...@@ -61,8 +61,6 @@ function Websock() {
var api = {}, // Public API var api = {}, // Public API
websocket = null, // WebSocket object websocket = null, // WebSocket object
protocols, // Protocols to request in priority order
mode = '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
...@@ -125,46 +123,26 @@ function rQshift32() { ...@@ -125,46 +123,26 @@ function rQshift32() {
(rQ[rQi++] << 8) + (rQ[rQi++] << 8) +
(rQ[rQi++] ); (rQ[rQi++] );
} }
function rQslice(start, end) {
if (mode === 'binary') {
if (end) {
return rQ.subarray(rQi + start, rQi + end);
} else {
return rQ.subarray(rQi + start);
}
} else {
if (end) {
return rQ.slice(rQi + start, rQi + end);
} else {
return rQ.slice(rQi + start);
}
}
}
function rQshiftStr(len) { function rQshiftStr(len) {
if (typeof(len) === 'undefined') { len = rQlen(); } if (typeof(len) === 'undefined') { len = rQlen(); }
var arr = rQslice(0, len); var arr = rQ.slice(rQi, rQi + len);
rQi += len; rQi += len;
return String.fromCharCode.apply(null, arr); return arr.map(function (num) {
return String.fromCharCode(num); } ).join('');
} }
function rQshiftBytes(len) { function rQshiftBytes(len) {
if (typeof(len) === 'undefined') { len = rQlen(); } if (typeof(len) === 'undefined') { len = rQlen(); }
var a = rQslice(0, len), b = [];
if (mode === 'binary') {
// Convert to plain array
b.push.apply(b, a);
} else {
// Already plain array, just return the original
b = a
}
rQi += len; rQi += len;
return b; return rQ.slice(rQi-len, rQi);
} }
function rQshiftArray(len) {
if (typeof(len) === 'undefined') { len = rQlen(); } function rQslice(start, end) {
var a = rQslice(0, len); if (end) {
rQi += len; return rQ.slice(rQi + start, rQi + end);
return a; } else {
return rQ.slice(rQi + start);
}
} }
// Check to see if we must wait for 'num' bytes (default to FBU.bytes) // Check to see if we must wait for 'num' bytes (default to FBU.bytes)
...@@ -192,26 +170,13 @@ function rQwait(msg, num, goback) { ...@@ -192,26 +170,13 @@ function rQwait(msg, num, goback) {
function encode_message() { function encode_message() {
/* base64 encode */ /* base64 encode */
if (mode === 'binary') { return Base64.encode(sQ);
return (new Uint8Array(sQ)).buffer;
} else {
return Base64.encode(sQ);
}
} }
function decode_message(data) { function decode_message(data) {
//Util.Debug(">> decode_message: " + data); //Util.Debug(">> decode_message: " + data);
if (mode === 'binary') { /* base64 decode */
// Create new arraybuffer and dump old and new data into it rQ = rQ.concat(Base64.decode(data, 0));
// TODO: this could be far more efficient and re-use the array
var new_rQ = new Uint8Array(rQ.length + data.byteLength);
new_rQ.set(rQ);
new_rQ.set(new Uint8Array(data), rQ.length);
rQ = new_rQ;
} else {
/* base64 decode and concat to the end */
rQ = rQ.concat(Base64.decode(data, 0));
}
//Util.Debug(">> decode_message, rQ: " + rQ); //Util.Debug(">> decode_message, rQ: " + rQ);
} }
...@@ -265,7 +230,7 @@ function recv_message(e) { ...@@ -265,7 +230,7 @@ function recv_message(e) {
// Compact the receive queue // Compact the receive queue
if (rQ.length > rQmax) { if (rQ.length > rQmax) {
//Util.Debug("Compacting receive queue"); //Util.Debug("Compacting receive queue");
rQ = rQslice(rQi); rQ = rQ.slice(rQi);
rQi = 0; rQi = 0;
} }
} else { } else {
...@@ -298,32 +263,7 @@ function init() { ...@@ -298,32 +263,7 @@ function init() {
rQ = []; rQ = [];
rQi = 0; rQi = 0;
sQ = []; sQ = [];
websocket = null, websocket = null;
protocols = "base64";
var bt = false,
wsbt = false;
if (('Uint8Array' in window) &&
('set' in Uint8Array.prototype)) {
bt = true;
}
// TODO: this sucks, the property should exist on the prototype
// but it does not.
try {
if (bt && ('binaryType' in (new WebSocket("ws://localhost:17523")))) {
wsbt = true;
}
} catch (exc) {
// Just ignore failed test localhost connections
}
if (bt && wsbt) {
Util.Info("Detected binaryType support in WebSockets");
protocols = ['binary', 'base64'];
} else {
Util.Info("No binaryType support in WebSockets, using base64 encoding");
protocols = 'base64';
}
} }
function open(uri) { function open(uri) {
...@@ -332,22 +272,19 @@ function open(uri) { ...@@ -332,22 +272,19 @@ function open(uri) {
if (test_mode) { if (test_mode) {
websocket = {}; websocket = {};
} else { } else {
websocket = new WebSocket(uri, protocols); websocket = new WebSocket(uri, 'base64');
// TODO: future native binary support
//websocket = new WebSocket(uri, ['binary', 'base64']);
} }
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) { if (websocket.protocol) {
mode = websocket.protocol;
Util.Info("Server chose sub-protocol: " + websocket.protocol); Util.Info("Server chose sub-protocol: " + websocket.protocol);
} else { } else {
mode = 'base64';
Util.Error("Server select no sub-protocol!: " + websocket.protocol); Util.Error("Server select no sub-protocol!: " + websocket.protocol);
} }
if (mode === 'binary') {
websocket.binaryType = 'arraybuffer';
}
eventHandlers.open(); eventHandlers.open();
Util.Debug("<< WebSock.onopen"); Util.Debug("<< WebSock.onopen");
}; };
......
This diff is collapsed.
...@@ -13,11 +13,9 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates ...@@ -13,11 +13,9 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
import socket, optparse, time, os, sys, subprocess import socket, optparse, time, os, sys, subprocess
from select import select from select import select
import websocket from websocket import WebSocketServer
try: from urllib.parse import parse_qs, urlparse
except: from urlparse import parse_qs, urlparse
class WebSocketProxy(websocket.WebSocketServer): class WebSocketProxy(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. All traffic to/from the client is base64
...@@ -45,9 +43,6 @@ Traffic Legend: ...@@ -45,9 +43,6 @@ Traffic Legend:
self.target_port = kwargs.pop('target_port') self.target_port = kwargs.pop('target_port')
self.wrap_cmd = kwargs.pop('wrap_cmd') self.wrap_cmd = kwargs.pop('wrap_cmd')
self.wrap_mode = kwargs.pop('wrap_mode') self.wrap_mode = kwargs.pop('wrap_mode')
self.unix_target = kwargs.pop('unix_target')
self.ssl_target = kwargs.pop('ssl_target')
self.target_cfg = kwargs.pop('target_cfg')
# Last 3 timestamps command was run # Last 3 timestamps command was run
self.wrap_times = [0, 0, 0] self.wrap_times = [0, 0, 0]
...@@ -63,7 +58,6 @@ Traffic Legend: ...@@ -63,7 +58,6 @@ Traffic Legend:
if not self.rebinder: if not self.rebinder:
raise Exception("rebind.so not found, perhaps you need to run make") raise Exception("rebind.so not found, perhaps you need to run make")
self.rebinder = os.path.abspath(self.rebinder)
self.target_host = "127.0.0.1" # Loopback self.target_host = "127.0.0.1" # Loopback
# Find a free high port # Find a free high port
...@@ -77,10 +71,7 @@ Traffic Legend: ...@@ -77,10 +71,7 @@ Traffic Legend:
"REBIND_OLD_PORT": str(kwargs['listen_port']), "REBIND_OLD_PORT": str(kwargs['listen_port']),
"REBIND_NEW_PORT": str(self.target_port)}) "REBIND_NEW_PORT": str(self.target_port)})
if self.target_cfg: WebSocketServer.__init__(self, *args, **kwargs)
self.target_cfg = os.path.abspath(self.target_cfg)
websocket.WebSocketServer.__init__(self, *args, **kwargs)
def run_wrap_cmd(self): def run_wrap_cmd(self):
print("Starting '%s'" % " ".join(self.wrap_cmd)) print("Starting '%s'" % " ".join(self.wrap_cmd))
...@@ -97,26 +88,14 @@ Traffic Legend: ...@@ -97,26 +88,14 @@ Traffic Legend:
# Need to call wrapped command after daemonization so we can # Need to call wrapped command after daemonization so we can
# know when the wrapped command exits # know when the wrapped command exits
if self.wrap_cmd: if self.wrap_cmd:
dst_string = "'%s' (port %s)" % (" ".join(self.wrap_cmd), self.target_port) print(" - proxying from %s:%s to '%s' (port %s)\n" % (
elif self.unix_target: self.listen_host, self.listen_port,
dst_string = self.unix_target " ".join(self.wrap_cmd), self.target_port))
else:
dst_string = "%s:%s" % (self.target_host, self.target_port)
if self.target_cfg:
msg = " - proxying from %s:%s to targets in %s" % (
self.listen_host, self.listen_port, self.target_cfg)
else:
msg = " - proxying from %s:%s to %s" % (
self.listen_host, self.listen_port, dst_string)
if self.ssl_target:
msg += " (using SSL)"
print(msg + "\n")
if self.wrap_cmd:
self.run_wrap_cmd() self.run_wrap_cmd()
else:
print(" - proxying from %s:%s to %s:%s\n" % (
self.listen_host, self.listen_port,
self.target_host, self.target_port))
def poll(self): def poll(self):
# If we are wrapping a command, check it's status # If we are wrapping a command, check it's status
...@@ -158,26 +137,12 @@ Traffic Legend: ...@@ -158,26 +137,12 @@ Traffic Legend:
""" """
Called after a new WebSocket connection has been established. Called after a new WebSocket connection has been established.
""" """
# Checks if we receive a token, and look
# for a valid target for it then
if self.target_cfg:
(self.target_host, self.target_port) = self.get_target(self.target_cfg, self.path)
# Connect to the target # Connect to the target
if self.wrap_cmd: self.msg("connecting to: %s:%s" % (
msg = "connecting to command: %s" % (" ".join(self.wrap_cmd), self.target_port) self.target_host, self.target_port))
elif self.unix_target:
msg = "connecting to unix socket: %s" % self.unix_target
else:
msg = "connecting to: %s:%s" % (
self.target_host, self.target_port)
if self.ssl_target:
msg += " (using SSL)"
self.msg(msg)
tsock = self.socket(self.target_host, self.target_port, tsock = self.socket(self.target_host, self.target_port,
connect=True, use_ssl=self.ssl_target, unix_socket=self.unix_target) connect=True)
if self.verbose and not self.daemon: if self.verbose and not self.daemon:
print(self.traffic_legend) print(self.traffic_legend)
...@@ -189,49 +154,10 @@ Traffic Legend: ...@@ -189,49 +154,10 @@ Traffic Legend:
if tsock: if tsock:
tsock.shutdown(socket.SHUT_RDWR) tsock.shutdown(socket.SHUT_RDWR)
tsock.close() tsock.close()
self.vmsg("%s:%s: Closed target" %( self.vmsg("%s:%s: Target closed" %(
self.target_host, self.target_port)) self.target_host, self.target_port))
raise raise
def get_target(self, target_cfg, path):
"""
Parses the path, extracts a token, and looks for a valid
target for that token in the configuration file(s). Sets
target_host and target_port if successful
"""
# The files in targets contain the lines
# in the form of token: host:port
# Extract the token parameter from url
args = parse_qs(urlparse(path)[4]) # 4 is the query from url
if not len(args['token']):
raise self.EClose("Token not present")
token = args['token'][0].rstrip('\n')
# target_cfg can be a single config file or directory of
# config files
if os.path.isdir(target_cfg):
cfg_files = [os.path.join(target_cfg, f)
for f in os.listdir(target_cfg)]
else:
cfg_files = [target_cfg]
targets = {}
for f in cfg_files:
for line in [l.strip() for l in file(f).readlines()]:
if line and not line.startswith('#'):
ttoken, target = line.split(': ')
targets[ttoken] = target.strip()
self.vmsg("Target config: %s" % repr(targets))
if targets.has_key(token):
return targets[token].split(':')
else:
raise self.EClose("Token '%s' not found" % token)
def do_proxy(self, target): def do_proxy(self, target):
""" """
Proxy client WebSocket to normal target socket. Proxy client WebSocket to normal target socket.
...@@ -265,8 +191,6 @@ Traffic Legend: ...@@ -265,8 +191,6 @@ Traffic Legend:
# Receive target data, encode it and queue for client # Receive target data, encode it and queue for client
buf = target.recv(self.buffer_size) buf = target.recv(self.buffer_size)
if len(buf) == 0: if len(buf) == 0:
self.vmsg("%s:%s: Target closed connection" %(
self.target_host, self.target_port))
raise self.CClose(1000, "Target closed") raise self.CClose(1000, "Target closed")
cqueue.append(buf) cqueue.append(buf)
...@@ -287,13 +211,11 @@ Traffic Legend: ...@@ -287,13 +211,11 @@ Traffic Legend:
if closed: if closed:
# TODO: What about blocking on client socket? # TODO: What about blocking on client socket?
self.vmsg("%s:%s: Client closed connection" %(
self.target_host, self.target_port))
raise self.CClose(closed['code'], closed['reason']) raise self.CClose(closed['code'], closed['reason'])
def websockify_init(): def websockify_init():
usage = "\n %prog [options]" usage = "\n %prog [options]"
usage += " [source_addr:]source_port [target_addr:target_port]" usage += " [source_addr:]source_port target_addr:target_port"
usage += "\n %prog [options]" usage += "\n %prog [options]"
usage += " [source_addr:]source_port -- WRAP_COMMAND_LINE" usage += " [source_addr:]source_port -- WRAP_COMMAND_LINE"
parser = optparse.OptionParser(usage=usage) parser = optparse.OptionParser(usage=usage)
...@@ -313,29 +235,17 @@ def websockify_init(): ...@@ -313,29 +235,17 @@ def websockify_init():
parser.add_option("--key", default=None, parser.add_option("--key", default=None,
help="SSL key file (if separate from cert)") help="SSL key file (if separate from cert)")
parser.add_option("--ssl-only", action="store_true", parser.add_option("--ssl-only", action="store_true",
help="disallow non-encrypted client connections") help="disallow non-encrypted connections")
parser.add_option("--ssl-target", action="store_true",
help="connect to SSL target as SSL client")
parser.add_option("--unix-target",
help="connect to unix socket target", metavar="FILE")
parser.add_option("--web", default=None, metavar="DIR", parser.add_option("--web", default=None, metavar="DIR",
help="run webserver on same port. Serve files from DIR.") help="run webserver on same port. Serve files from DIR.")
parser.add_option("--wrap-mode", default="exit", metavar="MODE", parser.add_option("--wrap-mode", default="exit", metavar="MODE",
choices=["exit", "ignore", "respawn"], choices=["exit", "ignore", "respawn"],
help="action to take when the wrapped program exits " help="action to take when the wrapped program exits "
"or daemonizes: exit (default), ignore, respawn") "or daemonizes: exit (default), ignore, respawn")
parser.add_option("--prefer-ipv6", "-6",
action="store_true", dest="source_is_ipv6",
help="prefer IPv6 when resolving source_addr")
parser.add_option("--target-config", metavar="FILE",
dest="target_cfg",
help="Configuration file containing valid targets "
"in the form 'token: host:port' or, alternatively, a "
"directory containing configuration files of this form")
(opts, args) = parser.parse_args() (opts, args) = parser.parse_args()
# Sanity checks # Sanity checks
if len(args) < 2 and not opts.target_cfg: if len(args) < 2:
parser.error("Too few arguments") parser.error("Too few arguments")
if sys.argv.count('--'): if sys.argv.count('--'):
opts.wrap_cmd = args[1:] opts.wrap_cmd = args[1:]
...@@ -344,29 +254,24 @@ def websockify_init(): ...@@ -344,29 +254,24 @@ def websockify_init():
if len(args) > 2: if len(args) > 2:
parser.error("Too many arguments") parser.error("Too many arguments")
if not websocket.ssl and opts.ssl_target:
parser.error("SSL target requested and Python SSL module not loaded.");
if opts.ssl_only and not os.path.exists(opts.cert): if opts.ssl_only and not os.path.exists(opts.cert):
parser.error("SSL only and %s not found" % opts.cert) parser.error("SSL only and %s not found" % opts.cert)
# Parse host:port and convert ports to numbers # Parse host:port and convert ports to numbers
if args[0].count(':') > 0: if args[0].count(':') > 0:
opts.listen_host, opts.listen_port = args[0].rsplit(':', 1) opts.listen_host, opts.listen_port = args[0].rsplit(':', 1)
opts.listen_host = opts.listen_host.strip('[]')
else: else:
opts.listen_host, opts.listen_port = '', args[0] opts.listen_host, opts.listen_port = '', args[0]
try: opts.listen_port = int(opts.listen_port) try: opts.listen_port = int(opts.listen_port)
except: parser.error("Error parsing listen port") except: parser.error("Error parsing listen port")
if opts.wrap_cmd or opts.unix_target or opts.target_cfg: if opts.wrap_cmd:
opts.target_host = None opts.target_host = None
opts.target_port = None opts.target_port = None
else: else:
if args[1].count(':') > 0: if args[1].count(':') > 0:
opts.target_host, opts.target_port = args[1].rsplit(':', 1) opts.target_host, opts.target_port = args[1].rsplit(':', 1)
opts.target_host = opts.target_host.strip('[]')
else: else:
parser.error("Error parsing target") parser.error("Error parsing target")
try: opts.target_port = int(opts.target_port) try: opts.target_port = int(opts.target_port)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment