diff options
author | Solly Ross <sross@redhat.com> | 2015-02-17 17:45:57 -0500 |
---|---|---|
committer | Solly Ross <sross@redhat.com> | 2015-02-17 17:45:57 -0500 |
commit | 5cd6de495f25b6f7edf6097fa12f8d6f5385cc61 (patch) | |
tree | 404e7e80614dcdf82e1308105863bf5531964676 | |
parent | 985c433867efdca08c36126e2956ddbe6028a13c (diff) | |
download | novnc-5cd6de495f25b6f7edf6097fa12f8d6f5385cc61.tar.gz |
Actually remove the "websockify" file
Somehow, `utils/websockify` itself manage to sneak back in to
6f5148648bd0e0ffa7ad00474c230f5f1ff4e39f. This actually removes
it.
-rwxr-xr-x | utils/websockify | 471 |
1 files changed, 0 insertions, 471 deletions
diff --git a/utils/websockify b/utils/websockify deleted file mode 100755 index 7b3ec11..0000000 --- a/utils/websockify +++ /dev/null @@ -1,471 +0,0 @@ -#!/usr/bin/env python - -''' -A WebSocket to TCP socket proxy with support for "wss://" encryption. -Copyright 2011 Joel Martin -Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3) - -You can make a cert/key with openssl using: -openssl req -new -x509 -days 365 -nodes -out self.pem -keyout self.pem -as taken from http://docs.python.org/dev/library/ssl.html#certificates - -''' - -import signal, socket, optparse, time, os, sys, subprocess, logging -try: from socketserver import ForkingMixIn -except: from SocketServer import ForkingMixIn -try: from http.server import HTTPServer -except: from BaseHTTPServer import HTTPServer -from select import select -import websocket -try: - from urllib.parse import parse_qs, urlparse -except: - from cgi import parse_qs - from urlparse import urlparse - -class ProxyRequestHandler(websocket.WebSocketRequestHandler): - - traffic_legend = """ -Traffic Legend: - } - Client receive - }. - Client receive partial - { - Target receive - - > - Target send - >. - Target send partial - < - Client send - <. - Client send partial -""" - - def new_websocket_client(self): - """ - 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.server.target_cfg: - (self.server.target_host, self.server.target_port) = self.get_target(self.server.target_cfg, self.path) - - # Connect to the target - if self.server.wrap_cmd: - msg = "connecting to command: '%s' (port %s)" % (" ".join(self.server.wrap_cmd), self.server.target_port) - elif self.server.unix_target: - msg = "connecting to unix socket: %s" % self.server.unix_target - else: - msg = "connecting to: %s:%s" % ( - self.server.target_host, self.server.target_port) - - if self.server.ssl_target: - msg += " (using SSL)" - self.log_message(msg) - - tsock = websocket.WebSocketServer.socket(self.server.target_host, - self.server.target_port, - connect=True, use_ssl=self.server.ssl_target, unix_socket=self.server.unix_target) - - self.print_traffic(self.traffic_legend) - - # Start proxying - try: - self.do_proxy(tsock) - except: - if tsock: - tsock.shutdown(socket.SHUT_RDWR) - tsock.close() - if self.verbose: - self.log_message("%s:%s: Closed target", - self.server.target_host, self.server.target_port) - 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 args.has_key('token') or 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): - """ - Proxy client WebSocket to normal target socket. - """ - cqueue = [] - c_pend = 0 - tqueue = [] - rlist = [self.request, target] - - while True: - wlist = [] - - if tqueue: wlist.append(target) - if cqueue or c_pend: wlist.append(self.request) - ins, outs, excepts = select(rlist, wlist, [], 1) - if excepts: raise Exception("Socket exception") - - if self.request in outs: - # Send queued target data to the client - c_pend = self.send_frames(cqueue) - - cqueue = [] - - if self.request in ins: - # Receive client data, decode it, and queue for target - bufs, closed = self.recv_frames() - tqueue.extend(bufs) - - if closed: - # TODO: What about blocking on client socket? - if self.verbose: - self.log_message("%s:%s: Client closed connection", - self.server.target_host, self.server.target_port) - raise self.CClose(closed['code'], closed['reason']) - - - if target in outs: - # Send queued client data to the target - dat = tqueue.pop(0) - sent = target.send(dat) - if sent == len(dat): - self.print_traffic(">") - else: - # requeue the remaining data - tqueue.insert(0, dat[sent:]) - self.print_traffic(".>") - - - if target in ins: - # Receive target data, encode it and queue for client - buf = target.recv(self.buffer_size) - if len(buf) == 0: - if self.verbose: - self.log_message("%s:%s: Target closed connection", - self.server.target_host, self.server.target_port) - raise self.CClose(1000, "Target closed") - - cqueue.append(buf) - self.print_traffic("{") - -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. - """ - - buffer_size = 65536 - - def __init__(self, RequestHandlerClass=ProxyRequestHandler, *args, **kwargs): - # Save off proxy specific options - self.target_host = kwargs.pop('target_host', None) - self.target_port = kwargs.pop('target_port', None) - self.wrap_cmd = kwargs.pop('wrap_cmd', None) - self.wrap_mode = kwargs.pop('wrap_mode', None) - self.unix_target = kwargs.pop('unix_target', None) - self.ssl_target = kwargs.pop('ssl_target', None) - self.target_cfg = kwargs.pop('target_cfg', None) - # Last 3 timestamps command was run - self.wrap_times = [0, 0, 0] - - if self.wrap_cmd: - wsdir = os.path.dirname(sys.argv[0]) - rebinder_path = [os.path.join(wsdir, "..", "lib"), - os.path.join(wsdir, "..", "lib", "websockify"), - wsdir] - self.rebinder = None - - for rdir in rebinder_path: - rpath = os.path.join(rdir, "rebind.so") - if os.path.exists(rpath): - self.rebinder = rpath - break - - if not self.rebinder: - 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 - # Find a free high port - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.bind(('', 0)) - self.target_port = sock.getsockname()[1] - sock.close() - - os.environ.update({ - "LD_PRELOAD": self.rebinder, - "REBIND_OLD_PORT": str(kwargs['listen_port']), - "REBIND_NEW_PORT": str(self.target_port)}) - - websocket.WebSocketServer.__init__(self, RequestHandlerClass, *args, **kwargs) - - def run_wrap_cmd(self): - self.msg("Starting '%s'", " ".join(self.wrap_cmd)) - self.wrap_times.append(time.time()) - self.wrap_times.pop(0) - self.cmd = subprocess.Popen( - self.wrap_cmd, env=os.environ, preexec_fn=_subprocess_setup) - self.spawn_message = True - - def started(self): - """ - Called after Websockets server startup (i.e. after daemonize) - """ - # Need to call wrapped command after daemonization so we can - # know when the wrapped command exits - if self.wrap_cmd: - dst_string = "'%s' (port %s)" % (" ".join(self.wrap_cmd), self.target_port) - elif self.unix_target: - dst_string = self.unix_target - 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)" - - self.msg("%s", msg) - - if self.wrap_cmd: - self.run_wrap_cmd() - - def poll(self): - # If we are wrapping a command, check it's status - - if self.wrap_cmd and self.cmd: - ret = self.cmd.poll() - if ret != None: - self.vmsg("Wrapped command exited (or daemon). Returned %s" % ret) - self.cmd = None - - if self.wrap_cmd and self.cmd == None: - # Response to wrapped command being gone - if self.wrap_mode == "ignore": - pass - elif self.wrap_mode == "exit": - sys.exit(ret) - elif self.wrap_mode == "respawn": - now = time.time() - avg = sum(self.wrap_times)/len(self.wrap_times) - if (now - avg) < 10: - # 3 times in the last 10 seconds - if self.spawn_message: - self.warn("Command respawning too fast") - self.spawn_message = False - else: - self.run_wrap_cmd() - - -def _subprocess_setup(): - # Python installs a SIGPIPE handler by default. This is usually not what - # non-Python successfulbprocesses expect. - signal.signal(signal.SIGPIPE, signal.SIG_DFL) - - -def logger_init(): - logger = logging.getLogger(WebSocketProxy.log_prefix) - logger.propagate = False - logger.setLevel(logging.INFO) - h = logging.StreamHandler() - h.setLevel(logging.DEBUG) - h.setFormatter(logging.Formatter("%(message)s")) - logger.addHandler(h) - - -def websockify_init(): - logger_init() - - usage = "\n %prog [options]" - usage += " [source_addr:]source_port [target_addr:target_port]" - usage += "\n %prog [options]" - usage += " [source_addr:]source_port -- WRAP_COMMAND_LINE" - parser = optparse.OptionParser(usage=usage) - parser.add_option("--verbose", "-v", action="store_true", - help="verbose messages") - parser.add_option("--traffic", action="store_true", - help="per frame traffic") - parser.add_option("--record", - help="record sessions to FILE.[session_number]", metavar="FILE") - parser.add_option("--daemon", "-D", - dest="daemon", action="store_true", - help="become a daemon (background process)") - parser.add_option("--run-once", action="store_true", - help="handle a single WebSocket connection and exit") - parser.add_option("--timeout", type=int, default=0, - help="after TIMEOUT seconds exit when not connected") - parser.add_option("--idle-timeout", type=int, default=0, - help="server exits after TIMEOUT seconds if there are no " - "active connections") - parser.add_option("--cert", default="self.pem", - help="SSL certificate file") - parser.add_option("--key", default=None, - help="SSL key file (if separate from cert)") - parser.add_option("--ssl-only", action="store_true", - help="disallow non-encrypted client 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", - help="run webserver on same port. Serve files from DIR.") - parser.add_option("--wrap-mode", default="exit", metavar="MODE", - choices=["exit", "ignore", "respawn"], - help="action to take when the wrapped program exits " - "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") - parser.add_option("--libserver", action="store_true", - help="use Python library SocketServer engine") - (opts, args) = parser.parse_args() - - if opts.verbose: - logging.getLogger(WebSocketProxy.log_prefix).setLevel(logging.DEBUG) - - # Sanity checks - if len(args) < 2 and not (opts.target_cfg or opts.unix_target): - parser.error("Too few arguments") - if sys.argv.count('--'): - opts.wrap_cmd = args[1:] - else: - opts.wrap_cmd = None - if len(args) > 2: - 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): - parser.error("SSL only and %s not found" % opts.cert) - - # Parse host:port and convert ports to numbers - if args[0].count(':') > 0: - opts.listen_host, opts.listen_port = args[0].rsplit(':', 1) - opts.listen_host = opts.listen_host.strip('[]') - else: - opts.listen_host, opts.listen_port = '', args[0] - - try: opts.listen_port = int(opts.listen_port) - except: parser.error("Error parsing listen port") - - if opts.wrap_cmd or opts.unix_target or opts.target_cfg: - opts.target_host = None - opts.target_port = None - else: - if args[1].count(':') > 0: - opts.target_host, opts.target_port = args[1].rsplit(':', 1) - opts.target_host = opts.target_host.strip('[]') - else: - parser.error("Error parsing target") - try: opts.target_port = int(opts.target_port) - except: parser.error("Error parsing target port") - - # Transform to absolute path as daemon may chdir - if opts.target_cfg: - opts.target_cfg = os.path.abspath(opts.target_cfg) - - # Create and start the WebSockets proxy - libserver = opts.libserver - del opts.libserver - if libserver: - # Use standard Python SocketServer framework - server = LibProxyServer(**opts.__dict__) - server.serve_forever() - else: - # Use internal service framework - server = WebSocketProxy(**opts.__dict__) - server.start_server() - - -class LibProxyServer(ForkingMixIn, HTTPServer): - """ - Just like WebSocketProxy, but uses standard Python SocketServer - framework. - """ - - def __init__(self, RequestHandlerClass=ProxyRequestHandler, **kwargs): - # Save off proxy specific options - self.target_host = kwargs.pop('target_host', None) - self.target_port = kwargs.pop('target_port', None) - self.wrap_cmd = kwargs.pop('wrap_cmd', None) - self.wrap_mode = kwargs.pop('wrap_mode', None) - self.unix_target = kwargs.pop('unix_target', None) - self.ssl_target = kwargs.pop('ssl_target', None) - self.target_cfg = kwargs.pop('target_cfg', None) - self.daemon = False - self.target_cfg = None - - # Server configuration - listen_host = kwargs.pop('listen_host', '') - listen_port = kwargs.pop('listen_port', None) - web = kwargs.pop('web', '') - - # Configuration affecting base request handler - self.only_upgrade = not web - self.verbose = kwargs.pop('verbose', False) - record = kwargs.pop('record', '') - if record: - self.record = os.path.abspath(record) - self.run_once = kwargs.pop('run_once', False) - self.handler_id = 0 - - for arg in kwargs.keys(): - print("warning: option %s ignored when using --libserver" % arg) - - if web: - os.chdir(web) - - HTTPServer.__init__(self, (listen_host, listen_port), - RequestHandlerClass) - - - def process_request(self, request, client_address): - """Override process_request to implement a counter""" - self.handler_id += 1 - ForkingMixIn.process_request(self, request, client_address) - - -if __name__ == '__main__': - websockify_init() |