diff --git a/tests/wsecho.html b/tests/wsecho.html
deleted file mode 120000
index 28c636a1..00000000
--- a/tests/wsecho.html
+++ /dev/null
@@ -1 +0,0 @@
-../utils/wsecho.html
\ No newline at end of file
diff --git a/tests/wsencoding.html b/tests/wsencoding.html
deleted file mode 100644
index 846645ea..00000000
--- a/tests/wsencoding.html
+++ /dev/null
@@ -1,151 +0,0 @@
-
-
-
WebSockets Test
-
-
-
- Host:
- Port:
- Encrypt:
-
-
-
- Messages:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/wsencoding.py b/tests/wsencoding.py
deleted file mode 100755
index c44b934e..00000000
--- a/tests/wsencoding.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/python
-
-'''
-WebSocket server-side load test program. Sends and receives traffic
-that has a random payload (length and content) that is checksummed and
-given a sequence number. Any errors are reported and counted.
-'''
-
-import sys, os, socket, ssl, time, traceback
-import random, time
-from base64 import b64encode, b64decode
-from codecs import utf_8_encode, utf_8_decode
-from select import select
-
-sys.path.insert(0,os.path.dirname(__file__) + "/../utils/")
-from websocket import *
-
-buffer_size = 65536
-recv_cnt = send_cnt = 0
-
-
-def check(buf):
-
- if buf[0] != '\x00' or buf[-1] != '\xff':
- raise Exception("Invalid WS packet")
-
- for decoded in decode(buf):
- nums = [ord(c) for c in decoded]
- print "Received nums: ", nums
-
- return
-
-
-def responder(client):
- cpartial = ""
- socks = [client]
- sent = False
- received = False
-
- while True:
- ins, outs, excepts = select(socks, socks, socks, 1)
- if excepts: raise Exception("Socket exception")
-
- if client in ins:
- buf = client.recv(buffer_size)
- if len(buf) == 0: raise Exception("Client closed")
- received = True
- #print "Client recv: %s (%d)" % (repr(buf[1:-1]), len(buf))
- if buf[-1] == '\xff':
- if cpartial:
- err = check(cpartial + buf)
- cpartial = ""
- else:
- err = check(buf)
- if err:
- print err
- else:
- print "received partitial"
- cpartial = cpartial + buf
-
- if received and not sent and client in outs:
- sent = True
- #nums = "".join([unichr(c) for c in range(0,256)])
- #nums = "".join([chr(c) for c in range(1,128)])
- #nums = nums + chr(194) + chr(128) + chr(194) + chr(129)
- #nums = "".join([chr(c) for c in range(0,256)])
- nums = "\x81\xff"
- nums = nums + "".join([chr(c) for c in range(0,256,4)])
- nums = nums + "\x00\x40\x41\xff\x81"
-# print nums
- client.send(encode(nums))
-# client.send("\x00" + nums + "\xff")
-# print "Sent characters 0-255"
-# #print "Client send: %s (%d)" % (repr(nums), len(nums))
-
-if __name__ == '__main__':
- try:
- if len(sys.argv) < 2: raise
- listen_port = int(sys.argv[1])
- except:
- print "Usage: "
- sys.exit(1)
-
- settings['listen_port'] = listen_port
- settings['daemon'] = False
- settings['handler'] = responder
- start_server()
diff --git a/tests/wstest.html b/tests/wstest.html
deleted file mode 120000
index 13d6ff0a..00000000
--- a/tests/wstest.html
+++ /dev/null
@@ -1 +0,0 @@
-../utils/wstest.html
\ No newline at end of file
diff --git a/tests/wstest.py b/tests/wstest.py
deleted file mode 120000
index 2c5b2b30..00000000
--- a/tests/wstest.py
+++ /dev/null
@@ -1 +0,0 @@
-../utils/wstest.py
\ No newline at end of file
diff --git a/utils/Makefile b/utils/Makefile
index 008d45c2..7dc1bc4f 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -1,25 +1,11 @@
-TARGETS=wsproxy wswrapper.so rebind.so
+TARGETS=rebind.so
CFLAGS += -fPIC
all: $(TARGETS)
-wsproxy: wsproxy.o websocket.o md5.o
- $(CC) $(LDFLAGS) $^ -lssl -lcrypto -lresolv -o $@
-
-wswrapper.o: wswrapper.h
-wswrapper.so: wswrapper.o md5.o
- $(CC) $(LDFLAGS) $^ -shared -fPIC -ldl -lresolv -o $@
-
rebind.so: rebind.o
$(CC) $(LDFLAGS) $^ -shared -fPIC -ldl -o $@
-websocket.o: websocket.c websocket.h md5.h
-wsproxy.o: wsproxy.c websocket.h
-wswrapper.o: wswrapper.c
- $(CC) -c $(CFLAGS) -o $@ $*.c
-md5.o: md5.c md5.h
- $(CC) -c $(CFLAGS) -o $@ $*.c -DHAVE_MEMCPY -DSTDC_HEADERS
-
clean:
- rm -f wsproxy wswrapper.so *.o
+ rm -f rebind.o rebind.so
diff --git a/utils/README.md b/utils/README.md
index 7aeebe68..0abbd0d1 100644
--- a/utils/README.md
+++ b/utils/README.md
@@ -1,163 +1,11 @@
## WebSockets Proxy
+wsproxy has become [websockify](https://github.com/kanaka/websockify).
+A copy of the python version of websockify (named wsproxy.py) is kept
+here for ease of use. The other versions of websockify (C, Node.js)
+and the associated test programs have been moved to
+[websockify](https://github.com/kanaka/websockify).
-### wsproxy
-
-At the most basic level, wsproxy just translates WebSockets traffic
-to normal socket traffic. wsproxy accepts the WebSockets handshake,
-parses it, and then begins forwarding traffic between the client and
-the target in both directions. WebSockets payload data is UTF-8
-encoded so in order to transport binary data it must use an encoding
-that can be encapsulated within UTF-8. wsproxy uses base64 to encode
-all traffic to and from the client. Also, WebSockets traffic starts
-with '\0' (0) and ends with '\xff' (255). Some buffering is done in
-case the data from the client is not a full WebSockets frame (i.e.
-does not end in 255).
-
-
-#### Additional wsproxy features
-
-These are not necessary for the basic operation.
-
-* Daemonizing: When the `-D` option is specified, wsproxy runs
- in the background as a daemon process.
-
-* SSL (the wss:// WebSockets URI): This is detected automatically by
- wsproxy by sniffing the first byte sent from the client and then
- wrapping the socket if the data starts with '\x16' or '\x80'
- (indicating SSL).
-
-* Flash security policy: wsproxy detects flash security policy
- requests (again by sniffing the first packet) and answers with an
- appropriate flash security policy response (and then closes the
- port). This means no separate flash security policy server is needed
- for supporting the flash WebSockets fallback emulator.
-
-* Session recording: This feature that allows recording of the traffic
- sent and received from the client to a file using the `--record`
- option.
-
-* Mini-webserver: wsproxy can detect and respond to normal web
- requests on the same port as the WebSockets proxy and Flash security
- policy. This functionality is activate with the `--web DIR` option
- where DIR is the root of the web directory to serve.
-
-* Wrap a program: see the "Wrap a Program" section below.
-
-
-#### Implementations of wsproxy
-
-There are three implementations of wsproxy: python, C, and Node
-(node.js). wswrapper is only implemented in C.
-
-Here is the feature support matrix for the the wsproxy
-implementations:
-
-
-
-
Program
-
Language
-
Multiprocess
-
Daemonize
-
SSL/wss
-
Flash Policy Server
-
Session Record
-
Web Server
-
Program Wrap
-
-
wsproxy.py
-
python
-
yes
-
yes
-
yes 1
-
yes
-
yes
-
yes
-
yes
-
-
wsproxy
-
C
-
yes
-
yes
-
yes
-
yes
-
no
-
no
-
no
-
-
-
wsproxy.js
-
Node (node.js)
-
yes
-
no
-
no
-
no
-
no
-
no
-
no
-
-
-
-
-* Note 1: to use SSL/wss with python 2.5 or older, see the following
- section on *Building the Python ssl module*.
-
-
-### Wrap a Program
-
-In addition to proxying from a source address to a target address
-(which may be on a different system), wsproxy has the ability to
-launch a program on the local system and proxy WebSockets traffic to
-a normal TCP port owned/bound by the program.
-
-The is accomplished with a small LD_PRELOAD library (`rebind.so`)
-which intercepts bind() system calls by the program. The specified
-port is moved to a new localhost/loopback free high port. wsproxy
-then proxies WebSockets traffic directed to the original port to the
-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.
-
- `./utils/wsproxy.py 2023 -- PROGRAM ARGS`
-
-The `--wrap-mode` option can be used to indicate what action to take
-when the wrapped program exits or daemonizes.
-
-Here is an example of using wsproxy to wrap the vncserver command
-(which backgrounds itself):
-
- `./utils/wsproxy.py 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 ./utils/wsproxy.py 2023 --wrap-mode=respawn -- telnetd -debug 2023`
-
-The `utils/wstelnet.html` page demonstrates a simple WebSockets based
-telnet client.
-
-
-### Building the Python ssl module (for python 2.5 and older)
-
-* Install the build dependencies. On Ubuntu use this command:
-
- `sudo aptitude install python-dev bluetooth-dev`
-
-* Download, build the ssl module and symlink to it:
-
- `cd noVNC/utils`
-
- `wget http://pypi.python.org/packages/source/s/ssl/ssl-1.15.tar.gz`
-
- `tar xvzf ssl-1.15.tar.gz`
-
- `cd ssl-1.15`
-
- `make`
-
- `cd ../`
-
- `ln -sf ssl-1.15/build/lib.linux-*/ssl ssl`
+For more detailed description and usage information please refer to
+the [websockify README](https://github.com/kanaka/websockify/blob/master/README.md).
diff --git a/utils/VT100.js b/utils/VT100.js
deleted file mode 100644
index 6a325e13..00000000
--- a/utils/VT100.js
+++ /dev/null
@@ -1,919 +0,0 @@
-// VT100.js -- a text terminal emulator in JavaScript with a ncurses-like
-// interface and a POSIX-like interface. (The POSIX-like calls are
-// implemented on top of the ncurses-like calls, not the other way round.)
-//
-// Released under the GNU LGPL v2.1, by Frank Bi
-//
-// 2007-08-12 - refresh():
-// - factor out colour code to html_colours_()
-// - fix handling of A_REVERSE | A_DIM
-// - simplify initial output code
-// - fix underlining colour
-// - fix attron() not to turn off attributes
-// - decouple A_STANDOUT and A_BOLD
-// 2007-08-11 - getch() now calls refresh()
-// 2007-08-06 - Safari compat fix -- turn '\r' into '\n' for onkeypress
-// 2007-08-05 - Opera compat fixes for onkeypress
-// 2007-07-30 - IE compat fixes:
-// - change key handling code
-// - add ... so that 1st and last lines align
-// 2007-07-28 - change wrapping behaviour -- writing at the right edge no
-// longer causes the cursor to immediately wrap around
-// - add ... to output to make A_STANDOUT stand out more
-// - add handling of backspace, tab, return keys
-// - fix doc. of VT100() constructor
-// - change from GPL to LGPL
-// 2007-07-09 - initial release
-//
-// class VT100
-// A_NORMAL, A_UNDERLINE, A_REVERSE, A_BLINK, A_DIM, A_BOLD, A_STANDOUT
-// =class constants=
-// Attribute constants.
-// VT100(wd, ht, scr_id) =constructor=
-// Creates a virtual terminal with width `wd', and
-// height `ht'. The terminal will be displayed between
-//
...
tags which have element ID `scr_id'.
-// addch(ch [, attr])
-// Writes out the character `ch'. If `attr' is given,
-// it specifies the attributes for the character,
-// otherwise the current attributes are used.
-// addstr(stuff) Writes out the string `stuff' using the current
-// attributes.
-// attroff(mode) Turns off any current options given in mode.
-// attron(mode) Turns on any options given in mode.
-// attrset(mode) Sets the current options to mode.
-// bkgdset(attr) Sets the background attributes to attr.
-// clear() Clears the terminal using the background attributes,
-// and homes the cursor.
-// clrtobol() Clears the portion of the terminal from the cursor
-// to the bottom.
-// clrtoeol() Clears the portion of the current line after the
-// cursor.
-// curs_set(vis [, grab])
-// If `vis' is 0, makes the cursor invisible; otherwise
-// make it visible. If `grab' is given and true, starts
-// capturing keyboard events (for `getch()'); if given
-// and false, stops capturing events.
-// echo() Causes key strokes to be automatically echoed on the
-// terminal.
-// erase() Same as `clear()'.
-// getch(isr) Arranges to call `isr' when a key stroke is
-// received. The received character and the terminal
-// object are passed as arguments to `isr'.
-// getmaxyx() Returns an associative array with the maximum row
-// (`y') and column (`x') numbers for the terminal.
-// getyx() Returns an associative array with the current row
-// (`y') and column (`x') of the cursor.
-// move(r, c) Moves the cursor to row `r', column `c'.
-// noecho() Stops automatically echoing key strokes.
-// refresh() Updates the display.
-// scroll() Scrolls the terminal up one line.
-// standend() Same as `attrset(VT100.A_NORMAL)'.
-// standout() Same as `attron(VT100.A_STANDOUT)'.
-// write(stuff) Writes `stuff' to the terminal and immediately
-// updates the display; (some) escape sequences are
-// interpreted and acted on.
-
-// constructor
-function VT100(wd, ht, scr_id)
-{
- var r;
- var c;
- var scr = document.getElementById(scr_id);
- this.wd_ = wd;
- this.ht_ = ht;
- this.scrolled_ = 0;
- this.bkgd_ = {
- mode: VT100.A_NORMAL,
- fg: VT100.COLOR_WHITE,
- bg: VT100.COLOR_BLACK
- };
- this.c_attr_ = {
- mode: VT100.A_NORMAL,
- fg: VT100.COLOR_WHITE,
- bg: VT100.COLOR_BLACK
- };
- this.text_ = new Array(ht);
- this.attr_ = new Array(ht);
- for (r = 0; r < ht; ++r) {
- this.text_[r] = new Array(wd);
- this.attr_[r] = new Array(wd);
- }
- this.scr_ = scr;
- this.cursor_vis_ = true;
- this.grab_events_ = false;
- this.getch_isr_ = undefined;
- this.key_buf_ = [];
- this.echo_ = true;
- this.esc_state_ = 0;
- // Internal debug setting.
- this.debug_ = 0;
- this.clear();
- this.refresh();
-}
-
-// public constants -- colours and colour pairs
-VT100.COLOR_BLACK = 0;
-VT100.COLOR_BLUE = 1;
-VT100.COLOR_GREEN = 2;
-VT100.COLOR_CYAN = 3;
-VT100.COLOR_RED = 4;
-VT100.COLOR_MAGENTA = 5;
-VT100.COLOR_YELLOW = 6;
-VT100.COLOR_WHITE = 7;
-VT100.COLOR_PAIRS = 256;
-VT100.COLORS = 8;
-// public constants -- attributes
-VT100.A_NORMAL = 0;
-VT100.A_UNDERLINE = 1;
-VT100.A_REVERSE = 2;
-VT100.A_BLINK = 4;
-VT100.A_DIM = 8;
-VT100.A_BOLD = 16;
-VT100.A_STANDOUT = 32;
-VT100.A_PROTECT = VT100.A_INVIS = 0; // ?
-// other public constants
-VT100.TABSIZE = 8;
-// private constants
-VT100.ATTR_FLAGS_ = VT100.A_UNDERLINE | VT100.A_REVERSE | VT100.A_BLINK |
- VT100.A_DIM | VT100.A_BOLD | VT100.A_STANDOUT |
- VT100.A_PROTECT | VT100.A_INVIS;
-VT100.COLOR_SHIFT_ = 6;
-VT100.browser_ie_ = (navigator.appName.indexOf("Microsoft") != -1);
-VT100.browser_opera_ = (navigator.appName.indexOf("Opera") != -1);
-// class variables
-VT100.the_vt_ = undefined;
-
-// class methods
-
-// this is actually an event handler
-VT100.handle_onkeypress_ = function VT100_handle_onkeypress(event)
-{
- var vt = VT100.the_vt_, ch;
- if (vt === undefined)
- return true;
- if (VT100.browser_ie_ || VT100.browser_opera_) {
- ch = event.keyCode;
- if (ch == 13)
- ch = 10;
- else if (ch > 255 || (ch < 32 && ch != 8))
- return true;
- ch = String.fromCharCode(ch);
- } else {
- ch = event.charCode;
- //dump("ch: " + ch + "\n");
- //dump("ctrl?: " + event.ctrlKey + "\n");
- vt.debug("onkeypress:: keyCode: " + event.keyCode + ", ch: " + event.charCode);
- if (ch) {
- if (ch > 255)
- return true;
- if (event.ctrlKey && event.shiftKey) {
- // Don't send the copy/paste commands.
- var charStr = String.fromCharCode(ch);
- if (charStr == 'C' || charStr == 'V') {
- return false;
- }
- }
- if (event.ctrlKey) {
- ch = String.fromCharCode(ch - 96);
- } else {
- ch = String.fromCharCode(ch);
- if (ch == '\r')
- ch = '\n';
- }
- } else {
- switch (event.keyCode) {
- case event.DOM_VK_BACK_SPACE:
- ch = '\b';
- break;
- case event.DOM_VK_TAB:
- ch = '\t';
- // Stop tab from moving to another element.
- event.preventDefault();
- break;
- case event.DOM_VK_RETURN:
- case event.DOM_VK_ENTER:
- ch = '\n';
- break;
- case event.DOM_VK_UP:
- ch = '\x1b[A';
- break;
- case event.DOM_VK_DOWN:
- ch = '\x1b[B';
- break;
- case event.DOM_VK_RIGHT:
- ch = '\x1b[C';
- break;
- case event.DOM_VK_LEFT:
- ch = '\x1b[D';
- break;
- case event.DOM_VK_DELETE:
- ch = '\x1b[3~';
- break;
- case event.DOM_VK_HOME:
- ch = '\x1b[H';
- break;
- case event.DOM_VK_ESCAPE:
- ch = '\x1bc';
- break;
- default:
- return true;
- }
- }
- }
- vt.key_buf_.push(ch);
- setTimeout(VT100.go_getch_, 0);
- return false;
-}
-
-// this is actually an event handler
-VT100.handle_onkeydown_ = function VT100_handle_onkeydown()
-{
- var vt = VT100.the_vt_, ch;
- switch (event.keyCode) {
- case 8:
- ch = '\b'; break;
- default:
- return true;
- }
- vt.key_buf_.push(ch);
- setTimeout(VT100.go_getch_, 0);
- return false;
-}
-
-VT100.go_getch_ = function VT100_go_getch()
-{
- var vt = VT100.the_vt_;
- if (vt === undefined)
- return;
- var isr = vt.getch_isr_;
- vt.getch_isr_ = undefined;
- if (isr === undefined)
- return;
- var ch = vt.key_buf_.shift();
- if (ch === undefined) {
- vt.getch_isr_ = isr;
- return;
- }
- if (vt.echo_)
- vt.addch(ch);
- isr(ch, vt);
-}
-
-// object methods
-
-VT100.prototype.may_scroll_ = function()
-{
- var ht = this.ht_, cr = this.row_;
- while (cr >= ht) {
- this.scroll();
- --cr;
- }
- this.row_ = cr;
-}
-
-VT100.prototype.html_colours_ = function(attr)
-{
- var fg, bg, co0, co1;
- fg = attr.fg;
- bg = attr.bg;
- switch (attr.mode & (VT100.A_REVERSE | VT100.A_DIM | VT100.A_BOLD)) {
- case 0:
- case VT100.A_DIM | VT100.A_BOLD:
- co0 = '00'; co1 = 'c0';
- break;
- case VT100.A_BOLD:
- co0 = '00'; co1 = 'ff';
- break;
- case VT100.A_DIM:
- if (fg == VT100.COLOR_BLACK)
- co0 = '40';
- else
- co0 = '00';
- co1 = '40';
- break;
- case VT100.A_REVERSE:
- case VT100.A_REVERSE | VT100.A_DIM | VT100.A_BOLD:
- co0 = 'c0'; co1 = '40';
- break;
- case VT100.A_REVERSE | VT100.A_BOLD:
- co0 = 'c0'; co1 = '00';
- break;
- default:
- if (fg == VT100.COLOR_BLACK)
- co0 = '80';
- else
- co0 = 'c0';
- co1 = 'c0';
- }
- return {
- f: '#' + (fg & 4 ? co1 : co0) +
- (fg & 2 ? co1 : co0) +
- (fg & 1 ? co1 : co0),
- b: '#' + (bg & 4 ? co1 : co0) +
- (bg & 2 ? co1 : co0) +
- (bg & 1 ? co1 : co0)
- };
-}
-
-VT100.prototype.addch = function(ch, attr)
-{
- var cc = this.col_;
- this.debug("addch:: ch: " + ch + ", attr: " + attr);
- switch (ch) {
- case '\b':
- if (cc != 0)
- --cc;
- break;
- case '\n':
- ++this.row_;
- cc = 0;
- this.clrtoeol();
- this.may_scroll_();
- break;
- case '\r':
- this.may_scroll_();
- cc = 0;
- break;
- case '\t':
- this.may_scroll_();
- cc += VT100.TABSIZE - cc % VT100.TABSIZE;
- if (cc >= this.wd_) {
- ++this.row_;
- cc -= this.wd_;
- }
- break;
- default:
- if (attr === undefined)
- attr = this._cloneAttr(this.c_attr_);
- if (cc >= this.wd_) {
- ++this.row_;
- cc = 0;
- }
- this.may_scroll_();
- this.text_[this.row_][cc] = ch;
- this.attr_[this.row_][cc] = attr;
- ++cc;
- }
- this.col_ = cc;
-}
-
-VT100.prototype.addstr = function(stuff)
-{
- for (var i = 0; i < stuff.length; ++i)
- this.addch(stuff.charAt(i));
-}
-
-VT100.prototype._cloneAttr = function VT100_cloneAttr(a)
-{
- return {
- mode: a.mode,
- fg: a.fg,
- bg: a.bg
- };
-}
-
-VT100.prototype.attroff = function(a)
-{
- //dump("attroff: " + a + "\n");
- a &= VT100.ATTR_FLAGS_;
- this.c_attr_.mode &= ~a;
-}
-
-VT100.prototype.attron = function(a)
-{
- //dump("attron: " + a + "\n");
- a &= VT100.ATTR_FLAGS_;
- this.c_attr_.mode |= a;
-}
-
-VT100.prototype.attrset = function(a)
-{
- //dump("attrset: " + a + "\n");
- this.c_attr_.mode = a;
-}
-
-VT100.prototype.fgset = function(fg)
-{
- //dump("fgset: " + fg + "\n");
- this.c_attr_.fg = fg;
-}
-
-VT100.prototype.bgset = function(bg)
-{
- //dump("bgset: " + bg + "\n");
- if (bg !== 0) {
- this.warn("bgset: " + bg + "\n");
- }
- this.c_attr_.bg = bg;
-}
-
-VT100.prototype.bkgdset = function(a)
-{
- this.bkgd_ = a;
-}
-
-VT100.prototype.clear = function()
-{
- this.debug("clear");
- this.row_ = this.col_ = 0;
- this.scrolled_ = 0;
- for (r = 0; r < this.ht_; ++r) {
- for (c = 0; c < this.wd_; ++c) {
- this.text_[r][c] = ' ';
- this.attr_[r][c] = this._cloneAttr(this.bkgd_);
- }
- }
-}
-
-VT100.prototype.clrtobot = function()
-{
- this.debug("clrtobot, row: " + this.row_);
- var ht = this.ht_;
- var wd = this.wd_;
- this.clrtoeol();
- for (var r = this.row_ + 1; r < ht; ++r) {
- for (var c = 0; c < wd; ++c) {
- this.text_[r][c] = ' ';
- this.attr_[r][c] = this.bkgd_;
- }
- }
-}
-
-VT100.prototype.clrtoeol = function()
-{
- this.debug("clrtoeol, col: " + this.col_);
- var r = this.row_;
- if (r >= this.ht_)
- return;
- for (var c = this.col_; c < this.wd_; ++c) {
- this.text_[r][c] = ' ';
- this.attr_[r][c] = this.bkgd_;
- }
-}
-
-VT100.prototype.clearpos = function(row, col)
-{
- this.debug("clearpos (" + row + ", " + col + ")");
- if (row < 0 || row >= this.ht_)
- return;
- if (col < 0 || col >= this.wd_)
- return;
- this.text_[row][col] = ' ';
- this.attr_[row][col] = this.bkgd_;
-}
-
-VT100.prototype.curs_set = function(vis, grab, eventist)
-{
- this.debug("curs_set:: vis: " + vis + ", grab: " + grab);
- if (vis !== undefined)
- this.cursor_vis_ = (vis > 0);
- if (eventist === undefined)
- eventist = window;
- if (grab === true || grab === false) {
- if (grab === this.grab_events_)
- return;
- if (grab) {
- this.grab_events_ = true;
- VT100.the_vt_ = this;
- eventist.addEventListener("keypress", VT100.handle_onkeypress_, false);
- if (VT100.browser_ie_)
- document.onkeydown = VT100.handle_onkeydown_;
- } else {
- eventist.removeEventListener("keypress", VT100.handle_onkeypress_, false);
- if (VT100.browser_ie_)
- document.onkeydown = VT100.handle_onkeydown_;
- this.grab_events_ = false;
- VT100.the_vt_ = undefined;
- }
- }
-}
-
-VT100.prototype.echo = function()
-{
- this.debug("echo on");
- this.echo_ = true;
-}
-
-VT100.prototype.erase = VT100.prototype.clear;
-
-VT100.prototype.getch = function(isr)
-{
- this.debug("getch");
- this.refresh();
- this.getch_isr_ = isr;
- setTimeout(VT100.go_getch_, 0);
-}
-
-VT100.prototype.getmaxyx = function()
-{
- return { y: this.ht_ - 1, x: this.wd_ - 1 };
-}
-
-VT100.prototype.getyx = function()
-{
- return { y: this.row_, x: this.col_ };
-}
-
-VT100.prototype.move = function(r, c)
-{
- this.debug("move: (" + r + ", " + c + ")");
- if (r < 0)
- r = 0;
- else if (r >= this.ht_)
- r = this.ht_ - 1;
- if (c < 0)
- c = 0;
- else if (c >= this.wd_)
- c = this.wd_ - 1;
- this.row_ = r;
- this.col_ = c;
-}
-
-VT100.prototype.noecho = function()
-{
- this.debug("echo off");
- this.echo_ = false;
-}
-
-VT100.prototype.refresh = function()
-{
- this.debug("refresh");
- var r, c, stuff = "", start_tag = "", end_tag = "", at = -1, n_at, ch,
- pair, cr, cc, ht, wd, cv, added_end_tag;
- ht = this.ht_;
- wd = this.wd_;
- cr = this.row_;
- cc = this.col_;
- cv = this.cursor_vis_;
- var innerHTML = this.scr_.innerHTML;
- if (cc >= wd)
- cc = wd - 1;
- for (r = 0; r < ht; ++r) {
- if (r > 0) {
- stuff += '\n';
- }
- for (c = 0; c < wd; ++c) {
- added_end_tag = false;
- n_at = this.attr_[r][c];
- if (cv && r == cr && c == cc) {
- // Draw the cursor here.
- n_at = this._cloneAttr(n_at);
- n_at.mode ^= VT100.A_REVERSE;
- }
- // If the attributes changed, make a new span.
- if (n_at.mode != at.mode || n_at.fg != at.fg || n_at.bg != at.bg) {
- if (c > 0) {
- stuff += end_tag;
- }
- start_tag = "";
- end_tag = "";
- if (n_at.mode & VT100.A_BLINK) {
- start_tag = "" + end_tag;
- }
- if (n_at.mode & VT100.A_STANDOUT)
- n_at.mode |= VT100.A_BOLD;
- pair = this.html_colours_(n_at);
- start_tag += '';
- stuff += start_tag;
- end_tag = "" + end_tag;
- at = n_at;
- added_end_tag = true;
- } else if (c == 0) {
- stuff += start_tag;
- }
- ch = this.text_[r][c];
- switch (ch) {
- case '&':
- stuff += '&'; break;
- case '<':
- stuff += '<'; break;
- case '>':
- stuff += '>'; break;
- case ' ':
- //stuff += ' '; break;
- stuff += ' '; break;
- default:
- stuff += ch;
- }
- }
- if (!added_end_tag)
- stuff += end_tag;
- }
- this.scr_.innerHTML = "" + stuff + "\n";
-}
-
-VT100.prototype.scroll = function()
-{
- this.scrolled_ += 1;
- this.debug("scrolled: " + this.scrolled_);
- var n_text = this.text_[0], n_attr = this.attr_[0],
- ht = this.ht_, wd = this.wd_;
- for (var r = 1; r < ht; ++r) {
- this.text_[r - 1] = this.text_[r];
- this.attr_[r - 1] = this.attr_[r];
- }
- this.text_[ht - 1] = n_text;
- this.attr_[ht - 1] = n_attr;
- for (var c = 0; c < wd; ++c) {
- n_text[c] = ' ';
- n_attr[c] = this.bkgd_;
- }
-}
-
-VT100.prototype.standend = function()
-{
- //this.debug("standend");
- this.attrset(0);
-}
-
-VT100.prototype.standout = function()
-{
- //this.debug("standout");
- this.attron(VT100.A_STANDOUT);
-}
-
-VT100.prototype.write = function(stuff)
-{
- var ch, x, r, c, i, j, yx, myx;
- for (i = 0; i < stuff.length; ++i) {
- ch = stuff.charAt(i);
- if (ch == '\x0D') {
- this.debug("write:: ch: " + ch.charCodeAt(0) + ", '\\x0D'");
- } else {
- this.debug("write:: ch: " + ch.charCodeAt(0) + ", '" + (ch == '\x1b' ? "ESC" : ch) + "'");
- }
- //dump("ch: " + ch.charCodeAt(0) + ", '" + (ch == '\x1b' ? "ESC" : ch) + "'\n");
- switch (ch) {
- case '\x00':
- case '\x7f':
- case '\x07': /* bell, ignore it */
- this.debug("write:: ignoring bell character: " + ch);
- continue;
- case '\a':
- case '\b':
- case '\t':
- case '\r':
- this.addch(ch);
- continue;
- case '\n':
- case '\v':
- case '\f': // what a mess
- yx = this.getyx();
- myx = this.getmaxyx();
- if (yx.y >= myx.y) {
- this.scroll();
- this.move(myx.y, 0);
- } else
- this.move(yx.y + 1, 0);
- continue;
- case '\x18':
- case '\x1a':
- this.esc_state_ = 0;
- this.debug("write:: set escape state: 0");
- continue;
- case '\x1b':
- this.esc_state_ = 1;
- this.debug("write:: set escape state: 1");
- continue;
- case '\x9b':
- this.esc_state_ = 2;
- this.debug("write:: set escape state: 2");
- continue;
- }
- // not a recognized control character
- switch (this.esc_state_) {
- case 0: // not in escape sequence
- this.addch(ch);
- break;
- case 1: // just saw ESC
- switch (ch) {
- case '[':
- this.esc_state_ = 2;
- this.debug("write:: set escape state: 2");
- break;
- case '=':
- /* Set keypade mode (ignored) */
- this.debug("write:: set keypade mode: ignored");
- this.esc_state_ = 0;
- break;
- case '>':
- /* Reset keypade mode (ignored) */
- this.debug("write:: reset keypade mode: ignored");
- this.esc_state_ = 0;
- break;
- case 'H':
- /* Set tab at cursor column (ignored) */
- this.debug("write:: set tab cursor column: ignored");
- this.esc_state_ = 0;
- break;
- }
- break;
- case 2: // just saw CSI
- switch (ch) {
- case 'K':
- /* Erase in Line */
- this.esc_state_ = 0;
- this.clrtoeol();
- continue;
- case 'H':
- /* Move to (0,0). */
- this.esc_state_ = 0;
- this.move(0, 0);
- continue;
- case 'J':
- /* Clear to the bottom. */
- this.esc_state_ = 0;
- this.clrtobot();
- continue;
- case '?':
- /* Special VT100 mode handling. */
- this.esc_state_ = 5;
- this.debug("write:: special vt100 mode");
- continue;
- }
- // Drop through to next case.
- this.csi_parms_ = [0];
- this.debug("write:: set escape state: 3");
- this.esc_state_ = 3;
- case 3: // saw CSI and parameters
- switch (ch) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- x = this.csi_parms_.pop();
- this.csi_parms_.push(x * 10 + ch * 1);
- this.debug("csi_parms_: " + this.csi_parms_);
- continue;
- case ';':
- if (this.csi_parms_.length < 17)
- this.csi_parms_.push(0);
- continue;
- }
- this.esc_state_ = 0;
- switch (ch) {
- case 'A':
- // Cursor Up [{COUNT}A
- this.move(this.row_ - Math.max(1, this.csi_parms_[0]),
- this.col_);
- break;
- case 'B':
- // Cursor Down [{COUNT}B
- this.move(this.row_ + Math.max(1, this.csi_parms_[0]),
- this.col_);
- break;
- case 'C':
- // Cursor Forward [{COUNT}C
- this.move(this.row_,
- this.col_ + Math.max(1, this.csi_parms_[0]));
- break;
- case 'c':
- this.warn("write:: got TERM query");
- break;
- case 'D':
- // Cursor Backward [{COUNT}D
- this.move(this.row_,
- this.col_ - Math.max(1, this.csi_parms_[0]));
- break;
- case 'f':
- case 'H':
- // Cursor Home [{ROW};{COLUMN}H
- this.csi_parms_.push(0);
- this.move(this.csi_parms_[0] - 1,
- this.csi_parms_[1] - 1);
- break;
- case 'J':
- switch (this.csi_parms_[0]) {
- case 0:
- this.clrtobot();
- break;
- case 2:
- this.clear();
- this.move(0, 0);
- }
- break;
- case 'm':
- for (j=0; j[?
- // Expect a number - the reset type
- this.csi_parms_ = [ch];
- this.esc_state_ = 6;
- break;
- case 6: // Reset mode handling, saw [?1
- // Expect a letter - the mode target, example:
- // [?1l : cursor key mode = cursor
- // [?1h : save current screen, create new empty
- // screen and position at 0,0
- // [?5l : White on blk
- // XXX: Ignored for now.
- //dump("Saw reset mode: [?" + this.csi_parms_[0] + ch + "\n");
- this.esc_state_ = 0;
- this.debug("write:: set escape state: 0");
- break;
- }
- }
- this.refresh();
-}
-
-VT100.prototype.debug = function(message) {
- if (this.debug_) {
- dump(message + "\n");
- }
-}
-
-VT100.prototype.warn = function(message) {
- dump(message + "\n");
-}
diff --git a/utils/include b/utils/include
deleted file mode 120000
index f5030fe8..00000000
--- a/utils/include
+++ /dev/null
@@ -1 +0,0 @@
-../include
\ No newline at end of file
diff --git a/utils/md5.c b/utils/md5.c
deleted file mode 100644
index dcdc3685..00000000
--- a/utils/md5.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/* Functions to compute MD5 message digest of files or memory blocks.
- according to the definition of MD5 in RFC 1321 from April 1992.
- Copyright (C) 1995,1996,1997,1999,2000,2001,2005
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-/* Written by Ulrich Drepper , 1995. */
-
-#ifdef HAVE_CONFIG_H
-# include
-#endif
-
-#include
-
-#if STDC_HEADERS || defined _LIBC
-# include
-# include
-#else
-# ifndef HAVE_MEMCPY
-# define memcpy(d, s, n) (bcopy ((s), (d), (n)), (d))
-# endif
-#endif
-
-#ifndef __THROW
-#define __THROW
-#endif
-
-#include "md5.h"
-
-#ifdef _LIBC
-# include
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define WORDS_BIGENDIAN 1
-# endif
-/* We need to keep the namespace clean so define the MD5 function
- protected using leading __ . */
-# define md5_init_ctx __md5_init_ctx
-# define md5_process_block __md5_process_block
-# define md5_process_bytes __md5_process_bytes
-# define md5_finish_ctx __md5_finish_ctx
-# define md5_read_ctx __md5_read_ctx
-# define md5_stream __md5_stream
-# define md5_buffer __md5_buffer
-#else
-/* Squelch compiler complaints */
-void md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx);
-void md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx);
-#endif
-
-#ifdef WORDS_BIGENDIAN
-# define SWAP(n) \
- (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-#else
-# define SWAP(n) (n)
-#endif
-
-
-/* This array contains the bytes used to pad the buffer to the next
- 64-byte boundary. (RFC 1321, 3.1: Step 1) */
-static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
-
-
-/* Initialize structure containing state of computation.
- (RFC 1321, 3.3: Step 3) */
-void
-md5_init_ctx (ctx)
- struct md5_ctx *ctx;
-{
- ctx->A = 0x67452301;
- ctx->B = 0xefcdab89;
- ctx->C = 0x98badcfe;
- ctx->D = 0x10325476;
-
- ctx->total[0] = ctx->total[1] = 0;
- ctx->buflen = 0;
-}
-
-/* Put result from CTX in first 16 bytes following RESBUF. The result
- must be in little endian byte order.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-void *
-md5_read_ctx (ctx, resbuf)
- const struct md5_ctx *ctx;
- void *resbuf;
-{
- ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
- ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
- ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
- ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
-
- return resbuf;
-}
-
-/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-void *
-md5_finish_ctx (ctx, resbuf)
- struct md5_ctx *ctx;
- void *resbuf;
-{
- /* Take yet unprocessed bytes into account. */
- md5_uint32 bytes = ctx->buflen;
- size_t pad;
-
- /* Now count remaining bytes. */
- ctx->total[0] += bytes;
- if (ctx->total[0] < bytes)
- ++ctx->total[1];
-
- pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
- memcpy (&ctx->buffer[bytes], fillbuf, pad);
-
- /* Put the 64-bit file length in *bits* at the end of the buffer. */
- *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
- *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
- (ctx->total[0] >> 29));
-
- /* Process last bytes. */
- md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
-
- return md5_read_ctx (ctx, resbuf);
-}
-
-/* Compute MD5 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
- beginning at RESBLOCK. */
-int
-md5_stream (stream, resblock)
- FILE *stream;
- void *resblock;
-{
- /* Important: BLOCKSIZE must be a multiple of 64. */
-#define BLOCKSIZE 4096
- struct md5_ctx ctx;
- char buffer[BLOCKSIZE + 72];
- size_t sum;
-
- /* Initialize the computation context. */
- md5_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- do
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
- }
- while (sum < BLOCKSIZE && n != 0);
- if (n == 0 && ferror (stream))
- return 1;
-
- /* If end of file is reached, end the loop. */
- if (n == 0)
- break;
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 64 == 0
- */
- md5_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- /* Add the last bytes if necessary. */
- if (sum > 0)
- md5_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- md5_finish_ctx (&ctx, resblock);
- return 0;
-}
-
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
- result is always in little endian byte order, so that a byte-wise
- output yields to the wanted ASCII representation of the message
- digest. */
-void *
-md5_buffer (buffer, len, resblock)
- const char *buffer;
- size_t len;
- void *resblock;
-{
- struct md5_ctx ctx;
-
- /* Initialize the computation context. */
- md5_init_ctx (&ctx);
-
- /* Process whole buffer but last len % 64 bytes. */
- md5_process_bytes (buffer, len, &ctx);
-
- /* Put result in desired memory area. */
- return md5_finish_ctx (&ctx, resblock);
-}
-
-
-void
-md5_process_bytes (buffer, len, ctx)
- const void *buffer;
- size_t len;
- struct md5_ctx *ctx;
-{
- /* When we already have some bits in our internal buffer concatenate
- both inputs first. */
- if (ctx->buflen != 0)
- {
- size_t left_over = ctx->buflen;
- size_t add = 128 - left_over > len ? len : 128 - left_over;
-
- memcpy (&ctx->buffer[left_over], buffer, add);
- ctx->buflen += add;
-
- if (ctx->buflen > 64)
- {
- md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
-
- ctx->buflen &= 63;
- /* The regions in the following copy operation cannot overlap. */
- memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
- ctx->buflen);
- }
-
- buffer = (const char *) buffer + add;
- len -= add;
- }
-
- /* Process available complete blocks. */
- if (len >= 64)
- {
-#if !_STRING_ARCH_unaligned
-/* To check alignment gcc has an appropriate operator. Other
- compilers don't. */
-# if __GNUC__ >= 2
-# define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
-# else
-# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
-# endif
- if (UNALIGNED_P (buffer))
- while (len > 64)
- {
- md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
- buffer = (const char *) buffer + 64;
- len -= 64;
- }
- else
-#endif
- {
- md5_process_block (buffer, len & ~63, ctx);
- buffer = (const char *) buffer + (len & ~63);
- len &= 63;
- }
- }
-
- /* Move remaining bytes in internal buffer. */
- if (len > 0)
- {
- size_t left_over = ctx->buflen;
-
- memcpy (&ctx->buffer[left_over], buffer, len);
- left_over += len;
- if (left_over >= 64)
- {
- md5_process_block (ctx->buffer, 64, ctx);
- left_over -= 64;
- memcpy (ctx->buffer, &ctx->buffer[64], left_over);
- }
- ctx->buflen = left_over;
- }
-}
-
-
-/* These are the four functions used in the four steps of the MD5 algorithm
- and defined in the RFC 1321. The first function is a little bit optimized
- (as found in Colin Plumbs public domain implementation). */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-
-/* Process LEN bytes of BUFFER, accumulating context into CTX.
- It is assumed that LEN % 64 == 0. */
-
-void
-md5_process_block (buffer, len, ctx)
- const void *buffer;
- size_t len;
- struct md5_ctx *ctx;
-{
- md5_uint32 correct_words[16];
- const md5_uint32 *words = buffer;
- size_t nwords = len / sizeof (md5_uint32);
- const md5_uint32 *endp = words + nwords;
- md5_uint32 A = ctx->A;
- md5_uint32 B = ctx->B;
- md5_uint32 C = ctx->C;
- md5_uint32 D = ctx->D;
-
- /* First increment the byte count. RFC 1321 specifies the possible
- length of the file up to 2^64 bits. Here we only compute the
- number of bytes. Do a double word increment. */
- ctx->total[0] += len;
- if (ctx->total[0] < len)
- ++ctx->total[1];
-
- /* Process all bytes in the buffer with 64 bytes in each round of
- the loop. */
- while (words < endp)
- {
- md5_uint32 *cwp = correct_words;
- md5_uint32 A_save = A;
- md5_uint32 B_save = B;
- md5_uint32 C_save = C;
- md5_uint32 D_save = D;
-
- /* First round: using the given function, the context and a constant
- the next context is computed. Because the algorithms processing
- unit is a 32-bit word and it is determined to work on words in
- little endian byte order we perhaps have to change the byte order
- before the computation. To reduce the work for the next steps
- we store the swapped words in the array CORRECT_WORDS. */
-
-#define OP(a, b, c, d, s, T) \
- do \
- { \
- a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
- ++words; \
- CYCLIC (a, s); \
- a += b; \
- } \
- while (0)
-
- /* It is unfortunate that C does not provide an operator for
- cyclic rotation. Hope the C compiler is smart enough. */
-#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
-
- /* Before we start, one word to the strange constants.
- They are defined in RFC 1321 as
-
- T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
- */
-
- /* Round 1. */
- OP (A, B, C, D, 7, 0xd76aa478);
- OP (D, A, B, C, 12, 0xe8c7b756);
- OP (C, D, A, B, 17, 0x242070db);
- OP (B, C, D, A, 22, 0xc1bdceee);
- OP (A, B, C, D, 7, 0xf57c0faf);
- OP (D, A, B, C, 12, 0x4787c62a);
- OP (C, D, A, B, 17, 0xa8304613);
- OP (B, C, D, A, 22, 0xfd469501);
- OP (A, B, C, D, 7, 0x698098d8);
- OP (D, A, B, C, 12, 0x8b44f7af);
- OP (C, D, A, B, 17, 0xffff5bb1);
- OP (B, C, D, A, 22, 0x895cd7be);
- OP (A, B, C, D, 7, 0x6b901122);
- OP (D, A, B, C, 12, 0xfd987193);
- OP (C, D, A, B, 17, 0xa679438e);
- OP (B, C, D, A, 22, 0x49b40821);
-
- /* For the second to fourth round we have the possibly swapped words
- in CORRECT_WORDS. Redefine the macro to take an additional first
- argument specifying the function to use. */
-#undef OP
-#define OP(f, a, b, c, d, k, s, T) \
- do \
- { \
- a += f (b, c, d) + correct_words[k] + T; \
- CYCLIC (a, s); \
- a += b; \
- } \
- while (0)
-
- /* Round 2. */
- OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
- OP (FG, D, A, B, C, 6, 9, 0xc040b340);
- OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
- OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
- OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
- OP (FG, D, A, B, C, 10, 9, 0x02441453);
- OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
- OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
- OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
- OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
- OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
- OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
- OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
- OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
- OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
- OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
- /* Round 3. */
- OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
- OP (FH, D, A, B, C, 8, 11, 0x8771f681);
- OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
- OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
- OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
- OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
- OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
- OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
- OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
- OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
- OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
- OP (FH, B, C, D, A, 6, 23, 0x04881d05);
- OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
- OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
- OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
- OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
-
- /* Round 4. */
- OP (FI, A, B, C, D, 0, 6, 0xf4292244);
- OP (FI, D, A, B, C, 7, 10, 0x432aff97);
- OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
- OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
- OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
- OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
- OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
- OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
- OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
- OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
- OP (FI, C, D, A, B, 6, 15, 0xa3014314);
- OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
- OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
- OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
- OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
- OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
-
- /* Add the starting values of the context. */
- A += A_save;
- B += B_save;
- C += C_save;
- D += D_save;
- }
-
- /* Put checksum in context given as argument. */
- ctx->A = A;
- ctx->B = B;
- ctx->C = C;
- ctx->D = D;
-}
diff --git a/utils/md5.h b/utils/md5.h
deleted file mode 100644
index b48545bf..00000000
--- a/utils/md5.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Declaration of functions and data types used for MD5 sum computing
- library functions.
- Copyright (C) 1995-1997,1999,2000,2001,2004,2005
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _MD5_H
-#define _MD5_H 1
-
-#include
-
-#if defined HAVE_LIMITS_H || _LIBC
-# include
-#endif
-
-#define MD5_DIGEST_SIZE 16
-#define MD5_BLOCK_SIZE 64
-
-/* The following contortions are an attempt to use the C preprocessor
- to determine an unsigned integral type that is 32 bits wide. An
- alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
- doing that would require that the configure script compile and *run*
- the resulting executable. Locally running cross-compiled executables
- is usually not possible. */
-
-#ifdef _LIBC
-# include
-typedef uint32_t md5_uint32;
-typedef uintptr_t md5_uintptr;
-#else
-# if defined __STDC__ && __STDC__
-# define UINT_MAX_32_BITS 4294967295U
-# else
-# define UINT_MAX_32_BITS 0xFFFFFFFF
-# endif
-
-/* If UINT_MAX isn't defined, assume it's a 32-bit type.
- This should be valid for all systems GNU cares about because
- that doesn't include 16-bit systems, and only modern systems
- (that certainly have ) have 64+-bit integral types. */
-
-# ifndef UINT_MAX
-# define UINT_MAX UINT_MAX_32_BITS
-# endif
-
-# if UINT_MAX == UINT_MAX_32_BITS
- typedef unsigned int md5_uint32;
-# else
-# if USHRT_MAX == UINT_MAX_32_BITS
- typedef unsigned short md5_uint32;
-# else
-# if ULONG_MAX == UINT_MAX_32_BITS
- typedef unsigned long md5_uint32;
-# else
- /* The following line is intended to evoke an error.
- Using #error is not portable enough. */
- "Cannot determine unsigned 32-bit data type."
-# endif
-# endif
-# endif
-/* We have to make a guess about the integer type equivalent in size
- to pointers which should always be correct. */
-typedef unsigned long int md5_uintptr;
-#endif
-
-/* Structure to save state of computation between the single steps. */
-struct md5_ctx
-{
- md5_uint32 A;
- md5_uint32 B;
- md5_uint32 C;
- md5_uint32 D;
-
- md5_uint32 total[2];
- md5_uint32 buflen;
- char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
-};
-
-/*
- * The following three functions are build up the low level used in
- * the functions `md5_stream' and `md5_buffer'.
- */
-
-/* Initialize structure containing state of computation.
- (RFC 1321, 3.3: Step 3) */
-extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW;
-
-/* Starting with the result of former calls of this function (or the
- initialization function update the context for the next LEN bytes
- starting at BUFFER.
- It is necessary that LEN is a multiple of 64!!! */
-extern void __md5_process_block (const void *buffer, size_t len,
- struct md5_ctx *ctx) __THROW;
-
-/* Starting with the result of former calls of this function (or the
- initialization function update the context for the next LEN bytes
- starting at BUFFER.
- It is NOT required that LEN is a multiple of 64. */
-extern void __md5_process_bytes (const void *buffer, size_t len,
- struct md5_ctx *ctx) __THROW;
-
-/* Process the remaining bytes in the buffer and put result from CTX
- in first 16 bytes following RESBUF. The result is always in little
- endian byte order, so that a byte-wise output yields to the wanted
- ASCII representation of the message digest.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
-
-
-/* Put result from CTX in first 16 bytes following RESBUF. The result is
- always in little endian byte order, so that a byte-wise output yields
- to the wanted ASCII representation of the message digest.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
-
-
-/* Compute MD5 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
- beginning at RESBLOCK. */
-extern int __md5_stream (FILE *stream, void *resblock) __THROW;
-
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
- result is always in little endian byte order, so that a byte-wise
- output yields to the wanted ASCII representation of the message
- digest. */
-extern void *__md5_buffer (const char *buffer, size_t len,
- void *resblock) __THROW;
-
-#endif /* md5.h */
diff --git a/utils/md5_test.c b/utils/md5_test.c
deleted file mode 100644
index 81c0f0a8..00000000
--- a/utils/md5_test.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int main () {
- printf("hello world\n");
-}
diff --git a/utils/websocket.c b/utils/websocket.c
deleted file mode 100644
index f73bb22a..00000000
--- a/utils/websocket.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * WebSocket lib with support for "wss://" encryption.
- * Copyright 2010 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
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include // daemonizing
-#include // daemonizing
-#include
-#include
-#include /* base64 encode/decode */
-#include "websocket.h"
-
-const char server_handshake[] = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\
-Upgrade: WebSocket\r\n\
-Connection: Upgrade\r\n\
-%sWebSocket-Origin: %s\r\n\
-%sWebSocket-Location: %s://%s%s\r\n\
-%sWebSocket-Protocol: sample\r\n\
-\r\n%s";
-
-const char policy_response[] = "\n";
-
-/*
- * Global state
- *
- * Warning: not thread safe
- */
-int ssl_initialized = 0;
-int pipe_error = 0;
-char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp;
-unsigned int bufsize, dbufsize;
-settings_t settings;
-
-void traffic(char * token) {
- if ((settings.verbose) && (! settings.daemon)) {
- fprintf(stdout, "%s", token);
- fflush(stdout);
- }
-}
-
-void error(char *msg)
-{
- perror(msg);
-}
-
-void fatal(char *msg)
-{
- perror(msg);
- exit(1);
-}
-
-/* resolve host with also IP address parsing */
-int resolve_host(struct in_addr *sin_addr, const char *hostname)
-{
- if (!inet_aton(hostname, sin_addr)) {
- struct addrinfo *ai, *cur;
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- if (getaddrinfo(hostname, NULL, &hints, &ai))
- return -1;
- for (cur = ai; cur; cur = cur->ai_next) {
- if (cur->ai_family == AF_INET) {
- *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
- freeaddrinfo(ai);
- return 0;
- }
- }
- freeaddrinfo(ai);
- return -1;
- }
- return 0;
-}
-
-
-/*
- * SSL Wrapper Code
- */
-
-ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len) {
- if (ctx->ssl) {
- //handler_msg("SSL recv\n");
- return SSL_read(ctx->ssl, buf, len);
- } else {
- return recv(ctx->sockfd, buf, len, 0);
- }
-}
-
-ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len) {
- if (ctx->ssl) {
- //handler_msg("SSL send\n");
- return SSL_write(ctx->ssl, buf, len);
- } else {
- return send(ctx->sockfd, buf, len, 0);
- }
-}
-
-ws_ctx_t *ws_socket(int socket) {
- ws_ctx_t *ctx;
- ctx = malloc(sizeof(ws_ctx_t));
- ctx->sockfd = socket;
- ctx->ssl = NULL;
- ctx->ssl_ctx = NULL;
- return ctx;
-}
-
-ws_ctx_t *ws_socket_ssl(int socket, char * certfile, char * keyfile) {
- int ret;
- char msg[1024];
- char * use_keyfile;
- ws_ctx_t *ctx;
- ctx = ws_socket(socket);
-
- if (keyfile && (keyfile[0] != '\0')) {
- // Separate key file
- use_keyfile = keyfile;
- } else {
- // Combined key and cert file
- use_keyfile = certfile;
- }
-
- // Initialize the library
- if (! ssl_initialized) {
- SSL_library_init();
- OpenSSL_add_all_algorithms();
- SSL_load_error_strings();
- ssl_initialized = 1;
-
- }
-
- ctx->ssl_ctx = SSL_CTX_new(TLSv1_server_method());
- if (ctx->ssl_ctx == NULL) {
- ERR_print_errors_fp(stderr);
- fatal("Failed to configure SSL context");
- }
-
- if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, use_keyfile,
- SSL_FILETYPE_PEM) <= 0) {
- sprintf(msg, "Unable to load private key file %s\n", use_keyfile);
- fatal(msg);
- }
-
- if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, certfile,
- SSL_FILETYPE_PEM) <= 0) {
- sprintf(msg, "Unable to load certificate file %s\n", certfile);
- fatal(msg);
- }
-
-// if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, "DEFAULT") != 1) {
-// sprintf(msg, "Unable to set cipher\n");
-// fatal(msg);
-// }
-
- // Associate socket and ssl object
- ctx->ssl = SSL_new(ctx->ssl_ctx);
- SSL_set_fd(ctx->ssl, socket);
-
- ret = SSL_accept(ctx->ssl);
- if (ret < 0) {
- ERR_print_errors_fp(stderr);
- return NULL;
- }
-
- return ctx;
-}
-
-int ws_socket_free(ws_ctx_t *ctx) {
- if (ctx->ssl) {
- SSL_free(ctx->ssl);
- ctx->ssl = NULL;
- }
- if (ctx->ssl_ctx) {
- SSL_CTX_free(ctx->ssl_ctx);
- ctx->ssl_ctx = NULL;
- }
- if (ctx->sockfd) {
- shutdown(ctx->sockfd, SHUT_RDWR);
- close(ctx->sockfd);
- ctx->sockfd = 0;
- }
- free(ctx);
-}
-
-/* ------------------------------------------------------- */
-
-
-int encode(u_char const *src, size_t srclength, char *target, size_t targsize) {
- int i, sz = 0, len = 0;
- unsigned char chr;
- target[sz++] = '\x00';
- len = b64_ntop(src, srclength, target+sz, targsize-sz);
- if (len < 0) {
- return len;
- }
- sz += len;
- target[sz++] = '\xff';
- return sz;
-}
-
-int decode(char *src, size_t srclength, u_char *target, size_t targsize) {
- char *start, *end, cntstr[4];
- int i, len, framecount = 0, retlen = 0;
- unsigned char chr;
- if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) {
- handler_emsg("WebSocket framing error\n");
- return -1;
- }
- start = src+1; // Skip '\x00' start
- do {
- /* We may have more than one frame */
- end = memchr(start, '\xff', srclength);
- *end = '\x00';
- len = b64_pton(start, target+retlen, targsize-retlen);
- if (len < 0) {
- return len;
- }
- retlen += len;
- start = end + 2; // Skip '\xff' end and '\x00' start
- framecount++;
- } while (end < (src+srclength-1));
- if (framecount > 1) {
- snprintf(cntstr, 3, "%d", framecount);
- traffic(cntstr);
- }
- return retlen;
-}
-
-int parse_handshake(char *handshake, headers_t *headers) {
- char *start, *end;
-
- if ((strlen(handshake) < 92) || (bcmp(handshake, "GET ", 4) != 0)) {
- return 0;
- }
- start = handshake+4;
- end = strstr(start, " HTTP/1.1");
- if (!end) { return 0; }
- strncpy(headers->path, start, end-start);
- headers->path[end-start] = '\0';
-
- start = strstr(handshake, "\r\nHost: ");
- if (!start) { return 0; }
- start += 8;
- end = strstr(start, "\r\n");
- strncpy(headers->host, start, end-start);
- headers->host[end-start] = '\0';
-
- start = strstr(handshake, "\r\nOrigin: ");
- if (!start) { return 0; }
- start += 10;
- end = strstr(start, "\r\n");
- strncpy(headers->origin, start, end-start);
- headers->origin[end-start] = '\0';
-
- start = strstr(handshake, "\r\n\r\n");
- if (!start) { return 0; }
- start += 4;
- if (strlen(start) == 8) {
- strncpy(headers->key3, start, 8);
- headers->key3[8] = '\0';
-
- start = strstr(handshake, "\r\nSec-WebSocket-Key1: ");
- if (!start) { return 0; }
- start += 22;
- end = strstr(start, "\r\n");
- strncpy(headers->key1, start, end-start);
- headers->key1[end-start] = '\0';
-
- start = strstr(handshake, "\r\nSec-WebSocket-Key2: ");
- if (!start) { return 0; }
- start += 22;
- end = strstr(start, "\r\n");
- strncpy(headers->key2, start, end-start);
- headers->key2[end-start] = '\0';
- } else {
- headers->key1[0] = '\0';
- headers->key2[0] = '\0';
- headers->key3[0] = '\0';
- }
-
- return 1;
-}
-
-int gen_md5(headers_t *headers, char *target) {
- unsigned int i, spaces1 = 0, spaces2 = 0;
- unsigned long num1 = 0, num2 = 0;
- unsigned char buf[17];
- for (i=0; i < strlen(headers->key1); i++) {
- if (headers->key1[i] == ' ') {
- spaces1 += 1;
- }
- if ((headers->key1[i] >= 48) && (headers->key1[i] <= 57)) {
- num1 = num1 * 10 + (headers->key1[i] - 48);
- }
- }
- num1 = num1 / spaces1;
-
- for (i=0; i < strlen(headers->key2); i++) {
- if (headers->key2[i] == ' ') {
- spaces2 += 1;
- }
- if ((headers->key2[i] >= 48) && (headers->key2[i] <= 57)) {
- num2 = num2 * 10 + (headers->key2[i] - 48);
- }
- }
- num2 = num2 / spaces2;
-
- /* Pack it big-endian */
- buf[0] = (num1 & 0xff000000) >> 24;
- buf[1] = (num1 & 0xff0000) >> 16;
- buf[2] = (num1 & 0xff00) >> 8;
- buf[3] = num1 & 0xff;
-
- buf[4] = (num2 & 0xff000000) >> 24;
- buf[5] = (num2 & 0xff0000) >> 16;
- buf[6] = (num2 & 0xff00) >> 8;
- buf[7] = num2 & 0xff;
-
- strncpy(buf+8, headers->key3, 8);
- buf[16] = '\0';
-
- md5_buffer(buf, 16, target);
- target[16] = '\0';
-
- return 1;
-}
-
-
-
-ws_ctx_t *do_handshake(int sock) {
- char handshake[4096], response[4096], trailer[17];
- char *scheme, *pre;
- headers_t headers;
- int len, ret;
- ws_ctx_t * ws_ctx;
-
- // Peek, but don't read the data
- len = recv(sock, handshake, 1024, MSG_PEEK);
- handshake[len] = 0;
- if (len == 0) {
- handler_msg("ignoring empty handshake\n");
- return NULL;
- } else if (bcmp(handshake, "", 22) == 0) {
- len = recv(sock, handshake, 1024, 0);
- handshake[len] = 0;
- handler_msg("sending flash policy response\n");
- send(sock, policy_response, sizeof(policy_response), 0);
- return NULL;
- } else if ((bcmp(handshake, "\x16", 1) == 0) ||
- (bcmp(handshake, "\x80", 1) == 0)) {
- // SSL
- if (!settings.cert) {
- handler_msg("SSL connection but no cert specified\n");
- return NULL;
- } else if (access(settings.cert, R_OK) != 0) {
- handler_msg("SSL connection but '%s' not found\n",
- settings.cert);
- return NULL;
- }
- ws_ctx = ws_socket_ssl(sock, settings.cert, settings.key);
- if (! ws_ctx) { return NULL; }
- scheme = "wss";
- handler_msg("using SSL socket\n");
- } else if (settings.ssl_only) {
- handler_msg("non-SSL connection disallowed\n");
- return NULL;
- } else {
- ws_ctx = ws_socket(sock);
- if (! ws_ctx) { return NULL; }
- scheme = "ws";
- handler_msg("using plain (not SSL) socket\n");
- }
- len = ws_recv(ws_ctx, handshake, 4096);
- if (len == 0) {
- handler_emsg("Client closed during handshake\n");
- return NULL;
- }
- handshake[len] = 0;
-
- if (!parse_handshake(handshake, &headers)) {
- handler_emsg("Invalid WS request\n");
- return NULL;
- }
-
- if (headers.key3[0] != '\0') {
- gen_md5(&headers, trailer);
- pre = "Sec-";
- handler_msg("using protocol version 76\n");
- } else {
- trailer[0] = '\0';
- pre = "";
- handler_msg("using protocol version 75\n");
- }
-
- sprintf(response, server_handshake, pre, headers.origin, pre, scheme,
- headers.host, headers.path, pre, trailer);
- //handler_msg("response: %s\n", response);
- ws_send(ws_ctx, response, strlen(response));
-
- return ws_ctx;
-}
-
-void signal_handler(sig) {
- switch (sig) {
- case SIGHUP: break; // ignore for now
- case SIGPIPE: pipe_error = 1; break; // handle inline
- case SIGTERM: exit(0); break;
- }
-}
-
-void daemonize(int keepfd) {
- int pid, i;
-
- umask(0);
- chdir('/');
- setgid(getgid());
- setuid(getuid());
-
- /* Double fork to daemonize */
- pid = fork();
- if (pid<0) { fatal("fork error"); }
- if (pid>0) { exit(0); } // parent exits
- setsid(); // Obtain new process group
- pid = fork();
- if (pid<0) { fatal("fork error"); }
- if (pid>0) { exit(0); } // parent exits
-
- /* Signal handling */
- signal(SIGHUP, signal_handler); // catch HUP
- signal(SIGTERM, signal_handler); // catch kill
-
- /* Close open files */
- for (i=getdtablesize(); i>=0; --i) {
- if (i != keepfd) {
- close(i);
- } else if (settings.verbose) {
- printf("keeping fd %d\n", keepfd);
- }
- }
- i=open("/dev/null", O_RDWR); // Redirect stdin
- dup(i); // Redirect stdout
- dup(i); // Redirect stderr
-}
-
-
-void start_server() {
- int lsock, csock, pid, clilen, sopt = 1, i;
- struct sockaddr_in serv_addr, cli_addr;
- ws_ctx_t *ws_ctx;
-
- /* Initialize buffers */
- bufsize = 65536;
- if (! (tbuf = malloc(bufsize)) )
- { fatal("malloc()"); }
- if (! (cbuf = malloc(bufsize)) )
- { fatal("malloc()"); }
- if (! (tbuf_tmp = malloc(bufsize)) )
- { fatal("malloc()"); }
- if (! (cbuf_tmp = malloc(bufsize)) )
- { fatal("malloc()"); }
-
- lsock = socket(AF_INET, SOCK_STREAM, 0);
- if (lsock < 0) { error("ERROR creating listener socket"); }
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(settings.listen_port);
-
- /* Resolve listen address */
- if (settings.listen_host && (settings.listen_host[0] != '\0')) {
- if (resolve_host(&serv_addr.sin_addr, settings.listen_host) < -1) {
- fatal("Could not resolve listen address");
- }
- } else {
- serv_addr.sin_addr.s_addr = INADDR_ANY;
- }
-
- setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&sopt, sizeof(sopt));
- if (bind(lsock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
- fatal("ERROR on binding listener socket");
- }
- listen(lsock,100);
-
- signal(SIGPIPE, signal_handler); // catch pipe
-
- if (settings.daemon) {
- daemonize(lsock);
- }
-
- // Reep zombies
- signal(SIGCHLD, SIG_IGN);
-
- printf("Waiting for connections on %s:%d\n",
- settings.listen_host, settings.listen_port);
-
- while (1) {
- clilen = sizeof(cli_addr);
- pipe_error = 0;
- pid = 0;
- csock = accept(lsock,
- (struct sockaddr *) &cli_addr,
- &clilen);
- if (csock < 0) {
- error("ERROR on accept");
- continue;
- }
- handler_msg("got client connection from %s\n",
- inet_ntoa(cli_addr.sin_addr));
- /* base64 is 4 bytes for every 3
- * 20 for WS '\x00' / '\xff' and good measure */
- dbufsize = (bufsize * 3)/4 - 20;
-
- handler_msg("forking handler process\n");
- pid = fork();
-
- if (pid == 0) { // handler process
- ws_ctx = do_handshake(csock);
- if (ws_ctx == NULL) {
- handler_msg("No connection after handshake\n");
- break; // Child process exits
- }
-
- settings.handler(ws_ctx);
- if (pipe_error) {
- handler_emsg("Closing due to SIGPIPE\n");
- }
- break; // Child process exits
- } else { // parent process
- settings.handler_id += 1;
- }
- }
- if (pid == 0) {
- if (ws_ctx) {
- ws_socket_free(ws_ctx);
- } else {
- shutdown(csock, SHUT_RDWR);
- close(csock);
- }
- handler_msg("handler exit\n");
- } else {
- handler_msg("wsproxy exit\n");
- }
-
-}
-
diff --git a/utils/websocket.h b/utils/websocket.h
deleted file mode 100644
index c428fa53..00000000
--- a/utils/websocket.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#include
-
-typedef struct {
- int sockfd;
- SSL_CTX *ssl_ctx;
- SSL *ssl;
-} ws_ctx_t;
-
-typedef struct {
- int verbose;
- char listen_host[256];
- int listen_port;
- void (*handler)(ws_ctx_t*);
- int handler_id;
- char *cert;
- char *key;
- int ssl_only;
- int daemon;
-} settings_t;
-
-typedef struct {
- char path[1024+1];
- char host[1024+1];
- char origin[1024+1];
- char key1[1024+1];
- char key2[1024+1];
- char key3[8+1];
-} headers_t;
-
-
-ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len);
-
-ssize_t ws_send(ws_ctx_t *ctx, const void *buf, size_t len);
-
-/* base64.c declarations */
-//int b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
-//int b64_pton(char const *src, u_char *target, size_t targsize);
-
-#define gen_handler_msg(stream, ...) \
- if (! settings.daemon) { \
- fprintf(stream, " %d: ", settings.handler_id); \
- fprintf(stream, __VA_ARGS__); \
- }
-
-#define handler_msg(...) gen_handler_msg(stdout, __VA_ARGS__);
-#define handler_emsg(...) gen_handler_msg(stderr, __VA_ARGS__);
-
diff --git a/utils/websockify b/utils/websockify
new file mode 100755
index 00000000..fed4c042
--- /dev/null
+++ b/utils/websockify
@@ -0,0 +1,308 @@
+#!/usr/bin/python
+
+'''
+A WebSocket to TCP socket proxy with support for "wss://" encryption.
+Copyright 2010 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 socket, optparse, time, os, sys, subprocess
+from select import select
+from websocket import WebSocketServer
+
+class WebSocketProxy(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
+
+ traffic_legend = """
+Traffic Legend:
+ } - Client receive
+ }. - Client receive partial
+ { - Target receive
+
+ > - Target send
+ >. - Target send partial
+ < - Client send
+ <. - Client send partial
+"""
+
+ def __init__(self, *args, **kwargs):
+ # Save off proxy specific options
+ self.target_host = kwargs.pop('target_host')
+ self.target_port = kwargs.pop('target_port')
+ self.wrap_cmd = kwargs.pop('wrap_cmd')
+ self.wrap_mode = kwargs.pop('wrap_mode')
+ # Last 3 timestamps command was run
+ self.wrap_times = [0, 0, 0]
+
+ if self.wrap_cmd:
+ rebinder_path = ['./', os.path.dirname(sys.argv[0])]
+ 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.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)})
+
+ WebSocketServer.__init__(self, *args, **kwargs)
+
+ def run_wrap_cmd(self):
+ print "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)
+ 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:
+ print " - proxying from %s:%s to '%s' (port %s)\n" % (
+ self.listen_host, self.listen_port,
+ " ".join(self.wrap_cmd), self.target_port)
+ 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):
+ # 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:
+ print "Command respawning too fast"
+ self.spawn_message = False
+ else:
+ self.run_wrap_cmd()
+
+ #
+ # Routines above this point are run in the master listener
+ # process.
+ #
+
+ #
+ # Routines below this point are connection handler routines and
+ # will be run in a separate forked process for each connection.
+ #
+
+ def new_client(self, client):
+ """
+ Called after a new WebSocket connection has been established.
+ """
+
+ self.rec = None
+ if self.record:
+ # Record raw frame data as a JavaScript compatible file
+ fname = "%s.%s" % (self.record,
+ self.handler_id)
+ self.msg("opening record file: %s" % fname)
+ self.rec = open(fname, 'w+')
+ self.rec.write("var VNC_frame_data = [\n")
+
+ # Connect to the target
+ self.msg("connecting to: %s:%s" % (
+ self.target_host, self.target_port))
+ tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ tsock.connect((self.target_host, self.target_port))
+
+ if self.verbose and not self.daemon:
+ print self.traffic_legend
+
+ # Stat proxying
+ try:
+ self.do_proxy(client, tsock)
+ except:
+ if tsock: tsock.close()
+ if self.rec:
+ self.rec.write("'EOF']\n")
+ self.rec.close()
+ raise
+
+ def do_proxy(self, client, target):
+ """
+ Proxy client WebSocket to normal target socket.
+ """
+ cqueue = []
+ cpartial = ""
+ tqueue = []
+ rlist = [client, target]
+ tstart = int(time.time()*1000)
+
+ while True:
+ wlist = []
+ tdelta = int(time.time()*1000) - tstart
+
+ if tqueue: wlist.append(target)
+ if cqueue: wlist.append(client)
+ ins, outs, excepts = select(rlist, wlist, [], 1)
+ if excepts: raise Exception("Socket exception")
+
+ if target in outs:
+ # Send queued client data to the target
+ dat = tqueue.pop(0)
+ sent = target.send(dat)
+ if sent == len(dat):
+ self.traffic(">")
+ else:
+ # requeue the remaining data
+ tqueue.insert(0, dat[sent:])
+ self.traffic(".>")
+
+ if client in outs:
+ # Send queued target data to the client
+ dat = cqueue.pop(0)
+ sent = client.send(dat)
+ if sent == len(dat):
+ self.traffic("<")
+ if self.rec:
+ self.rec.write("%s,\n" %
+ repr("{%s{" % tdelta + dat[1:-1]))
+ else:
+ cqueue.insert(0, dat[sent:])
+ self.traffic("<.")
+
+
+ if target in ins:
+ # Receive target data, encode it and queue for client
+ buf = target.recv(self.buffer_size)
+ if len(buf) == 0: raise self.EClose("Target closed")
+
+ cqueue.append(self.encode(buf))
+ self.traffic("{")
+
+ if client in ins:
+ # Receive client data, decode it, and queue for target
+ buf = client.recv(self.buffer_size)
+ if len(buf) == 0: raise self.EClose("Client closed")
+
+ if buf == '\xff\x00':
+ raise self.EClose("Client sent orderly close frame")
+ elif buf[-1] == '\xff':
+ if buf.count('\xff') > 1:
+ self.traffic(str(buf.count('\xff')))
+ self.traffic("}")
+ if self.rec:
+ self.rec.write("%s,\n" %
+ (repr("}%s}" % tdelta + buf[1:-1])))
+ if cpartial:
+ # Prepend saved partial and decode frame(s)
+ tqueue.extend(self.decode(cpartial + buf))
+ cpartial = ""
+ else:
+ # decode frame(s)
+ tqueue.extend(self.decode(buf))
+ else:
+ # Save off partial WebSockets frame
+ self.traffic(".}")
+ cpartial = cpartial + buf
+
+if __name__ == '__main__':
+ 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("--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].split(':')
+ 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].split(':')
+ 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()
diff --git a/utils/wsecho.html b/utils/wsecho.html
deleted file mode 100644
index 9e3c6d6c..00000000
--- a/utils/wsecho.html
+++ /dev/null
@@ -1,176 +0,0 @@
-
-
-
- WebSockets Echo Test
-
-
-
-
-
-
-
-
-
-
-
- Host:
- Port:
- Encrypt:
-
-
-
-
- Log:
-
-
-
-
-
-
-
diff --git a/utils/wsecho.py b/utils/wsecho.py
deleted file mode 100755
index 15e2ef75..00000000
--- a/utils/wsecho.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/bin/python
-
-'''
-A WebSocket server that echos back whatever it receives from the client.
-Copyright 2010 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 sys, socket, select
-from websocket import WebSocketServer
-
-class WebSocketEcho(WebSocketServer):
- """
- WebSockets server that echo back whatever is received from the
- client. All traffic to/from the client is base64
- encoded/decoded.
- """
- buffer_size = 8096
-
- def new_client(self, client):
- """
- Echo back whatever is received.
- """
-
- cqueue = []
- cpartial = ""
- rlist = [client]
-
- while True:
- wlist = []
-
- if cqueue: wlist.append(client)
- ins, outs, excepts = select.select(rlist, wlist, [], 1)
- if excepts: raise Exception("Socket exception")
-
- if client in outs:
- # Send queued target data to the client
- dat = cqueue.pop(0)
- sent = client.send(dat)
- self.vmsg("Sent %s/%s bytes of frame: '%s'" % (
- sent, len(dat), self.decode(dat)[0]))
- if sent != len(dat):
- # requeue the remaining data
- cqueue.insert(0, dat[sent:])
-
-
- if client in ins:
- # Receive client data, decode it, and send it back
- buf = client.recv(self.buffer_size)
- if len(buf) == 0: raise self.EClose("Client closed")
-
- if buf == '\xff\x00':
- raise self.EClose("Client sent orderly close frame")
- elif buf[-1] == '\xff':
- if cpartial:
- # Prepend saved partial and decode frame(s)
- frames = self.decode(cpartial + buf)
- cpartial = ""
- else:
- # decode frame(s)
- frames = self.decode(buf)
-
- for frame in frames:
- self.vmsg("Received frame: %s" % repr(frame))
- cqueue.append(self.encode(frame))
- else:
- # Save off partial WebSockets frame
- self.vmsg("Received partial frame")
- cpartial = cpartial + buf
-
-if __name__ == '__main__':
- try:
- if len(sys.argv) < 1: raise
- listen_port = int(sys.argv[1])
- except:
- print "Usage: %s " % sys.argv[0]
- sys.exit(1)
-
- server = WebSocketEcho(
- listen_port=listen_port,
- verbose=True,
- cert='self.pem',
- web='.')
- server.start_server()
-
diff --git a/utils/wsproxy.c b/utils/wsproxy.c
deleted file mode 100644
index 42bb45e7..00000000
--- a/utils/wsproxy.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * A WebSocket to TCP socket proxy with support for "wss://" encryption.
- * Copyright 2010 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
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "websocket.h"
-
-char traffic_legend[] = "\n\
-Traffic Legend:\n\
- } - Client receive\n\
- }. - Client receive partial\n\
- { - Target receive\n\
-\n\
- > - Target send\n\
- >. - Target send partial\n\
- < - Client send\n\
- <. - Client send partial\n\
-";
-
-char USAGE[] = "Usage: [options] " \
- "[source_addr:]source_port target_addr:target_port\n\n" \
- " --verbose|-v verbose messages and per frame traffic\n" \
- " --daemon|-D become a daemon (background process)\n" \
- " --cert CERT SSL certificate file\n" \
- " --key KEY SSL key file (if separate from cert)\n" \
- " --ssl-only disallow non-encrypted connections";
-
-#define usage(fmt, args...) \
- fprintf(stderr, "%s\n\n", USAGE); \
- fprintf(stderr, fmt , ## args); \
- exit(1);
-
-char target_host[256];
-int target_port;
-
-extern pipe_error;
-extern settings_t settings;
-extern char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp;
-extern unsigned int bufsize, dbufsize;
-
-void do_proxy(ws_ctx_t *ws_ctx, int target) {
- fd_set rlist, wlist, elist;
- struct timeval tv;
- int i, maxfd, client = ws_ctx->sockfd;
- unsigned int tstart, tend, cstart, cend, ret;
- ssize_t len, bytes;
-
- tstart = tend = cstart = cend = 0;
- maxfd = client > target ? client+1 : target+1;
-
- while (1) {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
-
- FD_ZERO(&rlist);
- FD_ZERO(&wlist);
- FD_ZERO(&elist);
-
- FD_SET(client, &elist);
- FD_SET(target, &elist);
-
- if (tend == tstart) {
- // Nothing queued for target, so read from client
- FD_SET(client, &rlist);
- } else {
- // Data queued for target, so write to it
- FD_SET(target, &wlist);
- }
- if (cend == cstart) {
- // Nothing queued for client, so read from target
- FD_SET(target, &rlist);
- } else {
- // Data queued for client, so write to it
- FD_SET(client, &wlist);
- }
-
- ret = select(maxfd, &rlist, &wlist, &elist, &tv);
- if (pipe_error) { break; }
-
- if (FD_ISSET(target, &elist)) {
- handler_emsg("target exception\n");
- break;
- }
- if (FD_ISSET(client, &elist)) {
- handler_emsg("client exception\n");
- break;
- }
-
- if (ret == -1) {
- handler_emsg("select(): %s\n", strerror(errno));
- break;
- } else if (ret == 0) {
- //handler_emsg("select timeout\n");
- continue;
- }
-
- if (FD_ISSET(target, &wlist)) {
- len = tend-tstart;
- bytes = send(target, tbuf + tstart, len, 0);
- if (pipe_error) { break; }
- if (bytes < 0) {
- handler_emsg("target connection error: %s\n",
- strerror(errno));
- break;
- }
- tstart += bytes;
- if (tstart >= tend) {
- tstart = tend = 0;
- traffic(">");
- } else {
- traffic(">.");
- }
- }
-
- if (FD_ISSET(client, &wlist)) {
- len = cend-cstart;
- bytes = ws_send(ws_ctx, cbuf + cstart, len);
- if (pipe_error) { break; }
- if (len < 3) {
- handler_emsg("len: %d, bytes: %d: %d\n", len, bytes, *(cbuf + cstart));
- }
- cstart += bytes;
- if (cstart >= cend) {
- cstart = cend = 0;
- traffic("<");
- } else {
- traffic("<.");
- }
- }
-
- if (FD_ISSET(target, &rlist)) {
- bytes = recv(target, cbuf_tmp, dbufsize , 0);
- if (pipe_error) { break; }
- if (bytes <= 0) {
- handler_emsg("target closed connection\n");
- break;
- }
- cstart = 0;
- cend = encode(cbuf_tmp, bytes, cbuf, bufsize);
- /*
- printf("encoded: ");
- for (i=0; i< cend; i++) {
- printf("%u,", (unsigned char) *(cbuf+i));
- }
- printf("\n");
- */
- if (cend < 0) {
- handler_emsg("encoding error\n");
- break;
- }
- traffic("{");
- }
-
- if (FD_ISSET(client, &rlist)) {
- bytes = ws_recv(ws_ctx, tbuf_tmp, bufsize-1);
- if (pipe_error) { break; }
- if (bytes <= 0) {
- handler_emsg("client closed connection\n");
- break;
- } else if ((bytes == 2) &&
- (tbuf_tmp[0] == '\xff') &&
- (tbuf_tmp[1] == '\x00')) {
- handler_emsg("client sent orderly close frame\n");
- break;
- }
- /*
- printf("before decode: ");
- for (i=0; i< bytes; i++) {
- printf("%u,", (unsigned char) *(tbuf_tmp+i));
- }
- printf("\n");
- */
- len = decode(tbuf_tmp, bytes, tbuf, bufsize-1);
- /*
- printf("decoded: ");
- for (i=0; i< len; i++) {
- printf("%u,", (unsigned char) *(tbuf+i));
- }
- printf("\n");
- */
- if (len < 0) {
- handler_emsg("decoding error\n");
- break;
- }
- traffic("}");
- tstart = 0;
- tend = len;
- }
- }
-}
-
-void proxy_handler(ws_ctx_t *ws_ctx) {
- int tsock = 0;
- struct sockaddr_in taddr;
-
- handler_msg("connecting to: %s:%d\n", target_host, target_port);
-
- tsock = socket(AF_INET, SOCK_STREAM, 0);
- if (tsock < 0) {
- handler_emsg("Could not create target socket: %s\n",
- strerror(errno));
- return;
- }
- bzero((char *) &taddr, sizeof(taddr));
- taddr.sin_family = AF_INET;
- taddr.sin_port = htons(target_port);
-
- /* Resolve target address */
- if (resolve_host(&taddr.sin_addr, target_host) < -1) {
- handler_emsg("Could not resolve target address: %s\n",
- strerror(errno));
- }
-
- if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) {
- handler_emsg("Could not connect to target: %s\n",
- strerror(errno));
- close(tsock);
- return;
- }
-
- if ((settings.verbose) && (! settings.daemon)) {
- printf("%s", traffic_legend);
- }
-
- do_proxy(ws_ctx, tsock);
-
- close(tsock);
-}
-
-int main(int argc, char *argv[])
-{
- int fd, c, option_index = 0;
- static int ssl_only = 0, daemon = 0, verbose = 0;
- char *found;
- static struct option long_options[] = {
- {"verbose", no_argument, &verbose, 'v'},
- {"ssl-only", no_argument, &ssl_only, 1 },
- {"daemon", no_argument, &daemon, 'D'},
- /* ---- */
- {"cert", required_argument, 0, 'c'},
- {"key", required_argument, 0, 'k'},
- {0, 0, 0, 0}
- };
-
- settings.cert = realpath("self.pem", NULL);
- if (!settings.cert) {
- /* Make sure it's always set to something */
- settings.cert = "self.pem";
- }
- settings.key = "";
-
- while (1) {
- c = getopt_long (argc, argv, "vDc:k:",
- long_options, &option_index);
-
- /* Detect the end */
- if (c == -1) { break; }
-
- switch (c) {
- case 0:
- break; // ignore
- case 1:
- break; // ignore
- case 'v':
- verbose = 1;
- break;
- case 'D':
- daemon = 1;
- break;
- case 'c':
- settings.cert = realpath(optarg, NULL);
- if (! settings.cert) {
- usage("No cert file at %s\n", optarg);
- }
- break;
- case 'k':
- settings.key = realpath(optarg, NULL);
- if (! settings.key) {
- usage("No key file at %s\n", optarg);
- }
- break;
- default:
- usage("");
- }
- }
- settings.verbose = verbose;
- settings.ssl_only = ssl_only;
- settings.daemon = daemon;
-
- if ((argc-optind) != 2) {
- usage("Invalid number of arguments\n");
- }
-
- found = strstr(argv[optind], ":");
- if (found) {
- memcpy(settings.listen_host, argv[optind], found-argv[optind]);
- settings.listen_port = strtol(found+1, NULL, 10);
- } else {
- settings.listen_host[0] = '\0';
- settings.listen_port = strtol(argv[optind], NULL, 10);
- }
- optind++;
- if (settings.listen_port == 0) {
- usage("Could not parse listen_port\n");
- }
-
- found = strstr(argv[optind], ":");
- if (found) {
- memcpy(target_host, argv[optind], found-argv[optind]);
- target_port = strtol(found+1, NULL, 10);
- } else {
- usage("Target argument must be host:port\n");
- }
- if (target_port == 0) {
- usage("Could not parse target port\n");
- }
-
- if (ssl_only) {
- if (!access(settings.cert, R_OK)) {
- usage("SSL only and cert file '%s' not found\n", settings.cert);
- }
- } else if (access(settings.cert, R_OK) != 0) {
- fprintf(stderr, "Warning: '%s' not found\n", settings.cert);
- }
-
- //printf(" verbose: %d\n", settings.verbose);
- //printf(" ssl_only: %d\n", settings.ssl_only);
- //printf(" daemon: %d\n", settings.daemon);
- //printf(" cert: %s\n", settings.cert);
- //printf(" key: %s\n", settings.key);
-
- settings.handler = proxy_handler;
- start_server();
-
- free(tbuf);
- free(cbuf);
- free(tbuf_tmp);
- free(cbuf_tmp);
-}
diff --git a/utils/wsproxy.js b/utils/wsproxy.js
deleted file mode 100644
index c85c506d..00000000
--- a/utils/wsproxy.js
+++ /dev/null
@@ -1,253 +0,0 @@
-// A WebSocket to TCP socket proxy
-// Copyright 2010 Joel Martin
-// Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
-
-var net = require('net'),
- sys = require('sys'),
- crypto = require('crypto'),
- source_arg, source_host, source_port,
- target_arg, target_host, target_port;
-
-// md5 calculation borrowed from Socket.IO (MIT license)
-function gen_md5(headers, k3) {
- var k1 = headers['sec-websocket-key1'],
- k2 = headers['sec-websocket-key2'],
- md5 = crypto.createHash('md5');
-
- [k1, k2].forEach(function(k){
- var n = parseInt(k.replace(/[^\d]/g, '')),
- spaces = k.replace(/[^ ]/g, '').length;
-
- if (spaces === 0 || n % spaces !== 0){
- return false;
- }
-
- n /= spaces;
-
- md5.update(String.fromCharCode(
- n >> 24 & 0xFF,
- n >> 16 & 0xFF,
- n >> 8 & 0xFF,
- n & 0xFF));
- });
-
- md5.update(k3.toString('binary'));
-
- return md5.digest('binary');
-}
-
-function encode(buf) {
- return String.fromCharCode(0) +
- buf.toString('base64', 0) +
- String.fromCharCode(255);
-}
-
-function decode(data) {
- var i, len = 0, strs, retstrs = [],
- buf = new Buffer(data.length),
- str = data.toString('binary', 1, data.length-1);
-
- if (str.indexOf('\xff') > -1) {
- // We've gotten multiple frames at once
- strs = str.split('\xff\x00')
- for (i = 0; i < strs.length; i++) {
- len = buf.write(strs[i], 0, 'base64');
- retstrs.push(buf.toString('binary', 0, len));
- }
- return retstrs.join("");
- } else {
- len = buf.write(str, 0, 'base64');
- return buf.toString('binary', 0, len);
- }
-}
-
-
-var server = net.createServer(function (client) {
- var handshake = "", headers = {}, header,
- version, path, k1, k2, k3, target = null;
-
- function cleanup() {
- client.end();
- if (target) {
- target.end();
- target = null;
- }
- }
-
- function do_handshake(data) {
- var i, idx, dlen = data.length, lines, location, rheaders,
- sec_hdr;
- //sys.log("received handshake data: " + data);
- handshake += data.toString('utf8');
- if ((data[dlen-12] != 13) ||
- (data[dlen-11] != 10) ||
- (data[dlen-10] != 13) ||
- (data[dlen-9] != 10)) {
- //sys.log("Got partial handshake");
- return;
- }
- //sys.log("Got whole handshake");
-
- if (handshake.indexOf('GET ') != 0) {
- sys.error("Got invalid handshake");
- client.end();
- return;
- }
-
- lines = handshake.split('\r\n');
- path = lines[0].split(' ')[1];
- //sys.log("path: " + path);
-
- k3 = data.slice(dlen-8, dlen);
- for (i = 1; i < lines.length; i++) {
- //sys.log("lines[i]: " + lines[i]);
- if (lines[i].length == 0) { break; }
- idx = lines[i].indexOf(': ');
- if (idx < 0) {
- sys.error("Got invalid handshake header");
- client.end();
- return;
- }
- header = lines[i].slice(0, idx).toLowerCase();
- headers[header] = lines[i].slice(idx+2);
- }
- //console.dir(headers);
- //sys.log("k3: " + k3 + ", k3.length: " + k3.length);
-
- if (headers.upgrade !== 'WebSocket') {
- sys.error("Upgrade header is not 'WebSocket'");
- client.end();
- return;
- }
-
- location = (headers.origin.substr(0, 5) == 'https' ? 'wss' : 'ws')
- + '://' + headers.host + path;
- //sys.log("location: " + location);
-
- if ('sec-websocket-key1' in headers) {
- version = 76;
- sec_hdr = "Sec-";
- } else {
- version = 75;
- sec_hdr = "";
- }
- sys.log("using protocol version " + version);
-
- rheaders = [
- 'HTTP/1.1 101 WebSocket Protocol Handshake',
- 'Upgrade: WebSocket',
- 'Connection: Upgrade',
- sec_hdr + 'WebSocket-Origin: ' + headers.origin,
- sec_hdr + 'WebSocket-Location: ' + location
- ];
- if ('sec-websocket-protocol' in headers) {
- rheaders.push('Sec-WebSocket-Protocol: ' + headers['sec-websocket-protocol']);
- }
- rheaders.push('');
- if (version === 76) {
- rheaders.push(gen_md5(headers, k3));
- }
-
- // Switch listener to normal data path
- client.on('data', client_data);
- //client.setEncoding('utf8');
- client.removeListener('data', do_handshake);
- // Do not delay writes
- client.setNoDelay(true);
-
- // Send the handshake response
- try {
- //sys.log("response: " + rheaders.join('\r\n'));
- client.write(rheaders.join('\r\n'), 'binary');
- } catch(e) {
- sys.error("Failed to send handshake response");
- client.end();
- return;
- }
-
- // Create a connection to the target
- target = net.createConnection(target_port, target_host);
- target.on('data', target_data);
- target.on('end', function () {
- sys.log("received target end");
- cleanup();
- });
- target.on('error', function (exc) {
- sys.log("received target error: " + exc);
- cleanup();
- });
- }
-
- function client_data(data) {
- var ret;
- //sys.log("received client data: " + data);
- //sys.log(" decoded: " + decode(data));
- try {
- ret = target.write(decode(data), 'binary');
- if (! ret) {
- sys.log("target write returned false");
- }
- } catch(e) {
- sys.log("fatal error writing to target");
- cleanup();
- }
- }
-
- function target_data(data) {
- //sys.log("received target data: " + data);
- //sys.log(" encoded: " + encode(data));
- try {
- client.write(encode(data), 'binary');
- } catch(e) {
- sys.log("fatal error writing to client");
- cleanup();
- }
- }
-
- client.on('connect', function () {
- sys.log("Got client connection");
- });
- client.on('data', do_handshake);
- client.on('end', function () {
- sys.log("recieved client end");
- cleanup();
- });
- client.on('error', function (exc) {
- sys.log("recieved client error: " + exc);
- cleanup();
- });
-});
-
-
-// parse source and target into parts
-source_arg = process.argv[2];
-target_arg = process.argv[3];
-try {
- var idx;
- idx = source_arg.indexOf(":");
- if (idx >= 0) {
- source_host = source_arg.slice(0, idx);
- source_port = parseInt(source_arg.slice(idx+1), 10);
- } else {
- source_host = "";
- source_port = parseInt(source_arg, 10);
- }
-
- idx = target_arg.indexOf(":");
- if (idx < 0) {
- throw("target must be host:port");
- }
- target_host = target_arg.slice(0, idx);
- target_port = parseInt(target_arg.slice(idx+1), 10);
-
- if (isNaN(source_port) || isNaN(target_port)) {
- throw("illegal port");
- }
-} catch(e) {
- console.error("wsproxy.py [source_addr:]source_port target_addr:target_port");
- process.exit(2);
-}
-
-sys.log("source: " + source_host + ":" + source_port);
-sys.log("target: " + target_host + ":" + target_port);
-server.listen(source_port, source_host);
diff --git a/utils/wsproxy.py b/utils/wsproxy.py
deleted file mode 100755
index fed4c042..00000000
--- a/utils/wsproxy.py
+++ /dev/null
@@ -1,308 +0,0 @@
-#!/usr/bin/python
-
-'''
-A WebSocket to TCP socket proxy with support for "wss://" encryption.
-Copyright 2010 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 socket, optparse, time, os, sys, subprocess
-from select import select
-from websocket import WebSocketServer
-
-class WebSocketProxy(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
-
- traffic_legend = """
-Traffic Legend:
- } - Client receive
- }. - Client receive partial
- { - Target receive
-
- > - Target send
- >. - Target send partial
- < - Client send
- <. - Client send partial
-"""
-
- def __init__(self, *args, **kwargs):
- # Save off proxy specific options
- self.target_host = kwargs.pop('target_host')
- self.target_port = kwargs.pop('target_port')
- self.wrap_cmd = kwargs.pop('wrap_cmd')
- self.wrap_mode = kwargs.pop('wrap_mode')
- # Last 3 timestamps command was run
- self.wrap_times = [0, 0, 0]
-
- if self.wrap_cmd:
- rebinder_path = ['./', os.path.dirname(sys.argv[0])]
- 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.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)})
-
- WebSocketServer.__init__(self, *args, **kwargs)
-
- def run_wrap_cmd(self):
- print "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)
- 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:
- print " - proxying from %s:%s to '%s' (port %s)\n" % (
- self.listen_host, self.listen_port,
- " ".join(self.wrap_cmd), self.target_port)
- 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):
- # 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:
- print "Command respawning too fast"
- self.spawn_message = False
- else:
- self.run_wrap_cmd()
-
- #
- # Routines above this point are run in the master listener
- # process.
- #
-
- #
- # Routines below this point are connection handler routines and
- # will be run in a separate forked process for each connection.
- #
-
- def new_client(self, client):
- """
- Called after a new WebSocket connection has been established.
- """
-
- self.rec = None
- if self.record:
- # Record raw frame data as a JavaScript compatible file
- fname = "%s.%s" % (self.record,
- self.handler_id)
- self.msg("opening record file: %s" % fname)
- self.rec = open(fname, 'w+')
- self.rec.write("var VNC_frame_data = [\n")
-
- # Connect to the target
- self.msg("connecting to: %s:%s" % (
- self.target_host, self.target_port))
- tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- tsock.connect((self.target_host, self.target_port))
-
- if self.verbose and not self.daemon:
- print self.traffic_legend
-
- # Stat proxying
- try:
- self.do_proxy(client, tsock)
- except:
- if tsock: tsock.close()
- if self.rec:
- self.rec.write("'EOF']\n")
- self.rec.close()
- raise
-
- def do_proxy(self, client, target):
- """
- Proxy client WebSocket to normal target socket.
- """
- cqueue = []
- cpartial = ""
- tqueue = []
- rlist = [client, target]
- tstart = int(time.time()*1000)
-
- while True:
- wlist = []
- tdelta = int(time.time()*1000) - tstart
-
- if tqueue: wlist.append(target)
- if cqueue: wlist.append(client)
- ins, outs, excepts = select(rlist, wlist, [], 1)
- if excepts: raise Exception("Socket exception")
-
- if target in outs:
- # Send queued client data to the target
- dat = tqueue.pop(0)
- sent = target.send(dat)
- if sent == len(dat):
- self.traffic(">")
- else:
- # requeue the remaining data
- tqueue.insert(0, dat[sent:])
- self.traffic(".>")
-
- if client in outs:
- # Send queued target data to the client
- dat = cqueue.pop(0)
- sent = client.send(dat)
- if sent == len(dat):
- self.traffic("<")
- if self.rec:
- self.rec.write("%s,\n" %
- repr("{%s{" % tdelta + dat[1:-1]))
- else:
- cqueue.insert(0, dat[sent:])
- self.traffic("<.")
-
-
- if target in ins:
- # Receive target data, encode it and queue for client
- buf = target.recv(self.buffer_size)
- if len(buf) == 0: raise self.EClose("Target closed")
-
- cqueue.append(self.encode(buf))
- self.traffic("{")
-
- if client in ins:
- # Receive client data, decode it, and queue for target
- buf = client.recv(self.buffer_size)
- if len(buf) == 0: raise self.EClose("Client closed")
-
- if buf == '\xff\x00':
- raise self.EClose("Client sent orderly close frame")
- elif buf[-1] == '\xff':
- if buf.count('\xff') > 1:
- self.traffic(str(buf.count('\xff')))
- self.traffic("}")
- if self.rec:
- self.rec.write("%s,\n" %
- (repr("}%s}" % tdelta + buf[1:-1])))
- if cpartial:
- # Prepend saved partial and decode frame(s)
- tqueue.extend(self.decode(cpartial + buf))
- cpartial = ""
- else:
- # decode frame(s)
- tqueue.extend(self.decode(buf))
- else:
- # Save off partial WebSockets frame
- self.traffic(".}")
- cpartial = cpartial + buf
-
-if __name__ == '__main__':
- 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("--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].split(':')
- 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].split(':')
- 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()
diff --git a/utils/wsproxy.py b/utils/wsproxy.py
new file mode 120000
index 00000000..05b5af45
--- /dev/null
+++ b/utils/wsproxy.py
@@ -0,0 +1 @@
+websockify
\ No newline at end of file
diff --git a/utils/wstelnet.html b/utils/wstelnet.html
deleted file mode 100644
index 73802484..00000000
--- a/utils/wstelnet.html
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
- Telnet Client using WebSockets
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Host:
- Port:
- Encrypt:
-
-
-
-
-
-
-
-
-
-
-
diff --git a/utils/wstelnet.js b/utils/wstelnet.js
deleted file mode 100644
index 2f4ab0e5..00000000
--- a/utils/wstelnet.js
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * WebSockets telnet client
- * Copyright (C) 2011 Joel Martin
- * Licensed under LGPL-3 (see LICENSE.txt)
- *
- * Includes VT100.js from:
- * http://code.google.com/p/sshconsole
- * Which was modified from:
- * http://fzort.org/bi/o.php#vt100_js
- *
- * Telnet protocol:
- * http://www.networksorcery.com/enp/protocol/telnet.htm
- * http://www.networksorcery.com/enp/rfc/rfc1091.txt
- *
- * ANSI escape sequeneces:
- * http://en.wikipedia.org/wiki/ANSI_escape_code
- * http://ascii-table.com/ansi-escape-sequences-vt-100.php
- * http://www.termsys.demon.co.uk/vtansi.htm
- * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
- *
- * ASCII codes:
- * http://en.wikipedia.org/wiki/ASCII
- * http://www.hobbyprojects.com/ascii-table/ascii-table.html
- *
- * Other web consoles:
- * http://stackoverflow.com/questions/244750/ajax-console-window-with-ansi-vt100-support
- */
-
-
-
-
-function Telnet(target, connect_callback, disconnect_callback) {
-
-var that = {}, // Public API interface
- vt100, ws, sQ = [];
- termType = "VT100";
-
-
-Array.prototype.pushStr = function (str) {
- var n = str.length;
- for (var i=0; i < n; i++) {
- this.push(str.charCodeAt(i));
- }
-}
-
-function do_send() {
- if (sQ.length > 0) {
- Util.Debug("Sending " + sQ);
- ws.send(Base64.encode(sQ));
- sQ = [];
- }
-}
-
-function do_recv(e) {
- //console.log(">> do_recv");
- var arr = Base64.decode(e.data), str = "",
- chr, cmd, code, value;
-
- Util.Debug("Received array '" + arr + "'");
- while (arr.length > 0) {
- chr = arr.shift();
- switch (chr) {
- case 255: // IAC
- cmd = chr;
- code = arr.shift();
- value = arr.shift();
- switch (code) {
- case 254: // DONT
- Util.Debug("Got Cmd DONT '" + value + "', ignoring");
- break;
- case 253: // DO
- Util.Debug("Got Cmd DO '" + value + "'");
- if (value === 24) {
- // Terminal type
- Util.Info("Send WILL '" + value + "' (TERM-TYPE)");
- sQ.push(255, 251, value);
- } else {
- // Refuse other DO requests with a WONT
- Util.Debug("Send WONT '" + value + "'");
- sQ.push(255, 252, value);
- }
- break;
- case 252: // WONT
- Util.Debug("Got Cmd WONT '" + value + "', ignoring");
- break;
- case 251: // WILL
- Util.Debug("Got Cmd WILL '" + value + "'");
- if (value === 1) {
- // Affirm echo with DO
- Util.Info("Send Cmd DO '" + value + "' (echo)");
- sQ.push(255, 253, value);
- } else {
- // Reject other WILL offers with a DONT
- Util.Debug("Send Cmd DONT '" + value + "'");
- sQ.push(255, 254, value);
- }
- break;
- case 250: // SB (subnegotiation)
- if (value === 24) {
- Util.Info("Got IAC SB TERM-TYPE SEND(1) IAC SE");
- // TERM-TYPE subnegotiation
- if (arr[0] === 1 &&
- arr[1] === 255 &&
- arr[2] === 240) {
- arr.shift(); arr.shift(); arr.shift();
- Util.Info("Send IAC SB TERM-TYPE IS(0) '" +
- termType + "' IAC SE");
- sQ.push(255, 250, 24, 0);
- sQ.pushStr(termType);
- sQ.push(255, 240);
- } else {
- Util.Info("Invalid subnegotiation received" + arr);
- }
- } else {
- Util.Info("Ignoring SB " + value);
- }
- break;
- default:
- Util.Info("Got Cmd " + cmd + " " + value + ", ignoring"); }
- continue;
- case 242: // Data Mark (Synch)
- cmd = chr;
- code = arr.shift();
- value = arr.shift();
- Util.Info("Ignoring Data Mark (Synch)");
- break;
- default: // everything else
- str += String.fromCharCode(chr);
- }
- }
-
- if (sQ) {
- do_send();
- }
-
- if (str) {
- vt100.write(str);
- }
-
- //console.log("<< do_recv");
-}
-
-
-
-that.connect = function(host, port, encrypt) {
- var host = host,
- port = port,
- scheme = "ws://", uri;
-
- Util.Debug(">> connect");
- if ((!host) || (!port)) {
- console.log("must set host and port");
- return;
- }
-
- if (ws) {
- ws.close();
- }
-
- if (encrypt) {
- scheme = "wss://";
- }
- uri = scheme + host + ":" + port;
- Util.Info("connecting to " + uri);
- ws = new WebSocket(uri);
-
- ws.onmessage = do_recv;
-
- ws.onopen = function(e) {
- Util.Info(">> WebSockets.onopen");
- vt100.curs_set(true, true);
- connect_callback();
- Util.Info("<< WebSockets.onopen");
- };
- ws.onclose = function(e) {
- Util.Info(">> WebSockets.onclose");
- that.disconnect();
- Util.Info("<< WebSockets.onclose");
- };
- ws.onerror = function(e) {
- Util.Info(">> WebSockets.onerror");
- that.disconnect();
- Util.Info("<< WebSockets.onerror");
- };
-
- Util.Debug("<< connect");
-}
-
-that.disconnect = function() {
- Util.Debug(">> disconnect");
- if (ws) {
- ws.close();
- }
- vt100.curs_set(true, false);
-
- disconnect_callback();
- Util.Debug("<< disconnect");
-}
-
-
-function constructor() {
- /* Initialize the terminal emulator/renderer */
-
- vt100 = new VT100(80, 24, target);
-
- // Turn off local echo
- vt100.noecho();
-
-
- /*
- * Override VT100 I/O routines
- */
-
- // Set handler for sending characters
- vt100.getch(
- function send_chr(chr, vt) {
- var i;
- Util.Debug(">> send_chr: " + chr);
- for (i = 0; i < chr.length; i++) {
- sQ.push(chr.charCodeAt(i));
- }
- do_send();
- vt100.getch(send_chr);
- }
- );
-
- vt100.debug = function(message) {
- Util.Debug(message + "\n");
- }
-
- vt100.warn = function(message) {
- Util.Warn(message + "\n");
- }
-
- vt100.curs_set = function(vis, grab, eventist)
- {
- this.debug("curs_set:: vis: " + vis + ", grab: " + grab);
- if (vis !== undefined)
- this.cursor_vis_ = (vis > 0);
- if (eventist === undefined)
- eventist = window;
- if (grab === true || grab === false) {
- if (grab === this.grab_events_)
- return;
- if (grab) {
- this.grab_events_ = true;
- VT100.the_vt_ = this;
- Util.addEvent(eventist, 'keydown', vt100.key_down);
- Util.addEvent(eventist, 'keyup', vt100.key_up);
- } else {
- Util.removeEvent(eventist, 'keydown', vt100.key_down);
- Util.removeEvent(eventist, 'keyup', vt100.key_up);
- this.grab_events_ = false;
- VT100.the_vt_ = undefined;
- }
- }
- }
-
- vt100.key_down = function(e) {
- var vt = VT100.the_vt_, keysym, ch, str = "";
-
- if (vt === undefined)
- return true;
-
- keysym = getKeysym(e);
-
- if (keysym < 128) {
- if (e.ctrlKey) {
- if (keysym == 64) {
- // control 0
- ch = 0;
- } else if ((keysym >= 97) && (keysym <= 122)) {
- // control codes 1-26
- ch = keysym - 96;
- } else if ((keysym >= 91) && (keysym <= 95)) {
- // control codes 27-31
- ch = keysym - 64;
- } else {
- Util.Info("Debug unknown control keysym: " + keysym);
- }
- } else {
- ch = keysym;
- }
- str = String.fromCharCode(ch);
- } else {
- switch (keysym) {
- case 65505: // Shift, do not send directly
- break;
- case 65507: // Ctrl, do not send directly
- break;
- case 65293: // Carriage return, line feed
- str = '\n'; break;
- case 65288: // Backspace
- str = '\b'; break;
- case 65307: // Escape
- str = '\x1b'; break;
- case 65361: // Left arrow
- str = '\x1b[D'; break;
- case 65362: // Up arrow
- str = '\x1b[A'; break;
- case 65363: // Right arrow
- str = '\x1b[C'; break;
- case 65364: // Down arrow
- str = '\x1b[B'; break;
- default:
- Util.Info("Unrecoginized keysym " + keysym);
- }
- }
-
- if (str) {
- vt.key_buf_.push(str);
- setTimeout(VT100.go_getch_, 0);
- }
-
- Util.stopEvent(e);
- return false;
- }
-
- vt100.key_up = function(e) {
- var vt = VT100.the_vt_;
- if (vt === undefined)
- return true;
- Util.stopEvent(e);
- return false;
- }
-
-
- return that;
-}
-
-return constructor(); // Return the public API interface
-
-} // End of Telnet()
diff --git a/utils/wstest.html b/utils/wstest.html
deleted file mode 100644
index c56c4c72..00000000
--- a/utils/wstest.html
+++ /dev/null
@@ -1,252 +0,0 @@
-
-
-
- WebSockets Test
-
-
-
-
-
-
-
-
-
-
-
- Host:
- Port:
- Encrypt:
- Send Delay (ms):
-
-
-
-
-
-
Packets sent:
-
0
-
-
Good Packets Received:
-
0
-
-
Errors (Bad Packets Received:)
-
0
-
-
-
-
- Errors:
-
-
-
-
-
-
-
diff --git a/utils/wstest.py b/utils/wstest.py
deleted file mode 100755
index 9442b04c..00000000
--- a/utils/wstest.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/python
-
-'''
-WebSocket server-side load test program. Sends and receives traffic
-that has a random payload (length and content) that is checksummed and
-given a sequence number. Any errors are reported and counted.
-'''
-
-import sys, os, socket, ssl, time, traceback
-import random, time
-from select import select
-
-sys.path.insert(0,os.path.dirname(__file__) + "/../utils/")
-from websocket import WebSocketServer
-
-
-class WebSocketTest(WebSocketServer):
-
- buffer_size = 65536
- max_packet_size = 10000
- recv_cnt = 0
- send_cnt = 0
-
- def __init__(self, *args, **kwargs):
- self.errors = 0
- self.delay = kwargs.pop('delay')
-
- print "Prepopulating random array"
- self.rand_array = []
- for i in range(0, self.max_packet_size):
- self.rand_array.append(random.randint(0, 9))
-
- WebSocketServer.__init__(self, *args, **kwargs)
-
- def new_client(self, client):
- self.send_cnt = 0
- self.recv_cnt = 0
-
- try:
- self.responder(client)
- except:
- print "accumulated errors:", self.errors
- self.errors = 0
- raise
-
- def responder(self, client):
- cqueue = []
- cpartial = ""
- socks = [client]
- last_send = time.time() * 1000
-
- while True:
- ins, outs, excepts = select(socks, socks, socks, 1)
- if excepts: raise Exception("Socket exception")
-
- if client in ins:
- buf = client.recv(self.buffer_size)
- if len(buf) == 0:
- raise self.EClose("Client closed")
- #print "Client recv: %s (%d)" % (repr(buf[1:-1]), len(buf))
- if buf[-1] == '\xff':
- if cpartial:
- err = self.check(cpartial + buf)
- cpartial = ""
- else:
- err = self.check(buf)
- if err:
- self.traffic("}")
- self.errors = self.errors + 1
- print err
- else:
- self.traffic(">")
- else:
- self.traffic(".>")
- cpartial = cpartial + buf
-
- now = time.time() * 1000
- if client in outs and now > (last_send + self.delay):
- last_send = now
- #print "Client send: %s" % repr(cqueue[0])
- client.send(self.generate())
- self.traffic("<")
-
- def generate(self):
- length = random.randint(10, self.max_packet_size)
- numlist = self.rand_array[self.max_packet_size-length:]
- # Error in length
- #numlist.append(5)
- chksum = sum(numlist)
- # Error in checksum
- #numlist[0] = 5
- nums = "".join( [str(n) for n in numlist] )
- data = "^%d:%d:%d:%s$" % (self.send_cnt, length, chksum, nums)
- self.send_cnt += 1
-
- return WebSocketServer.encode(data)
-
-
- def check(self, buf):
- try:
- data_list = WebSocketServer.decode(buf)
- except:
- print "\n" + repr(buf) + ""
- return "Failed to decode"
-
- err = ""
- for data in data_list:
- if data.count('$') > 1:
- raise Exception("Multiple parts within single packet")
- if len(data) == 0:
- self.traffic("_")
- continue
-
- if data[0] != "^":
- err += "buf did not start with '^'\n"
- continue
-
- try:
- cnt, length, chksum, nums = data[1:-1].split(':')
- cnt = int(cnt)
- length = int(length)
- chksum = int(chksum)
- except:
- print "\n" + repr(data) + ""
- err += "Invalid data format\n"
- continue
-
- if self.recv_cnt != cnt:
- err += "Expected count %d but got %d\n" % (self.recv_cnt, cnt)
- self.recv_cnt = cnt + 1
- continue
-
- self.recv_cnt += 1
-
- if len(nums) != length:
- err += "Expected length %d but got %d\n" % (length, len(nums))
- continue
-
- inv = nums.translate(None, "0123456789")
- if inv:
- err += "Invalid characters found: %s\n" % inv
- continue
-
- real_chksum = 0
- for num in nums:
- real_chksum += int(num)
-
- if real_chksum != chksum:
- err += "Expected checksum %d but real chksum is %d\n" % (chksum, real_chksum)
- return err
-
-
-if __name__ == '__main__':
- try:
- if len(sys.argv) < 2: raise
- listen_port = int(sys.argv[1])
- if len(sys.argv) == 3:
- delay = int(sys.argv[2])
- else:
- delay = 10
- except:
- print "Usage: %s [delay_ms]" % sys.argv[0]
- sys.exit(1)
-
- server = WebSocketTest(
- listen_port=listen_port,
- verbose=True,
- cert='self.pem',
- web='.',
- delay=delay)
- server.start_server()
diff --git a/utils/wswrap b/utils/wswrap
deleted file mode 100755
index 565d8ed3..00000000
--- a/utils/wswrap
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-usage() {
- echo "Usage: $(basename $0) PORT CMDLINE"
- echo
- echo " PORT Port to wrap with WebSockets support"
- echo " CMDLINE Command line to wrap"
- exit 2
-}
-
-# Parameter defaults
-mydir=$(readlink -f $(dirname ${0}))
-
-# Process parameters
-#while [ "${1}" != "${1#-}" ]; do
-# param=$1; shift
-#done
-
-export WSWRAP_PORT="${1}"; shift
-
-LD_PRELOAD=${mydir}/wswrapper.so "${@}"
-
diff --git a/utils/wswrapper.c b/utils/wswrapper.c
deleted file mode 100644
index bd4e6f06..00000000
--- a/utils/wswrapper.c
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * wswrap/wswrapper: Add WebSockets support to any service.
- * Copyright 2010 Joel Martin
- * Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
- *
- * wswrapper is an LD_PRELOAD library that converts a TCP listen socket of an
- * existing program to a be a WebSockets socket. The `wswrap` script can be
- * used to easily launch a program using wswrapper. Here is an example of
- * using wswrapper with vncserver. wswrapper will convert the socket listening
- * on port 5901 to be a WebSockets port:
- *
- * cd noVNC/utils
- * ./wswrap 5901 vncserver -geometry 640x480 :1
- *
- * This is tricky a subtle process so there are some serious limitations:
- * - multi-threaded programs may not work
- * - programs that fork may behave in strange and mysterious ways (such as
- * fork bombing your system)
- * - programs using ppoll or epoll will not work correctly
- * - doesn't support fopencookie, streams, putc, etc.
- *
- * **********************************************************************
- * WARNING:
- * Due to the above limitations, this code should be considered an experiment
- * only. Consider using the program wrap mode of wsproxy.py instead.
- * **********************************************************************
- */
-
-#define DO_MSG 1
-#define DO_DEBUG 1
-#define DO_TRACE 1
-
-#include
-#include
-
-#define __USE_GNU 1 // Pull in RTLD_NEXT
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include /* base64 encode/decode */
-#include
-#include "md5.h"
-#include "wswrapper.h"
-
-/*
- * If WSWRAP_PORT environment variable is set then listen to the bind fd that
- * matches WSWRAP_PORT
- */
-int _WS_listen_fd = -1;
-int _WS_nfds = 0;
-int _WS_fds[WS_MAX_FDS];
-_WS_connection *_WS_connections[65536];
-
-
-/*
- * Utillity routines
- */
-
-/*
- * Subtract the `struct timeval' values X and Y, storing the
- * result in RESULT. If TS is set then RESULT and X are really
- * type-cast `struct timespec` so scale them appropriately.
- * Return 1 if the difference is negative or 0, otherwise 0.
- */
-int _WS_subtract_time (result, x, y, ts)
- struct timeval *result, *x, *y;
-{
- int scale = ts ? 1000 : 1;
- /* Perform the carry for the later subtraction by updating y. */
- if ((x->tv_usec / scale) < y->tv_usec) {
- int sec = (y->tv_usec - (x->tv_usec / scale)) / 1000000 + 1;
- y->tv_usec -= 1000000 * sec;
- y->tv_sec += sec;
- }
- if ((x->tv_usec / scale) - y->tv_usec > 1000000) {
- int sec = ((x->tv_usec / scale) - y->tv_usec) / 1000000;
- y->tv_usec += 1000000 * sec;
- y->tv_sec -= sec;
- }
-
- /* Compute the time remaining to wait.
- * tv_usec is certainly positive. */
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_usec = x->tv_usec - (y->tv_usec * scale);
-
- /* Return 1 if result is negative or 0. */
- return x->tv_sec <= y->tv_sec;
-}
-
-int _WS_alloc(int fd) {
- if (_WS_connections[fd]) {
- RET_ERROR(ENOMEM, "Memory already allocated for fd %d\n", fd);
- }
- if (! (_WS_connections[fd] = malloc(sizeof(_WS_connection)))) {
- RET_ERROR(ENOMEM, "Could not allocate interposer memory\n");
- }
- _WS_connections[fd]->rcarry_cnt = 0;
- _WS_connections[fd]->rcarry[0] = '\0';
- _WS_connections[fd]->newframe = 1;
- _WS_connections[fd]->refcnt = 1;
-
- /* Add to search list for select/pselect */
- _WS_fds[_WS_nfds] = fd;
- _WS_nfds++;
-
- return 0;
-}
-
-int _WS_free(int fd) {
- int i;
- _WS_connection * wsptr;
- wsptr = _WS_connections[fd];
- if (wsptr) {
- TRACE(">> _WS_free(%d)\n", fd);
-
- wsptr->refcnt--;
- if (wsptr->refcnt <= 0) {
- free(wsptr);
- DEBUG("freed memory for fd %d\n", fd);
- }
- _WS_connections[fd] = NULL;
-
- /* Remove from the search list for select/pselect */
- for (i = 0; i < _WS_nfds; i++) {
- if (_WS_fds[i] == fd) {
- break;
- }
- }
- if (_WS_nfds - i - 1 > 0) {
- memmove(_WS_fds + i, _WS_fds + i + 1, _WS_nfds - i - 1);
- }
- _WS_nfds--;
-
- MSG("finished interposing on fd %d\n", fd);
- TRACE("<< _WS_free(%d)\n", fd);
- }
-}
-
-
-/*
- * WebSocket handshake routines
- */
-
-/* For WebSockets v76, use key1, key2 and key3 to generate md5 hash */
-int _WS_gen_md5(char *key1, char *key2, char *key3, char *target) {
- unsigned int i, spaces1 = 0, spaces2 = 0;
- unsigned long num1 = 0, num2 = 0;
- unsigned char buf[17];
-
- /* Parse number 1 from key 1 */
- for (i=0; i < strlen(key1); i++) {
- if (key1[i] == ' ') {
- spaces1 += 1;
- }
- if ((key1[i] >= 48) && (key1[i] <= 57)) {
- num1 = num1 * 10 + (key1[i] - 48);
- }
- }
- num1 = num1 / spaces1;
-
- /* Parse number 2 from key 2 */
- for (i=0; i < strlen(key2); i++) {
- if (key2[i] == ' ') {
- spaces2 += 1;
- }
- if ((key2[i] >= 48) && (key2[i] <= 57)) {
- num2 = num2 * 10 + (key2[i] - 48);
- }
- }
- num2 = num2 / spaces2;
-
- /* Pack it big-endian as the first 8 bytes */
- buf[0] = (num1 & 0xff000000) >> 24;
- buf[1] = (num1 & 0xff0000) >> 16;
- buf[2] = (num1 & 0xff00) >> 8;
- buf[3] = num1 & 0xff;
-
- buf[4] = (num2 & 0xff000000) >> 24;
- buf[5] = (num2 & 0xff0000) >> 16;
- buf[6] = (num2 & 0xff00) >> 8;
- buf[7] = num2 & 0xff;
-
- /* Add key 3 as the last 8 bytes */
- strncpy(buf+8, key3, 8);
- buf[16] = '\0';
-
- /* md5 hash all 16 bytes to generate 16 byte target */
- md5_buffer(buf, 16, target);
- target[16] = '\0';
-
- return 1;
-}
-
-/* Do v75 and v76 handshake on WebSocket connection */
-int _WS_handshake(int sockfd)
-{
- int sz = 0, len, idx;
- int ret = -1, save_errno = EPROTO;
- char *last, *start, *end;
- long flags;
- char handshake[4096], response[4096],
- path[1024], prefix[5] = "", scheme[10] = "ws", host[1024],
- origin[1024], key1[100], key2[100], key3[9], chksum[17];
-
- static void * (*rfunc)(), * (*wfunc)();
- if (!rfunc) rfunc = (void *(*)()) dlsym(RTLD_NEXT, "recv");
- if (!wfunc) wfunc = (void *(*)()) dlsym(RTLD_NEXT, "send");
- DEBUG("_WS_handshake starting\n");
-
- /* Disable NONBLOCK if set */
- flags = fcntl(sockfd, F_GETFL, 0);
- if (flags & O_NONBLOCK) {
- fcntl(sockfd, F_SETFL, flags^O_NONBLOCK);
- }
-
- while (1) {
- len = (int) rfunc(sockfd, handshake+sz, 4095, 0);
- if (len < 1) {
- ret = len;
- save_errno = errno;
- break;
- }
- sz += len;
- handshake[sz] = '\x00';
- if (sz < 4) {
- // Not enough yet
- continue;
- }
- if (strstr(handshake, "GET ") != handshake) {
- MSG("Got non-WebSockets client connection\n");
- break;
- }
- last = strstr(handshake, "\r\n\r\n");
- if (! last) {
- continue;
- }
- if (! strstr(handshake, "Upgrade: WebSocket\r\n")) {
- MSG("Invalid WebSockets handshake\n");
- break;
- }
-
- /* Now parse out the data elements */
- start = handshake+4;
- end = strstr(start, " HTTP/1.1");
- if (!end) { break; }
- snprintf(path, end-start+1, "%s", start);
-
- start = strstr(handshake, "\r\nHost: ");
- if (!start) { break; }
- start += 8;
- end = strstr(start, "\r\n");
- snprintf(host, end-start+1, "%s", start);
-
- start = strstr(handshake, "\r\nOrigin: ");
- if (!start) { break; }
- start += 10;
- end = strstr(start, "\r\n");
- snprintf(origin, end-start+1, "%s", start);
-
- start = strstr(handshake, "\r\n\r\n") + 4;
- if (strlen(start) == 8) {
- sprintf(prefix, "Sec-");
-
- snprintf(key3, 8+1, "%s", start);
-
- start = strstr(handshake, "\r\nSec-WebSocket-Key1: ");
- if (!start) { break; }
- start += 22;
- end = strstr(start, "\r\n");
- snprintf(key1, end-start+1, "%s", start);
-
- start = strstr(handshake, "\r\nSec-WebSocket-Key2: ");
- if (!start) { break; }
- start += 22;
- end = strstr(start, "\r\n");
- snprintf(key2, end-start+1, "%s", start);
-
- _WS_gen_md5(key1, key2, key3, chksum);
-
- //DEBUG("Got handshake (v76): %s\n", handshake);
- MSG("New WebSockets client (v76)\n");
-
- } else {
- sprintf(prefix, "");
- sprintf(key1, "");
- sprintf(key2, "");
- sprintf(key3, "");
- sprintf(chksum, "");
-
- //DEBUG("Got handshake (v75): %s\n", handshake);
- MSG("New WebSockets client (v75)\n");
- }
- sprintf(response, _WS_response, prefix, origin, prefix, scheme,
- host, path, prefix, chksum);
- //DEBUG("Handshake response: %s\n", response);
- wfunc(sockfd, response, strlen(response), 0);
- save_errno = 0;
- ret = 0;
- break;
- }
-
- /* Re-enable NONBLOCK if it was set */
- if (flags & O_NONBLOCK) {
- fcntl(sockfd, F_SETFL, flags);
- }
- errno = save_errno;
- return ret;
-}
-
-/*
- * Strip empty WebSockets frames and return a positive value if there is
- * enough data to base64 decode (a 4 byte chunk). If nonblock is not set then
- * it will block until there is enough data (or until an error occurs).
- */
-ssize_t _WS_ready(int sockfd, int nonblock)
-{
- _WS_connection *ws = _WS_connections[sockfd];
- char buf[6];
- int count, len, flags, i;
- static void * (*rfunc)();
- if (!rfunc) rfunc = (void *(*)()) dlsym(RTLD_NEXT, "recv");
-
- TRACE(">> _WS_ready(%d, %d)\n", sockfd, nonblock);
-
- count = 4 + ws->newframe;
- flags = MSG_PEEK;
- if (nonblock) {
- flags |= MSG_DONTWAIT;
- }
- while (1) {
- len = (int) rfunc(sockfd, buf, count, flags);
- if (len < 1) {
- TRACE("<< _WS_ready(%d, %d) len %d, errno: %d\n",
- sockfd, nonblock, len, errno);
- return len;
- }
- if (len >= 2 && buf[0] == '\x00' && buf[1] == '\xff') {
- /* Strip emtpy frame */
- DEBUG("_WS_ready(%d, %d), strip empty\n", sockfd, nonblock);
- len = (int) rfunc(sockfd, buf, 2, 0);
- if (len < 2) {
- MSG("Failed to strip empty frame headers\n");
- TRACE("<< _WS_ready: failed to strip empty frame headers\n");
- return len;
- } else if (len == 2 && nonblock) {
- errno = EAGAIN;
- TRACE("<< _WS_ready(%d, %d), len == 2, EAGAIN\n",
- sockfd, nonblock);
- return -1;
- }
- continue;
- }
- if (len < count) {
- if (nonblock) {
- errno = EAGAIN;
- TRACE("<< _WS_ready(%d, %d), len < count, EAGAIN\n",
- sockfd, nonblock);
- return -1;
- } else {
- fprintf(stderr, "_WS_ready(%d, %d), loop: len %d, buf:",
- sockfd, nonblock, len, (unsigned char) buf[0]);
- for (i = 0; i < len; i++) {
- fprintf(stderr, "%d", (unsigned char) buf[i]);
- }
- fprintf(stderr, "\n");
-
- continue;
- }
- }
- TRACE("<< _WS_ready(%d, %d) len: %d\n", sockfd, nonblock, len);
- return len;
- }
-}
-
-/*
- * WebSockets recv/read interposer routine
- */
-ssize_t _WS_recv(int recvf, int sockfd, const void *buf,
- size_t len, int flags)
-{
- _WS_connection *ws = _WS_connections[sockfd];
- int rawcount, deccount, left, striplen, decodelen, ready;
- ssize_t retlen, rawlen;
- int sockflags;
- int i;
- char *fstart, *fend, *cstart;
-
- static void * (*rfunc)(), * (*rfunc2)();
- if (!rfunc) rfunc = (void *(*)()) dlsym(RTLD_NEXT, "recv");
- if (!rfunc2) rfunc2 = (void *(*)()) dlsym(RTLD_NEXT, "read");
-
- if (! ws) {
- // Not our file descriptor, just pass through
- if (recvf) {
- return (ssize_t) rfunc(sockfd, buf, len, flags);
- } else {
- return (ssize_t) rfunc2(sockfd, buf, len);
- }
- }
- TRACE(">> _WS_recv(%d)\n", sockfd);
-
- if (len == 0) {
- TRACE("<< _WS_recv(%d) len == 0\n", sockfd);
- return 0;
- }
-
- sockflags = fcntl(sockfd, F_GETFL, 0);
- if (sockflags & O_NONBLOCK) {
- TRACE("_WS_recv(%d, _, %d) with O_NONBLOCK\n", sockfd, len);
- } else {
- TRACE("_WS_recv(%d, _, %d) without O_NONBLOCK\n", sockfd, len);
- }
-
- left = len;
- retlen = 0;
-
- /* first copy in carry-over bytes from previous recv/read */
- if (ws->rcarry_cnt) {
- if (ws->rcarry_cnt == 1) {
- DEBUG("Using carry byte: %u (", ws->rcarry[0]);
- } else if (ws->rcarry_cnt == 2) {
- DEBUG("Using carry bytes: %u,%u (", ws->rcarry[0],
- ws->rcarry[1]);
- } else {
- RET_ERROR(EIO, "Too many carry-over bytes\n");
- }
- if (len <= ws->rcarry_cnt) {
- DEBUG("final)\n");
- memcpy((char *) buf, ws->rcarry, len);
- ws->rcarry_cnt -= len;
- return len;
- } else {
- DEBUG("prepending)\n");
- memcpy((char *) buf, ws->rcarry, ws->rcarry_cnt);
- retlen += ws->rcarry_cnt;
- left -= ws->rcarry_cnt;
- ws->rcarry_cnt = 0;
- }
- }
-
- /* Determine the number of base64 encoded bytes needed */
- rawcount = (left * 4) / 3 + 3;
- rawcount -= rawcount%4;
-
- if (rawcount > WS_BUFSIZE - 1) {
- RET_ERROR(ENOMEM, "recv of %d bytes is larger than buffer\n", rawcount);
- }
-
- ready = _WS_ready(sockfd, 0);
- if (ready < 1) {
- if (retlen) {
- /* We had some carry over, don't error until next call */
- errno = 0;
- } else {
- retlen = ready;
- }
- TRACE("<< _WS_recv(%d, _, %d) retlen %d\n", sockfd, len, retlen);
- return retlen;
- }
-
- /* We have enough data to return something */
-
- /* Peek at everything available */
- rawlen = (ssize_t) rfunc(sockfd, ws->rbuf, WS_BUFSIZE-1,
- flags | MSG_PEEK);
- if (rawlen <= 0) {
- RET_ERROR(EPROTO, "Socket was ready but then had failure");
- }
- fstart = ws->rbuf;
- fstart[rawlen] = '\x00';
-
-
- if (ws->newframe) {
- if (fstart[0] != '\x00') {
- RET_ERROR(EPROTO, "Missing frame start\n");
- }
- fstart++;
- rawlen--;
- ws->newframe = 0;
- }
-
- fend = memchr(fstart, '\xff', rawlen);
-
- if (fend) {
- ws->newframe = 1;
- if ((fend - fstart) % 4) {
- RET_ERROR(EPROTO, "Frame length is not multiple of 4\n");
- }
- } else {
- fend = fstart + rawlen - (rawlen % 4);
- if (fend - fstart < 4) {
- RET_ERROR(EPROTO, "Frame too short\n");
- }
- }
-
- /* Determine amount to consume */
- if (rawcount < fend - fstart) {
- ws->newframe = 0;
- deccount = rawcount;
- } else {
- deccount = fend - fstart;
- }
-
- /* Now consume what was processed (if not MSG_PEEK) */
- if (flags & MSG_PEEK) {
- DEBUG("_WS_recv(%d, _, %d) MSG_PEEK, not consuming\n", sockfd, len);
- } else {
- rfunc(sockfd, ws->rbuf, fstart - ws->rbuf + deccount + ws->newframe, flags);
- }
-
- fstart[deccount] = '\x00'; // base64 terminator
-
- /* Do base64 decode into the return buffer */
- decodelen = b64_pton(fstart, (char *) buf + retlen, deccount);
- if (decodelen <= 0) {
- RET_ERROR(EPROTO, "Base64 decode error\n");
- }
-
- /* Calculate return length and carry-over */
- if (decodelen <= left) {
- retlen += decodelen;
- } else {
- retlen += left;
-
- if (! (flags & MSG_PEEK)) {
- /* Add anything left over to the carry-over */
- ws->rcarry_cnt = decodelen - left;
- if (ws->rcarry_cnt > 2) {
- RET_ERROR(EPROTO, "Got too much base64 data\n");
- }
- memcpy(ws->rcarry, buf + retlen, ws->rcarry_cnt);
- if (ws->rcarry_cnt == 1) {
- DEBUG("Saving carry byte: %u\n", ws->rcarry[0]);
- } else if (ws->rcarry_cnt == 2) {
- DEBUG("Saving carry bytes: %u,%u\n", ws->rcarry[0],
- ws->rcarry[1]);
- } else {
- RET_ERRO(EPROTO, "Too many carry bytes!\n");
- }
- }
- }
- ((char *) buf)[retlen] = '\x00';
-
- TRACE("<< _WS_recv(%d) retlen %d\n", sockfd, retlen);
- return retlen;
-}
-
-/*
- * WebSockets send and write interposer routine
- */
-ssize_t _WS_send(int sendf, int sockfd, const void *buf,
- size_t len, int flags)
-{
- _WS_connection *ws = _WS_connections[sockfd];
- int rawlen, enclen, rlen, over, left, clen, retlen, dbufsize;
- int sockflags;
- char * target;
- int i;
- static void * (*sfunc)(), * (*sfunc2)();
- if (!sfunc) sfunc = (void *(*)()) dlsym(RTLD_NEXT, "send");
- if (!sfunc2) sfunc2 = (void *(*)()) dlsym(RTLD_NEXT, "write");
-
- if (! ws) {
- // Not our file descriptor, just pass through
- if (sendf) {
- return (ssize_t) sfunc(sockfd, buf, len, flags);
- } else {
- return (ssize_t) sfunc2(sockfd, buf, len);
- }
- }
- TRACE(">> _WS_send(%d, _, %d)\n", sockfd, len);
-
- sockflags = fcntl(sockfd, F_GETFL, 0);
-
- dbufsize = (WS_BUFSIZE * 3)/4 - 2;
- if (len > dbufsize) {
- RET_ERROR(ENOMEM, "send of %d bytes is larger than send buffer\n", len);
- }
-
- /* base64 encode and add frame markers */
- rawlen = 0;
- ws->sbuf[rawlen++] = '\x00';
- enclen = b64_ntop(buf, len, ws->sbuf+rawlen, WS_BUFSIZE-rawlen);
- if (enclen < 0) {
- RET_ERROR(EPROTO, "Base64 encoding error\n");
- }
- rawlen += enclen;
- ws->sbuf[rawlen++] = '\xff';
-
- rlen = (int) sfunc(sockfd, ws->sbuf, rawlen, flags);
-
- if (rlen <= 0) {
- TRACE("<< _WS_send(%d, _, %d) send failed, returning\n", sockfd, len);
- return rlen;
- } else if (rlen < rawlen) {
- /* Spin until we can send a whole base64 chunck and frame end */
- over = (rlen - 1) % 4;
- left = (4 - over) % 4 + 1; // left to send
- DEBUG("_WS_send: rlen: %d (over: %d, left: %d), rawlen: %d\n",
- rlen, over, left, rawlen);
- rlen += left;
- ws->sbuf[rlen-1] = '\xff';
- i = 0;
- do {
- i++;
- clen = (int) sfunc(sockfd, ws->sbuf + rlen - left, left, flags);
- if (clen > 0) {
- left -= clen;
- } else if (clen == 0) {
- MSG("_WS_send: got clen %d\n", clen);
- } else if (!(sockflags & O_NONBLOCK)) {
- MSG("<< _WS_send: clen %d\n", clen);
- return clen;
- }
- if (i > 1000000) {
- RET_ERROR(EIO, "Could not send final part of frame\n");
- }
- } while (left > 0);
- //DEBUG("_WS_send: spins until finished %d\n", i);
- DEBUG("_WS_send: spins until finished %d\n", i);
- }
-
-
- /*
- * Report back the number of original characters sent,
- * not the raw number sent
- */
-
- /* Adjust for framing */
- retlen = rlen - 2;
-
- /* Adjust for base64 padding */
- if (ws->sbuf[rlen-1] == '=') { retlen --; }
- if (ws->sbuf[rlen-2] == '=') { retlen --; }
-
- /* Scale return value for base64 encoding size */
- retlen = (retlen*3)/4;
-
- TRACE(">> _WS_send(%d, _, %d) retlen %d\n", sockfd, len, retlen);
- return (ssize_t) retlen;
-}
-
-/*
- * Interpose select/pselect/poll.
- *
- * WebSocket descriptors are not ready until we have received a frame start
- * ('\x00') and at least 4 bytes of base64 encoded data. In addition we may
- * have carry-over data from the last 4 bytes of base64 data in which case the
- * WebSockets socket is ready even though there might not be data in the raw
- * socket itself.
- */
-
-/* Interpose on select (mode==0) and pselect (mode==1) */
-int _WS_select(int mode, int nfds, fd_set *readfds,
- fd_set *writefds, fd_set *exceptfds,
- void *timeptr, const sigset_t *sigmask)
-{
- _WS_connection *ws;
- fd_set carryfds, savefds;
- /* Assumes timeptr is two longs whether timeval or timespec */
- struct timeval savetv, starttv, nowtv, difftv;
- int carrycnt = 0, less = 0;
- int ret, i, ready, fd;
- static void * (*func0)(), * (*func1)();
- if (!func0) func0 = (void *(*)()) dlsym(RTLD_NEXT, "select");
- if (!func1) func1 = (void *(*)()) dlsym(RTLD_NEXT, "pselect");
-
- if ((_WS_listen_fd == -1) || (_WS_nfds == 0)) {
- if (mode == 0) {
- ret = (int) func0(nfds, readfds, writefds, exceptfds,
- timeptr);
- } else if (mode == 1) {
- ret = (int) func1(nfds, readfds, writefds, exceptfds,
- timeptr, sigmask);
- }
- return ret;
- }
-
-#ifdef DO_TRACE
- TRACE(">> _WS_select(%d, %d, _, _, _, _)\n", mode, nfds);
- for (i = 0; i < _WS_nfds; i++) {
- fd = _WS_fds[i];
- if (readfds && (FD_ISSET(fd, readfds))) {
- TRACE(" WS %d is in readfds\n", fd, nfds);
- }
- if (writefds && (FD_ISSET(fd, writefds))) {
- TRACE(" WS %d is in writefds\n", fd, nfds);
- }
- if (exceptfds && (FD_ISSET(fd, exceptfds))) {
- TRACE(" WS %d is in exceptfds\n", fd, nfds);
- }
- }
-#endif
- if (timeptr) {
- memcpy(&savetv, timeptr, sizeof(savetv));
- gettimeofday(&starttv, NULL);
- }
-
- /* If we have carry-over return it right away */
- FD_ZERO(&carryfds);
- if (readfds) {
- memcpy(&savefds, readfds, sizeof(savefds));
- for (i = 0; i < _WS_nfds; i++) {
- fd = _WS_fds[i];
- ws = _WS_connections[fd];
- if ((ws->rcarry_cnt) && (FD_ISSET(fd, readfds))) {
- FD_SET(fd, &carryfds);
- carrycnt++;
- }
- }
- }
- if (carrycnt) {
- if (writefds) {
- FD_ZERO(writefds);
- }
- if (exceptfds) {
- FD_ZERO(writefds);
- }
- memcpy(readfds, &carryfds, sizeof(carryfds));
- TRACE("<< _WS_select(%d, %d, _, _, _, _) carrycnt %d\n",
- mode, nfds, carrycnt);
- return carrycnt;
- }
-
- do {
- if (timeptr) {
- TRACE(" _WS_select tv/ts: %ld:%ld\n",
- ((struct timeval *) timeptr)->tv_sec,
- ((struct timeval *) timeptr)->tv_usec);
- }
- if (mode == 0) {
- ret = (int) func0(nfds, readfds, writefds, exceptfds,
- timeptr);
- } else if (mode == 1) {
- ret = (int) func1(nfds, readfds, writefds, exceptfds,
- timeptr, sigmask);
- }
- if (! readfds) {
- break;
- }
- if (ret <= 0) {
- break;
- }
-
- for (i = 0; i < _WS_nfds; i++) {
- fd = _WS_fds[i];
- ws = _WS_connections[fd];
- if (FD_ISSET(fd, readfds)) {
- ready = _WS_ready(fd, 1);
- if (ready == 0) {
- /* 0 means EOF which is also a ready condition */
- DEBUG("_WS_select: detected %d is closed\n", fd);
- } else if (ready < 0) {
- DEBUG("_WS_select: FD_CLR(%d,readfds) - not enough to decode\n", fd);
- FD_CLR(fd, readfds);
- ret--;
- }
- }
- }
- errno = 0; /* errno could be set by _WS_ready */
-
- if (ret == 0) {
- /*
- * If all the ready readfds were WebSockets, but none of
- * them were really ready (empty frames) then we select again. But
- * first restore original values less passage of time.
- */
- if (! timeptr) {
- /* No timeout, spin forever */
- continue;
- }
- memcpy(readfds, &savefds, sizeof(savefds));
- gettimeofday(&nowtv, NULL);
- /* Amount of time that has passed */
- _WS_subtract_time(&difftv, &nowtv, &starttv, 0);
- /* Subtract from original timout */
- less = _WS_subtract_time((struct timeval *) timeptr,
- &savetv, &difftv, mode);
- if (less) {
- /* Timer has expired */
- TRACE(" _WS_select expired timer\n", mode, nfds);
- break;
- }
- }
- } while (ret == 0);
-
- /* Restore original time value for pselect glibc does */
- if (timeptr && mode == 1) {
- memcpy(timeptr, &savetv, sizeof(savetv));
- }
-
-#ifdef DO_TRACE
- TRACE("<< _WS_select(%d, %d, _, _, _, _) ret %d, errno %d\n",
- mode, nfds, ret, errno);
- for (i = 0; i < _WS_nfds; i++) {
- fd = _WS_fds[i];
- if (readfds && (FD_ISSET(fd, readfds))) {
- TRACE(" WS %d is set in readfds\n", fd, nfds);
- }
- if (writefds && (FD_ISSET(fd, writefds))) {
- TRACE(" WS %d is set in writefds\n", fd, nfds);
- }
- if (exceptfds && (FD_ISSET(fd, exceptfds))) {
- TRACE(" WS %d is set in exceptfds\n", fd, nfds);
- }
- }
-#endif
- return ret;
-}
-
-/* Interpose on poll (mode==0) and ppoll (mode==1) */
-int _WS_poll(int mode, struct pollfd *fds, nfds_t nfds, int timeout,
- struct timespec *ptimeout, sigset_t *sigmask)
-{
- _WS_connection *ws;
- int savetimeout;
- struct timespec savets;
- struct timeval starttv, nowtv, difftv;
- struct pollfd *pfd;
- int carrycnt = 0, less = 0;
- int ret, i, ready, fd;
- static void * (*func0)(), * (*func1)();
- if (!func0) func0 = (void *(*)()) dlsym(RTLD_NEXT, "poll");
- if (!func1) func1 = (void *(*)()) dlsym(RTLD_NEXT, "ppoll");
-
- if ((_WS_listen_fd == -1) || (_WS_nfds == 0)) {
- if (mode == 0) {
- ret = (int) func0(fds, nfds, timeout);
- } else if (mode == 1) {
- ret = (int) func1(fds, nfds, ptimeout, sigmask);
- }
- return ret;
- }
-
- TRACE(">> _WS_poll(%d, %ld, _, _, _, _)\n", mode, nfds);
- if (mode == 0) {
- savetimeout = timeout;
- } else if (mode == 1) {
- memcpy(&savets, ptimeout, sizeof(savets));
- }
- gettimeofday(&starttv, NULL);
-
- do {
- TRACE(" _WS_poll(%d, %ld, _, _, _, _) tv/ts: %ld:%ld\n", mode, nfds,
- ptimeout->tv_sec, ptimeout->tv_nsec);
-
- if (mode == 0) {
- ret = (int) func0(fds, nfds, timeout);
- } else if (mode == 1) {
- ret = (int) func1(fds, nfds, ptimeout, sigmask);
- }
- if (ret <= 0) {
- break;
- }
-
- for (i = 0; i < nfds; i++) {
- pfd = &fds[i];
- if (! (pfd->events & POLLIN)) {
- continue;
- }
- ws = _WS_connections[pfd->fd];
- if (! ws) {
- continue;
- }
- if (ws->rcarry_cnt) {
- if (! (pfd->revents & POLLIN)) {
- pfd->revents |= POLLIN;
- ret++;
- }
- } else if (pfd->revents & POLLIN) {
- ready = _WS_ready(pfd->fd, 1);
- if (ready == 0) {
- /* 0 means EOF which is also a ready condition */
- DEBUG("_WS_poll: detected %d is closed\n", fd);
- } else if (ready < 0) {
- DEBUG("_WS_poll: not enough to decode\n", fd);
- pfd->revents -= POLLIN;
- ret--;
- }
- }
- }
- errno = 0; /* errno could be set by _WS_ready */
-
- if (ret == 0) {
- /*
- * If all the ready readfds were WebSockets, but none of
- * them were really ready (empty frames) then we select again. But
- * first restore original values less passage of time.
- */
- gettimeofday(&nowtv, NULL);
- /* Amount of time that has passed */
- _WS_subtract_time(&difftv, &nowtv, &starttv, 0);
- if (mode == 0) {
- if (timeout < 0) {
- /* Negative timeout means infinite */
- continue;
- }
- timeout -= difftv.tv_sec * 1000 + difftv.tv_usec / 1000;
- if (timeout <= 0) {
- less = 1;
- }
- } else if (mode == 1) {
- /* Subtract from original timout */
- less = _WS_subtract_time((struct timeval *) ptimeout,
- (struct timeval *) &savets,
- &difftv, 1);
- }
- if (less) {
- /* Timer has expired */
- TRACE(" _WS_poll expired timer\n", mode, nfds);
- break;
- }
- }
- } while (ret == 0);
-
- /* Restore original time value for pselect glibc does */
- if (mode == 1) {
- memcpy(ptimeout, &savets, sizeof(savets));
- }
-
- TRACE("<< _WS_poll(%d, %ld, _, _, _, _) ret %d, errno %d\n",
- mode, nfds, ret, errno);
- return ret;
-}
-
-
-/*
- * Overload (LD_PRELOAD) standard library network routines
- */
-
-int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
-{
- static void * (*func)();
- struct sockaddr_in * addr_in = (struct sockaddr_in *)addr;
- char * WSWRAP_PORT, * end;
- int ret, envport, bindport = htons(addr_in->sin_port);
- if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "bind");
- TRACE(">> bind(%d, _, %d)\n", sockfd, addrlen);
-
- ret = (int) func(sockfd, addr, addrlen);
-
- if (addr_in->sin_family != AF_INET) {
- // TODO: handle IPv6
- TRACE("<< bind, ignoring non-IPv4 socket\n");
- return ret;
- }
-
- WSWRAP_PORT = getenv("WSWRAP_PORT");
- if ((! WSWRAP_PORT) || (*WSWRAP_PORT == '\0')) {
- // TODO: interpose on all sockets when WSWRAP_PORT not set
- TRACE("<< bind, not interposing: WSWRAP_PORT is not set\n");
- return ret;
- }
-
- envport = strtol(WSWRAP_PORT, &end, 10);
- if ((envport == 0) || (*end != '\0')) {
- TRACE("<< bind, not interposing: WSWRAP_PORT is not a number\n");
- return ret;
- }
-
- if (envport != bindport) {
- TRACE("<< bind, not interposing on port: %d (fd %d)\n", bindport, sockfd);
- return ret;
- }
-
- _WS_listen_fd = sockfd;
-
- TRACE("<< bind, listening for WebSockets connections on port: %d (fd %d)\n", envport, sockfd);
- return ret;
-}
-
-int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
-{
- int fd, ret, envfd;
- static void * (*func)();
- if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "accept");
- TRACE("<< accept(%d, _, _)\n", sockfd);
-
- fd = (int) func(sockfd, addr, addrlen);
-
- if (_WS_listen_fd == -1) {
- TRACE("<< accept: not interposing\n");
- return fd;
- }
-
- if (_WS_listen_fd != sockfd) {
- TRACE("<< accept: not interposing on fd %d\n", sockfd);
- return fd;
- }
-
-
- if (_WS_connections[fd]) {
- RET_ERROR(EINVAL, "already interposing on fd %d\n", fd);
- } else {
- /* It's a port we're interposing on so allocate memory for it */
- if (_WS_nfds >= WS_MAX_FDS) {
- RET_ERROR(ENOMEM, "Too many interposer fds\n");
- }
- if (_WS_alloc(fd) < 0) {
- return -1;
- }
-
- ret = _WS_handshake(fd);
- if (ret < 0) {
- _WS_free(fd);
- errno = EPROTO;
- TRACE("<< accept(%d, _, _): ret %d\n", sockfd, ret);
- return ret;
- }
- MSG("interposing on fd %d (allocated memory)\n", fd);
- }
-
- return fd;
-}
-
-int close(int fd)
-{
- static void * (*func)();
- if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "close");
-
- TRACE("close(%d) called\n", fd);
-
- _WS_free(fd);
-
- return (int) func(fd);
-}
-
-
-ssize_t read(int fd, void *buf, size_t count)
-{
- TRACE("read(%d, _, %d) called\n", fd, count);
- return (ssize_t) _WS_recv(0, fd, buf, count, 0);
-}
-
-ssize_t write(int fd, const void *buf, size_t count)
-{
- TRACE("write(%d, _, %d) called\n", fd, count);
- return (ssize_t) _WS_send(0, fd, buf, count, 0);
-}
-
-ssize_t recv(int sockfd, void *buf, size_t len, int flags)
-{
- TRACE("recv(%d, _, %d, %d) called\n", sockfd, len, flags);
- return (ssize_t) _WS_recv(1, sockfd, buf, len, flags);
-}
-
-ssize_t send(int sockfd, const void *buf, size_t len, int flags)
-{
- TRACE("send(%d, _, %d, %d) called\n", sockfd, len, flags);
- return (ssize_t) _WS_send(1, sockfd, buf, len, flags);
-}
-
-int select(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, struct timeval *timeout)
-{
- TRACE("select(%d, _, _, _, _) called\n", nfds);
- return _WS_select(0, nfds, readfds, writefds, exceptfds,
- (void *) timeout, NULL);
-}
-
-int pselect(int nfds, fd_set *readfds, fd_set *writefds,
- fd_set *exceptfds, const struct timespec *timeout,
- const sigset_t *sigmask)
-{
- TRACE("pselect(%d, _, _, _, _, _) called\n", nfds);
- return _WS_select(1, nfds, readfds, writefds, exceptfds,
- (void *) timeout, sigmask);
-}
-
-int poll(struct pollfd *fds, nfds_t nfds, int timeout)
-{
- TRACE("poll(_, %ld, %d) called\n", nfds, timeout);
- return _WS_poll(0, fds, nfds, timeout, NULL, NULL);
-}
-
-int ppoll(struct pollfd *fds, nfds_t nfds,
- const struct timespec *timeout, const sigset_t *sigmask)
-{
- TRACE("ppoll(_, %ld, _, _) called\n", nfds);
- return _WS_poll(0, fds, nfds, 0, (struct timespec *)timeout,
- (sigset_t *)sigmask);
-}
-
-int dup(int oldfd) {
- int ret;
- static void * (*func)();
- if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "dup");
-
- TRACE(">> dup(%d) called\n", oldfd);
-
- ret = (int) func(oldfd);
-
- TRACE("<< dup(%d) ret %d\n", oldfd, ret);
- return ret;
-}
-
-int dup2(int oldfd, int newfd) {
- int ret;
- static void * (*func)();
- if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "dup2");
-
- TRACE(">> dup2(%d, %d) called\n", oldfd, newfd);
-
- ret = (int) func(oldfd, newfd);
- if ((! _WS_connections[oldfd]) && (! _WS_connections[newfd])) {
- return ret;
- }
-
- if ((ret < 0) || (oldfd == newfd) ||
- (_WS_connections[oldfd] == _WS_connections[newfd])) {
- TRACE("<< dup2(%d, %d) ret %d\n", oldfd, newfd, ret);
- return ret;
- }
-
- /* dup2 behavior is to close newfd if it's open */
- if (_WS_connections[newfd]) {
- _WS_free(newfd);
- }
-
- if (! _WS_connections[oldfd]) {
- TRACE("<< dup2(%d, %d) ret %d\n", oldfd, newfd, ret);
- return ret;
- }
-
- MSG("interposing on duplicated fd %d\n", newfd);
- /* oldfd and newfd are now descriptors for the same socket,
- * re-use the same context memory area */
- _WS_connections[newfd] = _WS_connections[oldfd];
- _WS_connections[newfd]->refcnt++;
-
- /* Add to search list for select/pselect */
- _WS_fds[_WS_nfds] = newfd;
- _WS_nfds++;
-
- TRACE("<< dup2(%d, %d) ret %d\n", oldfd, newfd, ret);
- return ret;
-
-}
-
-int dup3(int oldfd, int newfd, int flags) {
- int ret;
- static void * (*func)();
- if (!func) func = (void *(*)()) dlsym(RTLD_NEXT, "dup3");
-
- TRACE(">> dup3(%d, %d, %d) called\n", oldfd, newfd, flags);
-
- ret = (int) func(oldfd, newfd, flags);
-
- TRACE("<< dup3(%d, %d, %d) ret %d\n", oldfd, newfd, flags, ret);
- return ret;
-}
-
diff --git a/utils/wswrapper.h b/utils/wswrapper.h
deleted file mode 100644
index 412b17a3..00000000
--- a/utils/wswrapper.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * wswrap/wswrapper: Add WebSockets support to any service.
- * Copyright 2010 Joel Martin
- * Licensed under LGPL version 3 (see docs/LICENSE.LGPL-3)
- */
-
-#ifdef DO_MSG
-#define MSG(...) \
- fprintf(stderr, "wswrapper: "); \
- fprintf(stderr, __VA_ARGS__);
-#else
-#define MSG(...)
-#endif
-
-#ifdef DO_DEBUG
-#define DEBUG(...) \
- if (DO_DEBUG) { \
- fprintf(stderr, "wswrapper: "); \
- fprintf(stderr, __VA_ARGS__); \
- }
-#else
-#define DEBUG(...)
-#endif
-
-#ifdef DO_TRACE
-#define TRACE(...) \
- if (DO_TRACE) { \
- fprintf(stderr, "wswrapper: "); \
- fprintf(stderr, __VA_ARGS__); \
- }
-#else
-#define TRACE(...)
-#endif
-
-#define RET_ERROR(eno, ...) \
- fprintf(stderr, "wswrapper error: "); \
- fprintf(stderr, __VA_ARGS__); \
- errno = eno; \
- return -1;
-
-
-const char _WS_response[] = "\
-HTTP/1.1 101 Web Socket Protocol Handshake\r\n\
-Upgrade: WebSocket\r\n\
-Connection: Upgrade\r\n\
-%sWebSocket-Origin: %s\r\n\
-%sWebSocket-Location: %s://%s%s\r\n\
-%sWebSocket-Protocol: sample\r\n\
-\r\n%s";
-
-#define WS_BUFSIZE 65536
-#define WS_MAX_FDS 1024
-
-/* Buffers and state for each wrapped WebSocket connection */
-typedef struct {
- char rbuf[WS_BUFSIZE];
- char sbuf[WS_BUFSIZE];
- int rcarry_cnt;
- char rcarry[3];
- int newframe;
- int refcnt;
-} _WS_connection;
-
-