From f8fe86668c8099ffd7899299683347c5e9c36a37 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Thu, 26 Apr 2012 09:38:42 -0700 Subject: [PATCH 1/7] Re-organize code to allow for imports --- websockify.py | 1 - websockify/__init__.py | 0 websockify => websockify/proxy.py | 0 websocket.py => websockify/websocket.py | 0 websockify/websockify | 1 + websockify/websockify.py | 1 + 6 files changed, 2 insertions(+), 1 deletion(-) delete mode 120000 websockify.py create mode 100644 websockify/__init__.py rename websockify => websockify/proxy.py (100%) rename websocket.py => websockify/websocket.py (100%) create mode 120000 websockify/websockify create mode 120000 websockify/websockify.py diff --git a/websockify.py b/websockify.py deleted file mode 120000 index 05b5af4..0000000 --- a/websockify.py +++ /dev/null @@ -1 +0,0 @@ -websockify \ No newline at end of file diff --git a/websockify/__init__.py b/websockify/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/websockify b/websockify/proxy.py similarity index 100% rename from websockify rename to websockify/proxy.py diff --git a/websocket.py b/websockify/websocket.py similarity index 100% rename from websocket.py rename to websockify/websocket.py diff --git a/websockify/websockify b/websockify/websockify new file mode 120000 index 0000000..799385c --- /dev/null +++ b/websockify/websockify @@ -0,0 +1 @@ +proxy.py \ No newline at end of file diff --git a/websockify/websockify.py b/websockify/websockify.py new file mode 120000 index 0000000..799385c --- /dev/null +++ b/websockify/websockify.py @@ -0,0 +1 @@ +proxy.py \ No newline at end of file From 7fa86a08d3fd47299aa13ad23f04a74382c7a5cc Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 May 2012 14:19:05 -0700 Subject: [PATCH 2/7] Some more re-org --- README.md | 6 +-- bin/websockify | 88 ++++++++++++++++++++++++++++++++++++++++ websockify/proxy.py | 71 -------------------------------- websockify/websockify | 1 - websockify/websockify.py | 1 - 5 files changed, 91 insertions(+), 76 deletions(-) create mode 100755 bin/websockify mode change 100755 => 100644 websockify/proxy.py delete mode 120000 websockify/websockify delete mode 120000 websockify/websockify.py diff --git a/README.md b/README.md index 48c790a..70ceb8a 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ new (moved) port of the program. The program wrap mode is invoked by replacing the target with `--` followed by the program command line to wrap. - `./websockify 2023 -- PROGRAM ARGS` + `bin/websockify 2023 -- PROGRAM ARGS` The `--wrap-mode` option can be used to indicate what action to take when the wrapped program exits or daemonizes. @@ -119,13 +119,13 @@ Here is an example of using websockify to wrap the vncserver command (which backgrounds itself) for use with [noVNC](https://github.com/kanaka/noVNC): - `./websockify 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1` + `bin/websockify 5901 --wrap-mode=ignore -- vncserver -geometry 1024x768 :1` Here is an example of wrapping telnetd (from krb5-telnetd).telnetd exits after the connection closes so the wrap mode is set to respawn the command: - `sudo ./websockify 2023 --wrap-mode=respawn -- telnetd -debug 2023` + `sudo bin/websockify 2023 --wrap-mode=respawn -- telnetd -debug 2023` The `wstelnet.html` page demonstrates a simple WebSockets based telnet client. diff --git a/bin/websockify b/bin/websockify new file mode 100755 index 0000000..9c8e4fa --- /dev/null +++ b/bin/websockify @@ -0,0 +1,88 @@ +#!/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 optparse, os, sys +from websockify.proxy import WebSocketProxy + + +def websockify_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 and 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("--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 connections") + 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") + (opts, args) = parser.parse_args() + + # Sanity checks + if len(args) < 2: + 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 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) + 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: + opts.target_host = None + opts.target_port = None + else: + if args[1].count(':') > 0: + opts.target_host, opts.target_port = args[1].rsplit(':', 1) + else: + parser.error("Error parsing target") + try: opts.target_port = int(opts.target_port) + except: parser.error("Error parsing target port") + + # Create and start the WebSockets proxy + server = WebSocketProxy(**opts.__dict__) + server.start_server() + +if __name__ == '__main__': + websockify_init() diff --git a/websockify/proxy.py b/websockify/proxy.py old mode 100755 new mode 100644 index 550dff7..7a46cec --- a/websockify/proxy.py +++ b/websockify/proxy.py @@ -212,74 +212,3 @@ Traffic Legend: if closed: # TODO: What about blocking on client socket? raise self.CClose(closed['code'], closed['reason']) - -def websockify_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 and 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("--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 connections") - 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") - (opts, args) = parser.parse_args() - - # Sanity checks - if len(args) < 2: - 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 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) - 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: - opts.target_host = None - opts.target_port = None - else: - if args[1].count(':') > 0: - opts.target_host, opts.target_port = args[1].rsplit(':', 1) - else: - parser.error("Error parsing target") - try: opts.target_port = int(opts.target_port) - except: parser.error("Error parsing target port") - - # Create and start the WebSockets proxy - server = WebSocketProxy(**opts.__dict__) - server.start_server() - -if __name__ == '__main__': - websockify_init() diff --git a/websockify/websockify b/websockify/websockify deleted file mode 120000 index 799385c..0000000 --- a/websockify/websockify +++ /dev/null @@ -1 +0,0 @@ -proxy.py \ No newline at end of file diff --git a/websockify/websockify.py b/websockify/websockify.py deleted file mode 120000 index 799385c..0000000 --- a/websockify/websockify.py +++ /dev/null @@ -1 +0,0 @@ -proxy.py \ No newline at end of file From ff700cd628a97fb0bdd92907ea52c281f4b052d7 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 May 2012 14:24:25 -0700 Subject: [PATCH 3/7] Move html code into www dir --- tests/include | 2 +- {include => www/include}/VT100.js | 0 {include => www/include}/base64.js | 0 {include => www/include}/keysym.js | 0 {include => www/include}/util.js | 0 {include => www/include}/web-socket-js/README.txt | 0 .../include}/web-socket-js/WebSocketMain.swf | Bin {include => www/include}/web-socket-js/swfobject.js | 0 .../include}/web-socket-js/web_socket.js | 0 {include => www/include}/websock.js | 0 {include => www/include}/webutil.js | 0 {include => www/include}/wsirc.js | 0 {include => www/include}/wstelnet.js | 0 wsirc.html => www/wsirc.html | 0 wstelnet.html => www/wstelnet.html | 0 15 files changed, 1 insertion(+), 1 deletion(-) rename {include => www/include}/VT100.js (100%) rename {include => www/include}/base64.js (100%) rename {include => www/include}/keysym.js (100%) rename {include => www/include}/util.js (100%) rename {include => www/include}/web-socket-js/README.txt (100%) rename {include => www/include}/web-socket-js/WebSocketMain.swf (100%) rename {include => www/include}/web-socket-js/swfobject.js (100%) rename {include => www/include}/web-socket-js/web_socket.js (100%) rename {include => www/include}/websock.js (100%) rename {include => www/include}/webutil.js (100%) rename {include => www/include}/wsirc.js (100%) rename {include => www/include}/wstelnet.js (100%) rename wsirc.html => www/wsirc.html (100%) rename wstelnet.html => www/wstelnet.html (100%) diff --git a/tests/include b/tests/include index f5030fe..7c7a3f8 120000 --- a/tests/include +++ b/tests/include @@ -1 +1 @@ -../include \ No newline at end of file +../www/include \ No newline at end of file diff --git a/include/VT100.js b/www/include/VT100.js similarity index 100% rename from include/VT100.js rename to www/include/VT100.js diff --git a/include/base64.js b/www/include/base64.js similarity index 100% rename from include/base64.js rename to www/include/base64.js diff --git a/include/keysym.js b/www/include/keysym.js similarity index 100% rename from include/keysym.js rename to www/include/keysym.js diff --git a/include/util.js b/www/include/util.js similarity index 100% rename from include/util.js rename to www/include/util.js diff --git a/include/web-socket-js/README.txt b/www/include/web-socket-js/README.txt similarity index 100% rename from include/web-socket-js/README.txt rename to www/include/web-socket-js/README.txt diff --git a/include/web-socket-js/WebSocketMain.swf b/www/include/web-socket-js/WebSocketMain.swf similarity index 100% rename from include/web-socket-js/WebSocketMain.swf rename to www/include/web-socket-js/WebSocketMain.swf diff --git a/include/web-socket-js/swfobject.js b/www/include/web-socket-js/swfobject.js similarity index 100% rename from include/web-socket-js/swfobject.js rename to www/include/web-socket-js/swfobject.js diff --git a/include/web-socket-js/web_socket.js b/www/include/web-socket-js/web_socket.js similarity index 100% rename from include/web-socket-js/web_socket.js rename to www/include/web-socket-js/web_socket.js diff --git a/include/websock.js b/www/include/websock.js similarity index 100% rename from include/websock.js rename to www/include/websock.js diff --git a/include/webutil.js b/www/include/webutil.js similarity index 100% rename from include/webutil.js rename to www/include/webutil.js diff --git a/include/wsirc.js b/www/include/wsirc.js similarity index 100% rename from include/wsirc.js rename to www/include/wsirc.js diff --git a/include/wstelnet.js b/www/include/wstelnet.js similarity index 100% rename from include/wstelnet.js rename to www/include/wstelnet.js diff --git a/wsirc.html b/www/wsirc.html similarity index 100% rename from wsirc.html rename to www/wsirc.html diff --git a/wstelnet.html b/www/wstelnet.html similarity index 100% rename from wstelnet.html rename to www/wstelnet.html From f66b93255fd6539eb2313a4289139d30ead5d97e Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 May 2012 14:35:03 -0700 Subject: [PATCH 4/7] Move rebind to a subdirectory --- Makefile => rebind/Makefile | 0 rebind => rebind/rebind | 0 rebind.c => rebind/rebind.c | 0 websockify/proxy.py | 3 ++- 4 files changed, 2 insertions(+), 1 deletion(-) rename Makefile => rebind/Makefile (100%) rename rebind => rebind/rebind (100%) rename rebind.c => rebind/rebind.c (100%) diff --git a/Makefile b/rebind/Makefile similarity index 100% rename from Makefile rename to rebind/Makefile diff --git a/rebind b/rebind/rebind similarity index 100% rename from rebind rename to rebind/rebind diff --git a/rebind.c b/rebind/rebind.c similarity index 100% rename from rebind.c rename to rebind/rebind.c diff --git a/websockify/proxy.py b/websockify/proxy.py index 7a46cec..cd83709 100644 --- a/websockify/proxy.py +++ b/websockify/proxy.py @@ -47,11 +47,12 @@ Traffic Legend: self.wrap_times = [0, 0, 0] if self.wrap_cmd: - rebinder_path = ['./', os.path.dirname(sys.argv[0])] + rebinder_path = ['./', os.path.dirname(sys.argv[0]), 'rebind/'] self.rebinder = None for rdir in rebinder_path: rpath = os.path.join(rdir, "rebind.so") + print rpath if os.path.exists(rpath): self.rebinder = rpath break From 96250f8bfccf46592e0e23b6335e6388256305be Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 May 2012 14:38:25 -0700 Subject: [PATCH 5/7] Fix tests --- tests/echo.py | 2 +- tests/load.py | 2 +- tests/utf8-list.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/echo.py b/tests/echo.py index 878c31a..dd35810 100755 --- a/tests/echo.py +++ b/tests/echo.py @@ -12,7 +12,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates import os, sys, select, optparse sys.path.insert(0,os.path.dirname(__file__) + "/../") -from websocket import WebSocketServer +from websockify.websocket import WebSocketServer class WebSocketEcho(WebSocketServer): """ diff --git a/tests/load.py b/tests/load.py index 0501f7d..b298703 100755 --- a/tests/load.py +++ b/tests/load.py @@ -8,7 +8,7 @@ given a sequence number. Any errors are reported and counted. import sys, os, select, random, time, optparse sys.path.insert(0,os.path.dirname(__file__) + "/../") -from websocket import WebSocketServer +from websockify.websocket import WebSocketServer class WebSocketLoad(WebSocketServer): diff --git a/tests/utf8-list.py b/tests/utf8-list.py index 5a36da0..1ae1238 100755 --- a/tests/utf8-list.py +++ b/tests/utf8-list.py @@ -7,7 +7,7 @@ import sys, os, socket, ssl, time, traceback from select import select sys.path.insert(0,os.path.dirname(__file__) + "/../") -from websocket import WebSocketServer +from websockify.websocket import WebSocketServer if __name__ == '__main__': print "val: hixie | hybi_base64 | hybi_binary" From 841bb2f2ba5626c01a2304f0910f9e3e6920515b Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 May 2012 15:15:35 -0700 Subject: [PATCH 6/7] add ability to specify rebind path * Also update setup.py for proper bin/websockify path --- bin/websockify | 2 ++ setup.py | 6 +----- websockify/proxy.py | 11 +++++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/bin/websockify b/bin/websockify index 9c8e4fa..0026882 100755 --- a/bin/websockify +++ b/bin/websockify @@ -37,6 +37,8 @@ def websockify_init(): help="SSL certificate file") parser.add_option("--key", default=None, help="SSL key file (if separate from cert)") + parser.add_option("--rebind_path", default="./", + help="Directory containing rebind.so") parser.add_option("--ssl-only", action="store_true", help="disallow non-encrypted connections") parser.add_option("--web", default=None, metavar="DIR", diff --git a/setup.py b/setup.py index 095c653..43a0f0b 100644 --- a/setup.py +++ b/setup.py @@ -22,9 +22,5 @@ setup(name=name, include_package_data=True, install_requires=['numpy'], zip_safe=False, - entry_points={ - 'console_scripts': [ - 'websockify = websockify:websockify_init', - ] - }, + scripts=['bin/websockify'], ) diff --git a/websockify/proxy.py b/websockify/proxy.py index cd83709..5da4efb 100644 --- a/websockify/proxy.py +++ b/websockify/proxy.py @@ -43,16 +43,19 @@ Traffic Legend: self.target_port = kwargs.pop('target_port') self.wrap_cmd = kwargs.pop('wrap_cmd') self.wrap_mode = kwargs.pop('wrap_mode') + self.rebind_path = kwargs.pop('rebind_path') # Last 3 timestamps command was run self.wrap_times = [0, 0, 0] if self.wrap_cmd: - rebinder_path = ['./', os.path.dirname(sys.argv[0]), 'rebind/'] + rebinder_path = [self.rebind_path, + self.rebind_path + '/rebind.so', + './rebind.so', + os.path.dirname(sys.argv[0]) + 'rebind.so', + 'rebind/rebind.so'] self.rebinder = None - for rdir in rebinder_path: - rpath = os.path.join(rdir, "rebind.so") - print rpath + for rpath in rebinder_path: if os.path.exists(rpath): self.rebinder = rpath break From 3cdebe788d65cf132a6acf78a4f9c9de01569ef8 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 1 May 2012 15:22:04 -0700 Subject: [PATCH 7/7] Add additional path to rebind search , update docs --- README.md | 10 ++++++++-- websockify/proxy.py | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 70ceb8a..006a0c8 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ read binary data off of the receive queue. The Websock API is documented on the [websock.js API wiki page](https://github.com/kanaka/websockify/wiki/websock.js) See the "Wrap a Program" section below for an example of using Websock -and websockify as a browser telnet client (`wstelnet.html`). +and websockify as a browser telnet client (`www/wstelnet.html`). ### Additional websockify features @@ -107,6 +107,12 @@ port is moved to a new localhost/loopback free high port. websockify then proxies WebSockets traffic directed to the original port to the new (moved) port of the program. +You can build rebind.so like so: + + cd rebind + make + cd .. + The program wrap mode is invoked by replacing the target with `--` followed by the program command line to wrap. @@ -127,7 +133,7 @@ the command: `sudo bin/websockify 2023 --wrap-mode=respawn -- telnetd -debug 2023` -The `wstelnet.html` page demonstrates a simple WebSockets based telnet +The `www/wstelnet.html` page demonstrates a simple WebSockets based telnet client. diff --git a/websockify/proxy.py b/websockify/proxy.py index 5da4efb..56a0077 100644 --- a/websockify/proxy.py +++ b/websockify/proxy.py @@ -52,7 +52,8 @@ Traffic Legend: self.rebind_path + '/rebind.so', './rebind.so', os.path.dirname(sys.argv[0]) + 'rebind.so', - 'rebind/rebind.so'] + 'rebind/rebind.so', + '../rebind/rebind.so'] self.rebinder = None for rpath in rebinder_path: