mirror of
https://github.com/fcwu/docker-ubuntu-vnc-desktop
synced 2026-08-05 16:12:41 +02:00
feat: upgrade noVNC
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from base64 import b64encode, b64decode
|
||||
from codecs import (utf_8_encode, utf_8_decode,
|
||||
latin_1_encode, latin_1_decode)
|
||||
import random, time
|
||||
|
||||
buf_len = 10000
|
||||
iterations = 10000
|
||||
|
||||
print "Generating random input buffer"
|
||||
r = random.Random()
|
||||
buf = "".join([chr(r.randint(0, 255)) for i in range(buf_len)])
|
||||
|
||||
tests = {'UTF8 encode': lambda: utf_8_encode(unicode(buf, 'latin-1'))[0],
|
||||
'B64 encode': lambda: b64encode(buf)}
|
||||
utf8_buf = tests['UTF8 encode']()
|
||||
b64_buf = tests['B64 encode']()
|
||||
tests.update({'UTF8 decode': lambda: latin_1_encode(utf_8_decode(utf8_buf)[0])[0],
|
||||
'B64 decode': lambda: b64decode(b64_buf)})
|
||||
|
||||
print "Running tests"
|
||||
for test in 'UTF8 encode', 'B64 encode', 'UTF8 decode', 'B64 decode':
|
||||
start = time.time()
|
||||
for i in range(iterations):
|
||||
res_buf = tests[test]()
|
||||
print "%s took %s seconds (result size %s)" % (
|
||||
test, (time.time() - start), len(res_buf))
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Native Base64 Tests</title>
|
||||
<script src="include/util.js"></script>
|
||||
<script src="include/webutil.js"></script>
|
||||
<script src="include/base64.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Native Base64 Tests</h1>
|
||||
|
||||
<br>
|
||||
Messages:<br>
|
||||
<textarea id="debug" style="font-size: 9px;" cols=80 rows=25></textarea>
|
||||
|
||||
<br>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
function debug(str) {
|
||||
console.log(str);
|
||||
cell = $D('debug');
|
||||
cell.innerHTML += str + "\n";
|
||||
cell.scrollTop = cell.scrollHeight;
|
||||
}
|
||||
|
||||
function assertRun(code, result) {
|
||||
try {
|
||||
var actual = eval(code);
|
||||
} catch (exc) {
|
||||
debug("FAIL: '" + code + "' threw an exception");
|
||||
fail += 1;
|
||||
return false;
|
||||
}
|
||||
if (actual !== result) {
|
||||
debug("FAIL: '" + code + "' returned '" + actual + "', expected '" + result + "'");
|
||||
fail += 1;
|
||||
return false;
|
||||
}
|
||||
debug("PASS: '" + code + "' returned expected '" + result +"'");
|
||||
pass += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
function Base64_decode(data) {
|
||||
var arr = Base64.decode (data);
|
||||
return arr.map(function (num) {
|
||||
return String.fromCharCode(num); } ).join('');
|
||||
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
var str;
|
||||
debug('onload');
|
||||
fail = 0;
|
||||
pass = 0;
|
||||
assertRun('window.btoa("hello world")', 'aGVsbG8gd29ybGQ=');
|
||||
assertRun('window.btoa("a")', 'YQ==');
|
||||
assertRun('window.btoa("ab")', 'YWI=');
|
||||
assertRun('window.btoa("abc")', 'YWJj');
|
||||
assertRun('window.btoa("abcd")', 'YWJjZA==');
|
||||
assertRun('window.btoa("abcde")', 'YWJjZGU=');
|
||||
assertRun('window.btoa("abcdef")', 'YWJjZGVm');
|
||||
assertRun('window.btoa("abcdefg")', 'YWJjZGVmZw==');
|
||||
assertRun('window.btoa("abcdefgh")', 'YWJjZGVmZ2g=');
|
||||
|
||||
assertRun('window.atob("aGVsbG8gd29ybGQ=")', 'hello world');
|
||||
assertRun('Base64_decode("aGVsbG8gd29ybGQ=")', 'hello world');
|
||||
assertRun('window.atob("YQ==")', 'a');
|
||||
assertRun('Base64_decode("YQ==")', 'a');
|
||||
assertRun('window.atob("YWI=")', 'ab');
|
||||
assertRun('Base64_decode("YWI=")', 'ab');
|
||||
assertRun('window.atob("YWJj")', 'abc');
|
||||
assertRun('Base64_decode("YWJj")', 'abc');
|
||||
assertRun('window.atob("YWJjZA==")', 'abcd');
|
||||
assertRun('Base64_decode("YWJjZA==")', 'abcd');
|
||||
assertRun('window.atob("YWJjZGU=")', 'abcde');
|
||||
assertRun('Base64_decode("YWJjZGU=")', 'abcde');
|
||||
assertRun('window.atob("YWJjZGVm")', 'abcdef');
|
||||
assertRun('Base64_decode("YWJjZGVm")', 'abcdef');
|
||||
|
||||
assertRun('typeof window.btoa', 'function');
|
||||
assertRun('window.btoa("")', '');
|
||||
assertRun('window.btoa(null)', '');
|
||||
assertRun('window.atob(window.btoa(window))', window.toString()); // "[object DOMWindow]"
|
||||
assertRun('window.btoa("\\u0080\\u0081")', 'gIE=');
|
||||
|
||||
debug("Tests failed: " + fail);
|
||||
debug("Tests passed: " + pass);
|
||||
}
|
||||
</script>
|
||||
@@ -1,12 +0,0 @@
|
||||
// The following results in 'hello [MANGLED]'
|
||||
//
|
||||
// Filed as https://github.com/ry/node/issues/issue/402
|
||||
|
||||
var sys = require("sys"),
|
||||
buf = new Buffer(1024), len,
|
||||
str1 = "aGVsbG8g", // 'hello '
|
||||
str2 = "d29ybGQ=", // 'world'
|
||||
|
||||
len = buf.write(str1, 0, 'base64');
|
||||
len += buf.write(str2, len, 'base64');
|
||||
sys.log("decoded result: " + buf.toString('binary', 0, len));
|
||||
@@ -4,7 +4,6 @@
|
||||
<title>WebSockets Echo Test</title>
|
||||
<script src="include/util.js"></script>
|
||||
<script src="include/webutil.js"></script>
|
||||
<script src="include/base64.js"></script>
|
||||
<script src="include/websock.js"></script>
|
||||
<!-- Uncomment to activate firebug lite -->
|
||||
<!--
|
||||
|
||||
@@ -12,9 +12,9 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates
|
||||
|
||||
import os, sys, select, optparse, logging
|
||||
sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))
|
||||
from websockify.websocket import WebSocketServer, WebSocketRequestHandler
|
||||
from websockify.websockifyserver import WebSockifyServer, WebSockifyRequestHandler
|
||||
|
||||
class WebSocketEcho(WebSocketRequestHandler):
|
||||
class WebSocketEcho(WebSockifyRequestHandler):
|
||||
"""
|
||||
WebSockets server that echos back whatever is received from the
|
||||
client. """
|
||||
@@ -48,7 +48,7 @@ class WebSocketEcho(WebSocketRequestHandler):
|
||||
cqueue.extend(frames)
|
||||
|
||||
if closed:
|
||||
self.send_close()
|
||||
break
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = optparse.OptionParser(usage="%prog [options] listen_port")
|
||||
@@ -71,6 +71,6 @@ if __name__ == '__main__':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
opts.web = "."
|
||||
server = WebSocketServer(WebSocketEcho, **opts.__dict__)
|
||||
server = WebSockifyServer(WebSocketEcho, **opts.__dict__)
|
||||
server.start_server()
|
||||
|
||||
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import optparse
|
||||
import select
|
||||
|
||||
sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))
|
||||
from websockify.websocket import WebSocket, \
|
||||
WebSocketWantReadError, WebSocketWantWriteError
|
||||
|
||||
parser = optparse.OptionParser(usage="%prog URL")
|
||||
(opts, args) = parser.parse_args()
|
||||
|
||||
try:
|
||||
if len(args) != 1: raise
|
||||
URL = args[0]
|
||||
except:
|
||||
parser.error("Invalid arguments")
|
||||
|
||||
sock = WebSocket()
|
||||
print("Connecting to %s..." % URL)
|
||||
sock.connect(URL)
|
||||
print("Connected.")
|
||||
|
||||
def send(msg):
|
||||
while True:
|
||||
try:
|
||||
sock.sendmsg(msg)
|
||||
break
|
||||
except WebSocketWantReadError:
|
||||
msg = ''
|
||||
ins, outs, excepts = select.select([sock], [], [])
|
||||
if excepts: raise Exception("Socket exception")
|
||||
except WebSocketWantWriteError:
|
||||
msg = ''
|
||||
ins, outs, excepts = select.select([], [sock], [])
|
||||
if excepts: raise Exception("Socket exception")
|
||||
|
||||
def read():
|
||||
while True:
|
||||
try:
|
||||
return sock.recvmsg()
|
||||
except WebSocketWantReadError:
|
||||
ins, outs, excepts = select.select([sock], [], [])
|
||||
if excepts: raise Exception("Socket exception")
|
||||
except WebSocketWantWriteError:
|
||||
ins, outs, excepts = select.select([], [sock], [])
|
||||
if excepts: raise Exception("Socket exception")
|
||||
|
||||
counter = 1
|
||||
while True:
|
||||
msg = "Message #%d" % counter
|
||||
counter += 1
|
||||
send(msg)
|
||||
print("Sent message: %r" % msg)
|
||||
|
||||
while True:
|
||||
ins, outs, excepts = select.select([sock], [], [], 1.0)
|
||||
if excepts: raise Exception("Socket exception")
|
||||
|
||||
if ins == []:
|
||||
break
|
||||
|
||||
while True:
|
||||
msg = read()
|
||||
print("Received message: %r" % msg)
|
||||
|
||||
if not sock.pending():
|
||||
break
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
<head>
|
||||
<title>WebSockets Latency Test</title>
|
||||
<script src="include/base64.js"></script>
|
||||
<script src="include/util.js"></script>
|
||||
<script src="include/webutil.js"></script>
|
||||
<script src="include/websock.js"></script>
|
||||
@@ -57,7 +56,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
var host = null, port = null, sendDelay = 0, actualSendDelay,
|
||||
var host = null, port = null, sendDelay = 0,
|
||||
ws = null, send_ref = null,
|
||||
sent, received, latencies, ltotal, laverage, lrunning, lmin, lmax,
|
||||
run_length = 40,
|
||||
@@ -92,8 +91,8 @@
|
||||
now = (new Date()).getTime(); // Early as possible
|
||||
|
||||
arr = ws.rQshiftBytes(ws.rQlen());
|
||||
first = String.fromCharCode(arr.shift());
|
||||
last = String.fromCharCode(arr.pop());
|
||||
first = String.fromCharCode(arr[0]);
|
||||
last = String.fromCharCode(arr[arr.length-1]);
|
||||
|
||||
if (first != "^") {
|
||||
message("Error: packet missing start char '^'");
|
||||
@@ -105,9 +104,11 @@
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
arr = arr.map(function(num) {
|
||||
return String.fromCharCode(num);
|
||||
} ).join('').split(':');
|
||||
text = ''
|
||||
for (var i = 1; i < arr.length-1; i++) {
|
||||
text += String.fromCharCode(arr[i]);
|
||||
}
|
||||
arr = text.split(':');
|
||||
seq = arr[0];
|
||||
timestamp = parseInt(arr[1],10);
|
||||
rpayload = arr[2];
|
||||
@@ -152,19 +153,6 @@
|
||||
|
||||
function sendMsg() {
|
||||
var arr = [];
|
||||
if (! ws.flush() ) {
|
||||
message("WebSocket not ready, backing off");
|
||||
actualSendDelay = actualSendDelay * 2;
|
||||
send_ref = setTimeout(sendMsg, actualSendDelay);
|
||||
return false;
|
||||
} else {
|
||||
// Scale the delay down to the requested minimum
|
||||
if (actualSendDelay > sendDelay) {
|
||||
message("WebSocket ready, increasing presure");
|
||||
actualSendDelay = Math.max(actualSendDelay / 2, sendDelay);
|
||||
}
|
||||
}
|
||||
|
||||
timestamp = (new Date()).getTime();
|
||||
arr.pushStr("^" + send_seq + ":" + timestamp + ":" + payload + "$");
|
||||
send_seq ++;
|
||||
@@ -172,7 +160,7 @@
|
||||
sent++;
|
||||
|
||||
showStats();
|
||||
send_ref = setTimeout(sendMsg, actualSendDelay);
|
||||
send_ref = setTimeout(sendMsg, sendDelay);
|
||||
}
|
||||
|
||||
function showStats() {
|
||||
@@ -246,7 +234,6 @@
|
||||
lrunning = 0;
|
||||
lmin = 999999999;
|
||||
lmax = 0;
|
||||
actualSendDelay = sendDelay;
|
||||
|
||||
$D('connectButton').value = "Stop";
|
||||
$D('connectButton').onclick = disconnect;
|
||||
@@ -275,11 +262,6 @@
|
||||
|
||||
window.onload = function() {
|
||||
console.log("onload");
|
||||
if (Websock_native) {
|
||||
message("Using native WebSockets");
|
||||
} else {
|
||||
message("initializing web-socket-js flash bridge");
|
||||
}
|
||||
var url = document.location.href;
|
||||
$D('host').value = (url.match(/host=([^&#]*)/) || ['',window.location.hostname])[1];
|
||||
$D('port').value = (url.match(/port=([^&#]*)/) || ['',window.location.port])[1];
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<title>WebSockets Load Test</title>
|
||||
<script src="include/util.js"></script>
|
||||
<script src="include/webutil.js"></script>
|
||||
<script src="include/base64.js"></script>
|
||||
<script src="include/websock.js"></script>
|
||||
<!-- Uncomment to activate firebug lite -->
|
||||
<!--
|
||||
@@ -221,26 +220,8 @@
|
||||
console.log("<< disconnect");
|
||||
}
|
||||
|
||||
|
||||
/* If no builtin websockets then load web_socket.js */
|
||||
if (window.WebSocket) {
|
||||
VNC_native_ws = true;
|
||||
} else {
|
||||
VNC_native_ws = false;
|
||||
console.log("Loading web-socket-js flash bridge");
|
||||
var extra = "<script src='include/web-socket-js/swfobject.js'><\/script>";
|
||||
extra += "<script src='include/web-socket-js/FABridge.js'><\/script>";
|
||||
extra += "<script src='include/web-socket-js/web_socket.js'><\/script>";
|
||||
document.write(extra);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
console.log("onload");
|
||||
if (!VNC_native_ws) {
|
||||
console.log("initializing web-socket-js flash bridge");
|
||||
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
|
||||
WebSocket.__initialize();
|
||||
}
|
||||
var url = document.location.href;
|
||||
$D('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
||||
$D('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
||||
|
||||
@@ -8,9 +8,9 @@ given a sequence number. Any errors are reported and counted.
|
||||
|
||||
import sys, os, select, random, time, optparse, logging
|
||||
sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))
|
||||
from websockify.websocket import WebSocketServer, WebSocketRequestHandler
|
||||
from websockify.websockifyserver import WebSockifyServer, WebSockifyRequestHandler
|
||||
|
||||
class WebSocketLoadServer(WebSocketServer):
|
||||
class WebSocketLoadServer(WebSockifyServer):
|
||||
|
||||
recv_cnt = 0
|
||||
send_cnt = 0
|
||||
@@ -18,10 +18,10 @@ class WebSocketLoadServer(WebSocketServer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.delay = kwargs.pop('delay')
|
||||
|
||||
WebSocketServer.__init__(self, *args, **kwargs)
|
||||
WebSockifyServer.__init__(self, *args, **kwargs)
|
||||
|
||||
|
||||
class WebSocketLoad(WebSocketRequestHandler):
|
||||
class WebSocketLoad(WebSockifyRequestHandler):
|
||||
|
||||
max_packet_size = 10000
|
||||
|
||||
@@ -35,12 +35,10 @@ class WebSocketLoad(WebSocketRequestHandler):
|
||||
self.send_cnt = 0
|
||||
self.recv_cnt = 0
|
||||
|
||||
try:
|
||||
self.responder(self.request)
|
||||
except:
|
||||
print "accumulated errors:", self.errors
|
||||
self.errors = 0
|
||||
raise
|
||||
self.responder(self.request)
|
||||
|
||||
print "accumulated errors:", self.errors
|
||||
self.errors = 0
|
||||
|
||||
def responder(self, client):
|
||||
c_pend = 0
|
||||
@@ -62,7 +60,7 @@ class WebSocketLoad(WebSocketRequestHandler):
|
||||
print err
|
||||
|
||||
if closed:
|
||||
self.send_close()
|
||||
break
|
||||
|
||||
now = time.time() * 1000
|
||||
if client in outs:
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
}
|
||||
uri = scheme + host + ":" + port;
|
||||
message("connecting to " + uri);
|
||||
ws = new WebSocket(uri, "base64");
|
||||
ws = new WebSocket(uri);
|
||||
|
||||
ws.onmessage = function(e) {
|
||||
//console.log(">> WebSockets.onmessage");
|
||||
@@ -139,26 +139,8 @@
|
||||
console.log("<< disconnect");
|
||||
}
|
||||
|
||||
|
||||
/* If no builtin websockets then load web_socket.js */
|
||||
if (window.WebSocket) {
|
||||
VNC_native_ws = true;
|
||||
} else {
|
||||
VNC_native_ws = false;
|
||||
console.log("Loading web-socket-js flash bridge");
|
||||
var extra = "<script src='include/web-socket-js/swfobject.js'><\/script>";
|
||||
extra += "<script src='include/web-socket-js/FABridge.js'><\/script>";
|
||||
extra += "<script src='include/web-socket-js/web_socket.js'><\/script>";
|
||||
document.write(extra);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
console.log("onload");
|
||||
if (!VNC_native_ws) {
|
||||
console.log("initializing web-socket-js flash bridge");
|
||||
WebSocket.__swfLocation = "include/web-socket-js/WebSocketMain.swf";
|
||||
WebSocket.__initialize();
|
||||
}
|
||||
var url = document.location.href;
|
||||
$D('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
|
||||
$D('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>Websock Simple Client</title>
|
||||
<script src="include/util.js"></script>
|
||||
<script src="include/base64.js"></script>
|
||||
<script src="include/websock.js"></script>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
""" Unit tests for Authentication plugins"""
|
||||
|
||||
from websockify.auth_plugins import BasicHTTPAuth, AuthenticationError
|
||||
import unittest
|
||||
|
||||
|
||||
class BasicHTTPAuthTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.plugin = BasicHTTPAuth('Aladdin:open sesame')
|
||||
|
||||
def test_no_auth(self):
|
||||
headers = {}
|
||||
self.assertRaises(AuthenticationError, self.plugin.authenticate, headers, 'localhost', '1234')
|
||||
|
||||
def test_invalid_password(self):
|
||||
headers = {'Authorization': 'Basic QWxhZGRpbjpzZXNhbWUgc3RyZWV0'}
|
||||
self.assertRaises(AuthenticationError, self.plugin.authenticate, headers, 'localhost', '1234')
|
||||
|
||||
def test_valid_password(self):
|
||||
headers = {'Authorization': 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
|
||||
self.plugin.authenticate(headers, 'localhost', '1234')
|
||||
|
||||
def test_garbage_auth(self):
|
||||
headers = {'Authorization': 'Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx'}
|
||||
self.assertRaises(AuthenticationError, self.plugin.authenticate, headers, 'localhost', '1234')
|
||||
@@ -15,229 +15,172 @@
|
||||
# under the License.
|
||||
|
||||
""" Unit tests for websocket """
|
||||
import errno
|
||||
import os
|
||||
import logging
|
||||
import select
|
||||
import shutil
|
||||
import socket
|
||||
import ssl
|
||||
import stubout
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from ssl import SSLError
|
||||
from websockify import websocket as websocket
|
||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
||||
from websockify import websocket
|
||||
|
||||
class FakeSocket:
|
||||
def __init__(self):
|
||||
self.data = b''
|
||||
|
||||
class MockConnection(object):
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
def send(self, buf):
|
||||
self.data += buf
|
||||
return len(buf)
|
||||
|
||||
def makefile(self, mode='r', bufsize=-1):
|
||||
return open(self.path, mode, bufsize)
|
||||
class AcceptTestCase(unittest.TestCase):
|
||||
def test_success(self):
|
||||
ws = websocket.WebSocket()
|
||||
sock = FakeSocket()
|
||||
ws.accept(sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
self.assertEqual(sock.data[:13], b'HTTP/1.1 101 ')
|
||||
self.assertTrue(b'\r\nUpgrade: websocket\r\n' in sock.data)
|
||||
self.assertTrue(b'\r\nConnection: Upgrade\r\n' in sock.data)
|
||||
self.assertTrue(b'\r\nSec-WebSocket-Accept: pczpYSQsvE1vBpTQYjFQPcuoj6M=\r\n' in sock.data)
|
||||
|
||||
def test_bad_version(self):
|
||||
ws = websocket.WebSocket()
|
||||
sock = FakeSocket()
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '5',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '20',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
|
||||
class WebSocketTestCase(unittest.TestCase):
|
||||
def test_bad_upgrade(self):
|
||||
ws = websocket.WebSocket()
|
||||
sock = FakeSocket()
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket2',
|
||||
'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
|
||||
def _init_logger(self, tmpdir):
|
||||
name = 'websocket-unittest'
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.propagate = True
|
||||
filename = "%s.log" % (name)
|
||||
handler = logging.FileHandler(filename)
|
||||
handler.setFormatter(logging.Formatter("%(message)s"))
|
||||
logger.addHandler(handler)
|
||||
def test_missing_key(self):
|
||||
ws = websocket.WebSocket()
|
||||
sock = FakeSocket()
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13'})
|
||||
|
||||
def setUp(self):
|
||||
"""Called automatically before each test."""
|
||||
super(WebSocketTestCase, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
# Temporary dir for test data
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
# Put log somewhere persistent
|
||||
self._init_logger('./')
|
||||
# Mock this out cause it screws tests up
|
||||
self.stubs.Set(os, 'chdir', lambda *args, **kwargs: None)
|
||||
self.server = self._get_websockserver(daemon=True,
|
||||
ssl_only=False)
|
||||
self.soc = self.server.socket('localhost')
|
||||
def test_protocol(self):
|
||||
class ProtoSocket(websocket.WebSocket):
|
||||
def select_subprotocol(self, protocol):
|
||||
return 'gazonk'
|
||||
|
||||
def tearDown(self):
|
||||
"""Called automatically after each test."""
|
||||
self.stubs.UnsetAll()
|
||||
shutil.rmtree(self.tmpdir)
|
||||
super(WebSocketTestCase, self).tearDown()
|
||||
ws = ProtoSocket()
|
||||
sock = FakeSocket()
|
||||
ws.accept(sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q==',
|
||||
'Sec-WebSocket-Protocol': 'foobar gazonk'})
|
||||
self.assertEqual(sock.data[:13], b'HTTP/1.1 101 ')
|
||||
self.assertTrue(b'\r\nSec-WebSocket-Protocol: gazonk\r\n' in sock.data)
|
||||
|
||||
def _get_websockserver(self, **kwargs):
|
||||
return websocket.WebSocketServer(listen_host='localhost',
|
||||
listen_port=80,
|
||||
key=self.tmpdir,
|
||||
web=self.tmpdir,
|
||||
record=self.tmpdir,
|
||||
**kwargs)
|
||||
def test_no_protocol(self):
|
||||
ws = websocket.WebSocket()
|
||||
sock = FakeSocket()
|
||||
ws.accept(sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q=='})
|
||||
self.assertEqual(sock.data[:13], b'HTTP/1.1 101 ')
|
||||
self.assertFalse(b'\r\nSec-WebSocket-Protocol:' in sock.data)
|
||||
|
||||
def _mock_os_open_oserror(self, file, flags):
|
||||
raise OSError('')
|
||||
def test_missing_protocol(self):
|
||||
ws = websocket.WebSocket()
|
||||
sock = FakeSocket()
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q==',
|
||||
'Sec-WebSocket-Protocol': 'foobar gazonk'})
|
||||
|
||||
def _mock_os_close_oserror(self, fd):
|
||||
raise OSError('')
|
||||
def test_protocol(self):
|
||||
class ProtoSocket(websocket.WebSocket):
|
||||
def select_subprotocol(self, protocol):
|
||||
return 'oddball'
|
||||
|
||||
def _mock_os_close_oserror_EBADF(self, fd):
|
||||
raise OSError(errno.EBADF, '')
|
||||
ws = ProtoSocket()
|
||||
sock = FakeSocket()
|
||||
self.assertRaises(Exception, ws.accept,
|
||||
sock, {'upgrade': 'websocket',
|
||||
'Sec-WebSocket-Version': '13',
|
||||
'Sec-WebSocket-Key': 'DKURYVK9cRFul1vOZVA56Q==',
|
||||
'Sec-WebSocket-Protocol': 'foobar gazonk'})
|
||||
|
||||
def _mock_socket(self, *args, **kwargs):
|
||||
return self.soc
|
||||
class HyBiEncodeDecodeTestCase(unittest.TestCase):
|
||||
def test_decode_hybi_text(self):
|
||||
buf = b'\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58'
|
||||
ws = websocket.WebSocket()
|
||||
res = ws._decode_hybi(buf)
|
||||
|
||||
def _mock_select(self, rlist, wlist, xlist, timeout=None):
|
||||
return '_mock_select'
|
||||
self.assertEqual(res['fin'], 1)
|
||||
self.assertEqual(res['opcode'], 0x1)
|
||||
self.assertEqual(res['masked'], True)
|
||||
self.assertEqual(res['length'], len(buf))
|
||||
self.assertEqual(res['payload'], b'Hello')
|
||||
|
||||
def _mock_select_exception(self, rlist, wlist, xlist, timeout=None):
|
||||
raise Exception
|
||||
def test_decode_hybi_binary(self):
|
||||
buf = b'\x82\x04\x01\x02\x03\x04'
|
||||
ws = websocket.WebSocket()
|
||||
res = ws._decode_hybi(buf)
|
||||
|
||||
def _mock_select_keyboardinterrupt(self, rlist, wlist,
|
||||
xlist, timeout=None):
|
||||
raise KeyboardInterrupt
|
||||
self.assertEqual(res['fin'], 1)
|
||||
self.assertEqual(res['opcode'], 0x2)
|
||||
self.assertEqual(res['length'], len(buf))
|
||||
self.assertEqual(res['payload'], b'\x01\x02\x03\x04')
|
||||
|
||||
def _mock_select_systemexit(self, rlist, wlist, xlist, timeout=None):
|
||||
sys.exit()
|
||||
def test_decode_hybi_extended_16bit_binary(self):
|
||||
data = (b'\x01\x02\x03\x04' * 65) # len > 126 -- len == 260
|
||||
buf = b'\x82\x7e\x01\x04' + data
|
||||
ws = websocket.WebSocket()
|
||||
res = ws._decode_hybi(buf)
|
||||
|
||||
def test_daemonize_error(self):
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=1, idle_timeout=1)
|
||||
self.stubs.Set(os, 'fork', lambda *args: None)
|
||||
self.stubs.Set(os, 'setsid', lambda *args: None)
|
||||
self.stubs.Set(os, 'close', self._mock_os_close_oserror)
|
||||
self.assertRaises(OSError, soc.daemonize, keepfd=None, chdir='./')
|
||||
self.assertEqual(res['fin'], 1)
|
||||
self.assertEqual(res['opcode'], 0x2)
|
||||
self.assertEqual(res['length'], len(buf))
|
||||
self.assertEqual(res['payload'], data)
|
||||
|
||||
def test_daemonize_EBADF_error(self):
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=1, idle_timeout=1)
|
||||
self.stubs.Set(os, 'fork', lambda *args: None)
|
||||
self.stubs.Set(os, 'setsid', lambda *args: None)
|
||||
self.stubs.Set(os, 'close', self._mock_os_close_oserror_EBADF)
|
||||
self.stubs.Set(os, 'open', self._mock_os_open_oserror)
|
||||
self.assertRaises(OSError, soc.daemonize, keepfd=None, chdir='./')
|
||||
def test_decode_hybi_extended_64bit_binary(self):
|
||||
data = (b'\x01\x02\x03\x04' * 65) # len > 126 -- len == 260
|
||||
buf = b'\x82\x7f\x00\x00\x00\x00\x00\x00\x01\x04' + data
|
||||
ws = websocket.WebSocket()
|
||||
res = ws._decode_hybi(buf)
|
||||
|
||||
def test_decode_hybi(self):
|
||||
soc = self._get_websockserver(daemon=False, ssl_only=1, idle_timeout=1)
|
||||
self.assertRaises(Exception, soc.decode_hybi, 'a' * 128,
|
||||
base64=True)
|
||||
self.assertEqual(res['fin'], 1)
|
||||
self.assertEqual(res['opcode'], 0x2)
|
||||
self.assertEqual(res['length'], len(buf))
|
||||
self.assertEqual(res['payload'], data)
|
||||
|
||||
def test_do_websocket_handshake(self):
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
soc.scheme = 'scheme'
|
||||
headers = {'Sec-WebSocket-Protocol': 'binary',
|
||||
'Sec-WebSocket-Version': '7',
|
||||
'Sec-WebSocket-Key': 'foo'}
|
||||
soc.do_websocket_handshake(headers, '127.0.0.1')
|
||||
def test_decode_hybi_multi(self):
|
||||
buf1 = b'\x01\x03\x48\x65\x6c'
|
||||
buf2 = b'\x80\x02\x6c\x6f'
|
||||
|
||||
def test_do_handshake(self):
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
self.stubs.Set(select, 'select', self._mock_select)
|
||||
self.stubs.Set(socket._socketobject, 'recv', lambda *args: 'mock_recv')
|
||||
self.assertRaises(Exception, soc.do_handshake, self.soc, '127.0.0.1')
|
||||
ws = websocket.WebSocket()
|
||||
|
||||
def test_do_handshake_ssl_error(self):
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
res1 = ws._decode_hybi(buf1)
|
||||
self.assertEqual(res1['fin'], 0)
|
||||
self.assertEqual(res1['opcode'], 0x1)
|
||||
self.assertEqual(res1['length'], len(buf1))
|
||||
self.assertEqual(res1['payload'], b'Hel')
|
||||
|
||||
def _mock_wrap_socket(*args, **kwargs):
|
||||
from ssl import SSLError
|
||||
raise SSLError('unit test exception')
|
||||
res2 = ws._decode_hybi(buf2)
|
||||
self.assertEqual(res2['fin'], 1)
|
||||
self.assertEqual(res2['opcode'], 0x0)
|
||||
self.assertEqual(res2['length'], len(buf2))
|
||||
self.assertEqual(res2['payload'], b'lo')
|
||||
|
||||
self.stubs.Set(select, 'select', self._mock_select)
|
||||
self.stubs.Set(socket._socketobject, 'recv', lambda *args: '\x16')
|
||||
self.stubs.Set(ssl, 'wrap_socket', _mock_wrap_socket)
|
||||
self.assertRaises(SSLError, soc.do_handshake, self.soc, '127.0.0.1')
|
||||
def test_encode_hybi_basic(self):
|
||||
ws = websocket.WebSocket()
|
||||
res = ws._encode_hybi(0x1, b'Hello')
|
||||
expected = b'\x81\x05\x48\x65\x6c\x6c\x6f'
|
||||
|
||||
def test_fallback_SIGCHILD(self):
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
soc.fallback_SIGCHLD(None, None)
|
||||
|
||||
def test_start_server_Exception(self):
|
||||
soc = self._get_websockserver(daemon=False, ssl_only=1, idle_timeout=1)
|
||||
self.stubs.Set(websocket.WebSocketServer, 'socket', self._mock_socket)
|
||||
self.stubs.Set(websocket.WebSocketServer, 'daemonize',
|
||||
lambda *args, **kwargs: None)
|
||||
self.stubs.Set(select, 'select', self._mock_select_exception)
|
||||
self.assertEqual(None, soc.start_server())
|
||||
|
||||
def test_start_server_KeyboardInterrupt(self):
|
||||
soc = self._get_websockserver(daemon=False, ssl_only=1, idle_timeout=1)
|
||||
self.stubs.Set(websocket.WebSocketServer, 'socket', self._mock_socket)
|
||||
self.stubs.Set(websocket.WebSocketServer, 'daemonize',
|
||||
lambda *args, **kwargs: None)
|
||||
self.stubs.Set(select, 'select', self._mock_select_keyboardinterrupt)
|
||||
self.assertEqual(None, soc.start_server())
|
||||
|
||||
def test_start_server_systemexit(self):
|
||||
websocket.ssl = None
|
||||
self.stubs.Set(websocket.WebSocketServer, 'socket', self._mock_socket)
|
||||
self.stubs.Set(websocket.WebSocketServer, 'daemonize',
|
||||
lambda *args, **kwargs: None)
|
||||
self.stubs.Set(select, 'select', self._mock_select_systemexit)
|
||||
soc = self._get_websockserver(daemon=True, ssl_only=0, idle_timeout=1,
|
||||
verbose=True)
|
||||
self.assertEqual(None, soc.start_server())
|
||||
|
||||
def test_WSRequestHandle_do_GET_nofile(self):
|
||||
request = 'GET /tmp.txt HTTP/0.9'
|
||||
with tempfile.NamedTemporaryFile() as test_file:
|
||||
test_file.write(request)
|
||||
test_file.flush()
|
||||
test_file.seek(0)
|
||||
con = MockConnection(test_file.name)
|
||||
soc = websocket.WSRequestHandler(con, "127.0.0.1", file_only=True)
|
||||
soc.path = ''
|
||||
soc.headers = {'upgrade': ''}
|
||||
self.stubs.Set(SimpleHTTPRequestHandler, 'send_response',
|
||||
lambda *args: None)
|
||||
soc.do_GET()
|
||||
self.assertEqual(404, soc.last_code)
|
||||
|
||||
def test_WSRequestHandle_do_GET_hidden_resource(self):
|
||||
request = 'GET /tmp.txt HTTP/0.9'
|
||||
with tempfile.NamedTemporaryFile() as test_file:
|
||||
test_file.write(request)
|
||||
test_file.flush()
|
||||
test_file.seek(0)
|
||||
con = MockConnection(test_file.name)
|
||||
soc = websocket.WSRequestHandler(con, '127.0.0.1', no_parent=True)
|
||||
soc.path = test_file.name + '?'
|
||||
soc.headers = {'upgrade': ''}
|
||||
soc.webroot = 'no match startswith'
|
||||
self.stubs.Set(SimpleHTTPRequestHandler,
|
||||
'send_response',
|
||||
lambda *args: None)
|
||||
soc.do_GET()
|
||||
self.assertEqual(403, soc.last_code)
|
||||
|
||||
def testsocket_set_keepalive_options(self):
|
||||
keepcnt = 12
|
||||
keepidle = 34
|
||||
keepintvl = 56
|
||||
|
||||
sock = self.server.socket('localhost',
|
||||
tcp_keepcnt=keepcnt,
|
||||
tcp_keepidle=keepidle,
|
||||
tcp_keepintvl=keepintvl)
|
||||
|
||||
self.assertEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPCNT), keepcnt)
|
||||
self.assertEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPIDLE), keepidle)
|
||||
self.assertEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPINTVL), keepintvl)
|
||||
|
||||
sock = self.server.socket('localhost',
|
||||
tcp_keepalive=False,
|
||||
tcp_keepcnt=keepcnt,
|
||||
tcp_keepidle=keepidle,
|
||||
tcp_keepintvl=keepintvl)
|
||||
|
||||
self.assertNotEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPCNT), keepcnt)
|
||||
self.assertNotEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPIDLE), keepidle)
|
||||
self.assertNotEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPINTVL), keepintvl)
|
||||
self.assertEqual(res, expected)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright(c)2013 NTT corp. All Rights Reserved.
|
||||
# Copyright(c) 2015 Red Hat, Inc All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
@@ -15,113 +15,132 @@
|
||||
# under the License.
|
||||
|
||||
""" Unit tests for websocketproxy """
|
||||
import os
|
||||
import logging
|
||||
import select
|
||||
import shutil
|
||||
import stubout
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import unittest
|
||||
import unittest
|
||||
import socket
|
||||
|
||||
from mox3 import stubout
|
||||
|
||||
from websockify import websockifyserver
|
||||
from websockify import websocketproxy
|
||||
from websockify import token_plugins
|
||||
from websockify import auth_plugins
|
||||
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
BytesIO = StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
class MockSocket(object):
|
||||
def __init__(*args, **kwargs):
|
||||
class FakeSocket(object):
|
||||
def __init__(self, data=''):
|
||||
if isinstance(data, bytes):
|
||||
self._data = data
|
||||
else:
|
||||
self._data = data.encode('latin_1')
|
||||
|
||||
def recv(self, amt, flags=None):
|
||||
res = self._data[0:amt]
|
||||
if not (flags & socket.MSG_PEEK):
|
||||
self._data = self._data[amt:]
|
||||
|
||||
return res
|
||||
|
||||
def makefile(self, mode='r', buffsize=None):
|
||||
if 'b' in mode:
|
||||
return BytesIO(self._data)
|
||||
else:
|
||||
return StringIO(self._data.decode('latin_1'))
|
||||
|
||||
|
||||
class FakeServer(object):
|
||||
class EClose(Exception):
|
||||
pass
|
||||
|
||||
def shutdown(*args):
|
||||
pass
|
||||
|
||||
def close(*args):
|
||||
pass
|
||||
|
||||
|
||||
class WebSocketProxyTest(unittest.TestCase):
|
||||
|
||||
def _init_logger(self, tmpdir):
|
||||
name = 'websocket-unittest'
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.propagate = True
|
||||
filename = "%s.log" % (name)
|
||||
handler = logging.FileHandler(filename)
|
||||
handler.setFormatter(logging.Formatter("%(message)s"))
|
||||
logger.addHandler(handler)
|
||||
def __init__(self):
|
||||
self.token_plugin = None
|
||||
self.auth_plugin = None
|
||||
self.wrap_cmd = None
|
||||
self.ssl_target = None
|
||||
self.unix_target = None
|
||||
|
||||
class ProxyRequestHandlerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
"""Called automatically before each test."""
|
||||
super(WebSocketProxyTest, self).setUp()
|
||||
self.soc = ''
|
||||
super(ProxyRequestHandlerTestCase, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
# Temporary dir for test data
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
# Put log somewhere persistent
|
||||
self._init_logger('./')
|
||||
# Mock this out cause it screws tests up
|
||||
self.stubs.Set(os, 'chdir', lambda *args, **kwargs: None)
|
||||
self.handler = websocketproxy.ProxyRequestHandler(
|
||||
FakeSocket(''), "127.0.0.1", FakeServer())
|
||||
self.handler.path = "https://localhost:6080/websockify?token=blah"
|
||||
self.handler.headers = None
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
|
||||
staticmethod(lambda *args, **kwargs: None))
|
||||
|
||||
def tearDown(self):
|
||||
"""Called automatically after each test."""
|
||||
self.stubs.UnsetAll()
|
||||
shutil.rmtree(self.tmpdir)
|
||||
super(WebSocketProxyTest, self).tearDown()
|
||||
super(ProxyRequestHandlerTestCase, self).tearDown()
|
||||
|
||||
def _get_websockproxy(self, **kwargs):
|
||||
return websocketproxy.WebSocketProxy(key=self.tmpdir,
|
||||
web=self.tmpdir,
|
||||
record=self.tmpdir,
|
||||
**kwargs)
|
||||
def test_get_target(self):
|
||||
class TestPlugin(token_plugins.BasePlugin):
|
||||
def lookup(self, token):
|
||||
return ("some host", "some port")
|
||||
|
||||
def test_run_wrap_cmd(self):
|
||||
web_socket_proxy = self._get_websockproxy()
|
||||
web_socket_proxy.__dict__["wrap_cmd"] = "wrap_cmd"
|
||||
host, port = self.handler.get_target(
|
||||
TestPlugin(None), self.handler.path)
|
||||
|
||||
def mock_Popen(*args, **kwargs):
|
||||
return '_mock_cmd'
|
||||
self.assertEqual(host, "some host")
|
||||
self.assertEqual(port, "some port")
|
||||
|
||||
self.stubs.Set(subprocess, 'Popen', mock_Popen)
|
||||
web_socket_proxy.run_wrap_cmd()
|
||||
self.assertEquals(web_socket_proxy.spawn_message, True)
|
||||
def test_get_target_unix_socket(self):
|
||||
class TestPlugin(token_plugins.BasePlugin):
|
||||
def lookup(self, token):
|
||||
return ("unix_socket", "/tmp/socket")
|
||||
|
||||
def test_started(self):
|
||||
web_socket_proxy = self._get_websockproxy()
|
||||
web_socket_proxy.__dict__["spawn_message"] = False
|
||||
web_socket_proxy.__dict__["wrap_cmd"] = "wrap_cmd"
|
||||
_, socket = self.handler.get_target(
|
||||
TestPlugin(None), self.handler.path)
|
||||
|
||||
def mock_run_wrap_cmd(*args, **kwargs):
|
||||
web_socket_proxy.__dict__["spawn_message"] = True
|
||||
self.assertEqual(socket, "/tmp/socket")
|
||||
|
||||
self.stubs.Set(web_socket_proxy, 'run_wrap_cmd', mock_run_wrap_cmd)
|
||||
web_socket_proxy.started()
|
||||
self.assertEquals(web_socket_proxy.__dict__["spawn_message"], True)
|
||||
def test_get_target_raises_error_on_unknown_token(self):
|
||||
class TestPlugin(token_plugins.BasePlugin):
|
||||
def lookup(self, token):
|
||||
return None
|
||||
|
||||
def test_poll(self):
|
||||
web_socket_proxy = self._get_websockproxy()
|
||||
web_socket_proxy.__dict__["wrap_cmd"] = "wrap_cmd"
|
||||
web_socket_proxy.__dict__["wrap_mode"] = "respawn"
|
||||
web_socket_proxy.__dict__["wrap_times"] = [99999999]
|
||||
web_socket_proxy.__dict__["spawn_message"] = True
|
||||
web_socket_proxy.__dict__["cmd"] = None
|
||||
self.stubs.Set(time, 'time', lambda: 100000000.000)
|
||||
web_socket_proxy.poll()
|
||||
self.assertEquals(web_socket_proxy.spawn_message, False)
|
||||
self.assertRaises(FakeServer.EClose, self.handler.get_target,
|
||||
TestPlugin(None), "https://localhost:6080/websockify?token=blah")
|
||||
|
||||
def test_new_client(self):
|
||||
web_socket_proxy = self._get_websockproxy()
|
||||
web_socket_proxy.__dict__["verbose"] = "verbose"
|
||||
web_socket_proxy.__dict__["daemon"] = None
|
||||
web_socket_proxy.__dict__["client"] = "client"
|
||||
def test_token_plugin(self):
|
||||
class TestPlugin(token_plugins.BasePlugin):
|
||||
def lookup(self, token):
|
||||
return (self.source + token).split(',')
|
||||
|
||||
self.stubs.Set(web_socket_proxy, 'socket', MockSocket)
|
||||
self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
|
||||
staticmethod(lambda *args, **kwargs: None))
|
||||
|
||||
def mock_select(*args, **kwargs):
|
||||
ins = None
|
||||
outs = None
|
||||
excepts = "excepts"
|
||||
return ins, outs, excepts
|
||||
self.handler.server.token_plugin = TestPlugin("somehost,")
|
||||
self.handler.validate_connection()
|
||||
|
||||
self.assertEqual(self.handler.server.target_host, "somehost")
|
||||
self.assertEqual(self.handler.server.target_port, "blah")
|
||||
|
||||
def test_auth_plugin(self):
|
||||
class TestPlugin(auth_plugins.BasePlugin):
|
||||
def authenticate(self, headers, target_host, target_port):
|
||||
if target_host == self.source:
|
||||
raise auth_plugins.AuthenticationError(response_msg="some_error")
|
||||
|
||||
self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
|
||||
staticmethod(lambda *args, **kwargs: None))
|
||||
|
||||
self.handler.server.auth_plugin = TestPlugin("somehost")
|
||||
self.handler.server.target_host = "somehost"
|
||||
self.handler.server.target_port = "someport"
|
||||
|
||||
self.assertRaises(auth_plugins.AuthenticationError,
|
||||
self.handler.validate_connection)
|
||||
|
||||
self.handler.server.target_host = "someotherhost"
|
||||
self.handler.validate_connection()
|
||||
|
||||
self.stubs.Set(select, 'select', mock_select)
|
||||
self.assertRaises(Exception, web_socket_proxy.new_websocket_client)
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright(c)2013 NTT corp. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
""" Unit tests for websockifyserver """
|
||||
import errno
|
||||
import os
|
||||
import logging
|
||||
import select
|
||||
import shutil
|
||||
import socket
|
||||
import ssl
|
||||
from mox3 import stubout
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import socket
|
||||
import signal
|
||||
from websockify import websockifyserver
|
||||
|
||||
try:
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
except ImportError:
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
|
||||
try:
|
||||
from StringIO import StringIO
|
||||
BytesIO = StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
|
||||
|
||||
def raise_oserror(*args, **kwargs):
|
||||
raise OSError('fake error')
|
||||
|
||||
|
||||
class FakeSocket(object):
|
||||
def __init__(self, data=''):
|
||||
if isinstance(data, bytes):
|
||||
self._data = data
|
||||
else:
|
||||
self._data = data.encode('latin_1')
|
||||
|
||||
def recv(self, amt, flags=None):
|
||||
res = self._data[0:amt]
|
||||
if not (flags & socket.MSG_PEEK):
|
||||
self._data = self._data[amt:]
|
||||
|
||||
return res
|
||||
|
||||
def makefile(self, mode='r', buffsize=None):
|
||||
if 'b' in mode:
|
||||
return BytesIO(self._data)
|
||||
else:
|
||||
return StringIO(self._data.decode('latin_1'))
|
||||
|
||||
|
||||
class WebSockifyRequestHandlerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super(WebSockifyRequestHandlerTestCase, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
self.tmpdir = tempfile.mkdtemp('-websockify-tests')
|
||||
# Mock this out cause it screws tests up
|
||||
self.stubs.Set(os, 'chdir', lambda *args, **kwargs: None)
|
||||
self.stubs.Set(BaseHTTPRequestHandler, 'send_response',
|
||||
lambda *args, **kwargs: None)
|
||||
|
||||
def tearDown(self):
|
||||
"""Called automatically after each test."""
|
||||
self.stubs.UnsetAll()
|
||||
os.rmdir(self.tmpdir)
|
||||
super(WebSockifyRequestHandlerTestCase, self).tearDown()
|
||||
|
||||
def _get_server(self, handler_class=websockifyserver.WebSockifyRequestHandler,
|
||||
**kwargs):
|
||||
web = kwargs.pop('web', self.tmpdir)
|
||||
return websockifyserver.WebSockifyServer(
|
||||
handler_class, listen_host='localhost',
|
||||
listen_port=80, key=self.tmpdir, web=web,
|
||||
record=self.tmpdir, daemon=False, ssl_only=0, idle_timeout=1,
|
||||
**kwargs)
|
||||
|
||||
def test_normal_get_with_only_upgrade_returns_error(self):
|
||||
server = self._get_server(web=None)
|
||||
handler = websockifyserver.WebSockifyRequestHandler(
|
||||
FakeSocket('GET /tmp.txt HTTP/1.1'), '127.0.0.1', server)
|
||||
|
||||
def fake_send_response(self, code, message=None):
|
||||
self.last_code = code
|
||||
|
||||
self.stubs.Set(BaseHTTPRequestHandler, 'send_response',
|
||||
fake_send_response)
|
||||
|
||||
handler.do_GET()
|
||||
self.assertEqual(handler.last_code, 405)
|
||||
|
||||
def test_list_dir_with_file_only_returns_error(self):
|
||||
server = self._get_server(file_only=True)
|
||||
handler = websockifyserver.WebSockifyRequestHandler(
|
||||
FakeSocket('GET / HTTP/1.1'), '127.0.0.1', server)
|
||||
|
||||
def fake_send_response(self, code, message=None):
|
||||
self.last_code = code
|
||||
|
||||
self.stubs.Set(BaseHTTPRequestHandler, 'send_response',
|
||||
fake_send_response)
|
||||
|
||||
handler.path = '/'
|
||||
handler.do_GET()
|
||||
self.assertEqual(handler.last_code, 404)
|
||||
|
||||
|
||||
class WebSockifyServerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super(WebSockifyServerTestCase, self).setUp()
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
self.tmpdir = tempfile.mkdtemp('-websockify-tests')
|
||||
# Mock this out cause it screws tests up
|
||||
self.stubs.Set(os, 'chdir', lambda *args, **kwargs: None)
|
||||
|
||||
def tearDown(self):
|
||||
"""Called automatically after each test."""
|
||||
self.stubs.UnsetAll()
|
||||
os.rmdir(self.tmpdir)
|
||||
super(WebSockifyServerTestCase, self).tearDown()
|
||||
|
||||
def _get_server(self, handler_class=websockifyserver.WebSockifyRequestHandler,
|
||||
**kwargs):
|
||||
return websockifyserver.WebSockifyServer(
|
||||
handler_class, listen_host='localhost',
|
||||
listen_port=80, key=self.tmpdir, web=self.tmpdir,
|
||||
record=self.tmpdir, **kwargs)
|
||||
|
||||
def test_daemonize_raises_error_while_closing_fds(self):
|
||||
server = self._get_server(daemon=True, ssl_only=1, idle_timeout=1)
|
||||
self.stubs.Set(os, 'fork', lambda *args: 0)
|
||||
self.stubs.Set(signal, 'signal', lambda *args: None)
|
||||
self.stubs.Set(os, 'setsid', lambda *args: None)
|
||||
self.stubs.Set(os, 'close', raise_oserror)
|
||||
self.assertRaises(OSError, server.daemonize, keepfd=None, chdir='./')
|
||||
|
||||
def test_daemonize_ignores_ebadf_error_while_closing_fds(self):
|
||||
def raise_oserror_ebadf(fd):
|
||||
raise OSError(errno.EBADF, 'fake error')
|
||||
|
||||
server = self._get_server(daemon=True, ssl_only=1, idle_timeout=1)
|
||||
self.stubs.Set(os, 'fork', lambda *args: 0)
|
||||
self.stubs.Set(os, 'setsid', lambda *args: None)
|
||||
self.stubs.Set(signal, 'signal', lambda *args: None)
|
||||
self.stubs.Set(os, 'close', raise_oserror_ebadf)
|
||||
self.stubs.Set(os, 'open', raise_oserror)
|
||||
self.assertRaises(OSError, server.daemonize, keepfd=None, chdir='./')
|
||||
|
||||
def test_handshake_fails_on_not_ready(self):
|
||||
server = self._get_server(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
return ([], [], [])
|
||||
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
self.assertRaises(
|
||||
websockifyserver.WebSockifyServer.EClose, server.do_handshake,
|
||||
FakeSocket(), '127.0.0.1')
|
||||
|
||||
def test_empty_handshake_fails(self):
|
||||
server = self._get_server(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
|
||||
sock = FakeSocket('')
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
return ([sock], [], [])
|
||||
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
self.assertRaises(
|
||||
websockifyserver.WebSockifyServer.EClose, server.do_handshake,
|
||||
sock, '127.0.0.1')
|
||||
|
||||
def test_handshake_policy_request(self):
|
||||
# TODO(directxman12): implement
|
||||
pass
|
||||
|
||||
def test_handshake_ssl_only_without_ssl_raises_error(self):
|
||||
server = self._get_server(daemon=True, ssl_only=1, idle_timeout=1)
|
||||
|
||||
sock = FakeSocket('some initial data')
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
return ([sock], [], [])
|
||||
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
self.assertRaises(
|
||||
websockifyserver.WebSockifyServer.EClose, server.do_handshake,
|
||||
sock, '127.0.0.1')
|
||||
|
||||
def test_do_handshake_no_ssl(self):
|
||||
class FakeHandler(object):
|
||||
CALLED = False
|
||||
def __init__(self, *args, **kwargs):
|
||||
type(self).CALLED = True
|
||||
|
||||
FakeHandler.CALLED = False
|
||||
|
||||
server = self._get_server(
|
||||
handler_class=FakeHandler, daemon=True,
|
||||
ssl_only=0, idle_timeout=1)
|
||||
|
||||
sock = FakeSocket('some initial data')
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
return ([sock], [], [])
|
||||
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
self.assertEqual(server.do_handshake(sock, '127.0.0.1'), sock)
|
||||
self.assertTrue(FakeHandler.CALLED, True)
|
||||
|
||||
def test_do_handshake_ssl(self):
|
||||
# TODO(directxman12): implement this
|
||||
pass
|
||||
|
||||
def test_do_handshake_ssl_without_ssl_raises_error(self):
|
||||
# TODO(directxman12): implement this
|
||||
pass
|
||||
|
||||
def test_do_handshake_ssl_without_cert_raises_error(self):
|
||||
server = self._get_server(daemon=True, ssl_only=0, idle_timeout=1,
|
||||
cert='afdsfasdafdsafdsafdsafdas')
|
||||
|
||||
sock = FakeSocket("\x16some ssl data")
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
return ([sock], [], [])
|
||||
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
self.assertRaises(
|
||||
websockifyserver.WebSockifyServer.EClose, server.do_handshake,
|
||||
sock, '127.0.0.1')
|
||||
|
||||
def test_do_handshake_ssl_error_eof_raises_close_error(self):
|
||||
server = self._get_server(daemon=True, ssl_only=0, idle_timeout=1)
|
||||
|
||||
sock = FakeSocket("\x16some ssl data")
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
return ([sock], [], [])
|
||||
|
||||
def fake_wrap_socket(*args, **kwargs):
|
||||
raise ssl.SSLError(ssl.SSL_ERROR_EOF)
|
||||
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
self.stubs.Set(ssl, 'wrap_socket', fake_wrap_socket)
|
||||
self.assertRaises(
|
||||
websockifyserver.WebSockifyServer.EClose, server.do_handshake,
|
||||
sock, '127.0.0.1')
|
||||
|
||||
def test_fallback_sigchld_handler(self):
|
||||
# TODO(directxman12): implement this
|
||||
pass
|
||||
|
||||
def test_start_server_error(self):
|
||||
server = self._get_server(daemon=False, ssl_only=1, idle_timeout=1)
|
||||
sock = server.socket('localhost')
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
raise Exception("fake error")
|
||||
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
|
||||
lambda *args, **kwargs: sock)
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'daemonize',
|
||||
lambda *args, **kwargs: None)
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
server.start_server()
|
||||
|
||||
def test_start_server_keyboardinterrupt(self):
|
||||
server = self._get_server(daemon=False, ssl_only=0, idle_timeout=1)
|
||||
sock = server.socket('localhost')
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
raise KeyboardInterrupt
|
||||
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
|
||||
lambda *args, **kwargs: sock)
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'daemonize',
|
||||
lambda *args, **kwargs: None)
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
server.start_server()
|
||||
|
||||
def test_start_server_systemexit(self):
|
||||
server = self._get_server(daemon=False, ssl_only=0, idle_timeout=1)
|
||||
sock = server.socket('localhost')
|
||||
|
||||
def fake_select(rlist, wlist, xlist, timeout=None):
|
||||
sys.exit()
|
||||
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
|
||||
lambda *args, **kwargs: sock)
|
||||
self.stubs.Set(websockifyserver.WebSockifyServer, 'daemonize',
|
||||
lambda *args, **kwargs: None)
|
||||
self.stubs.Set(select, 'select', fake_select)
|
||||
server.start_server()
|
||||
|
||||
def test_socket_set_keepalive_options(self):
|
||||
keepcnt = 12
|
||||
keepidle = 34
|
||||
keepintvl = 56
|
||||
|
||||
server = self._get_server(daemon=False, ssl_only=0, idle_timeout=1)
|
||||
sock = server.socket('localhost',
|
||||
tcp_keepcnt=keepcnt,
|
||||
tcp_keepidle=keepidle,
|
||||
tcp_keepintvl=keepintvl)
|
||||
|
||||
if hasattr(socket, 'TCP_KEEPCNT'):
|
||||
self.assertEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPCNT), keepcnt)
|
||||
self.assertEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPIDLE), keepidle)
|
||||
self.assertEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPINTVL), keepintvl)
|
||||
|
||||
sock = server.socket('localhost',
|
||||
tcp_keepalive=False,
|
||||
tcp_keepcnt=keepcnt,
|
||||
tcp_keepidle=keepidle,
|
||||
tcp_keepintvl=keepintvl)
|
||||
|
||||
if hasattr(socket, 'TCP_KEEPCNT'):
|
||||
self.assertNotEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPCNT), keepcnt)
|
||||
self.assertNotEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPIDLE), keepidle)
|
||||
self.assertNotEqual(sock.getsockopt(socket.SOL_TCP,
|
||||
socket.TCP_KEEPINTVL), keepintvl)
|
||||
@@ -1,20 +0,0 @@
|
||||
# Tox (http://tox.testrun.org/) is a tool for running tests
|
||||
# in multiple virtualenvs. This configuration file will run the
|
||||
# test suite on all supported python versions. To use it, "pip install tox"
|
||||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py24,py25,py26,py27,py30
|
||||
setupdir = ../
|
||||
|
||||
[testenv]
|
||||
commands = nosetests {posargs}
|
||||
deps =
|
||||
mox
|
||||
nose
|
||||
|
||||
# At some point we should enable this since tox epdctes it to exist but
|
||||
# the code will need pep8ising first.
|
||||
#[testenv:pep8]
|
||||
#commands = flake8
|
||||
#dep = flake8
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
'''
|
||||
Display UTF-8 encoding for 0-255.'''
|
||||
|
||||
import sys, os, socket, ssl, time, traceback
|
||||
from select import select
|
||||
sys.path.insert(0,os.path.join(os.path.dirname(__file__), ".."))
|
||||
from websockify.websocket import WebSocketServer
|
||||
|
||||
if __name__ == '__main__':
|
||||
print "val: hybi_base64 | hybi_binary"
|
||||
for c in range(0, 256):
|
||||
hybi_base64 = WebSocketServer.encode_hybi(chr(c), opcode=1,
|
||||
base64=True)
|
||||
hybi_binary = WebSocketServer.encode_hybi(chr(c), opcode=2,
|
||||
base64=False)
|
||||
print "%d: %s | %s" % (c, repr(hybi_base64), repr(hybi_binary))
|
||||
|
||||
Reference in New Issue
Block a user