Moved websocket.py code into a class WebSocketServer. WebSockets server implementations will sub-class and define a handler() method which is passed the client socket after. Global variable settings have been changed to be parameters for WebSocketServer when created. Subclass implementations still have to handle queueing and sending but the parent class handles everything else (daemonizing, websocket handshake, encode/decode, etc). It would be better if the parent class could handle queueing and sending. This adds some buffering and polling complexity to the parent class but it would be better to do so at some point. However, the result is still much cleaner as can be seen in wsecho.py. Refactored wsproxy.py and wstest.py (formerly ws.py) to use the new class. Added wsecho.py as a simple echo server. - rename tests/ws.py to utils/wstest.py and add a symlink from tests/wstest.py - rename tests/ws.html to tests/wstest.html to match utils/wstest.py. - add utils/wsecho.py - add tests/wsecho.html which communicates with wsecho.py and simply sends periodic messages and shows what is received.
177 lines
5.4 KiB
HTML
177 lines
5.4 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<title>WebSockets Echo Test</title>
|
|
<script src="include/base64.js"></script>
|
|
<script src="include/util.js"></script>
|
|
<script src="include/webutil.js"></script>
|
|
<!-- Uncomment to activate firebug lite -->
|
|
<!--
|
|
<script type='text/javascript'
|
|
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
|
|
-->
|
|
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
Host: <input id='host' style='width:100'>
|
|
Port: <input id='port' style='width:50'>
|
|
Encrypt: <input id='encrypt' type='checkbox'>
|
|
<input id='connectButton' type='button' value='Start' style='width:100px'
|
|
onclick="connect();">
|
|
|
|
|
|
<br>
|
|
Log:<br>
|
|
<textarea id="messages" style="font-size: 9;" cols=80 rows=25></textarea>
|
|
</body>
|
|
|
|
|
|
<script>
|
|
var ws, host = null, port = null,
|
|
msg_cnt = 0, send_cnt = 1, echoDelay = 500,
|
|
echo_ref;
|
|
|
|
function message(str) {
|
|
console.log(str);
|
|
cell = $D('messages');
|
|
cell.innerHTML += msg_cnt + ": " + str + "\n";
|
|
cell.scrollTop = cell.scrollHeight;
|
|
msg_cnt++;
|
|
}
|
|
|
|
Array.prototype.pushStr = function (str) {
|
|
var n = str.length;
|
|
for (var i=0; i < n; i++) {
|
|
this.push(str.charCodeAt(i));
|
|
}
|
|
}
|
|
|
|
function send_msg() {
|
|
if (ws.bufferedAmount > 0) {
|
|
console.log("Delaying send");
|
|
return;
|
|
}
|
|
var str = "Message #" + send_cnt, arr = [];
|
|
arr.pushStr(str)
|
|
ws.send(Base64.encode(arr));
|
|
message("Sent message: '" + str + "'");
|
|
send_cnt++;
|
|
}
|
|
|
|
function update_stats() {
|
|
$D('sent').innerHTML = sent;
|
|
$D('received').innerHTML = received;
|
|
$D('errors').innerHTML = errors;
|
|
}
|
|
|
|
function init_ws() {
|
|
console.log(">> init_ws");
|
|
console.log("<< init_ws");
|
|
}
|
|
|
|
function connect() {
|
|
var host = $D('host').value,
|
|
port = $D('port').value,
|
|
scheme = "ws://", uri;
|
|
|
|
console.log(">> connect");
|
|
if ((!host) || (!port)) {
|
|
console.log("must set host and port");
|
|
return;
|
|
}
|
|
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
|
|
if ($D('encrypt').checked) {
|
|
scheme = "wss://";
|
|
}
|
|
uri = scheme + host + ":" + port;
|
|
message("connecting to " + uri);
|
|
ws = new WebSocket(uri);
|
|
|
|
ws.onmessage = function(e) {
|
|
//console.log(">> WebSockets.onmessage");
|
|
var arr = Base64.decode(e.data), str = "", i;
|
|
|
|
for (i = 0; i < arr.length; i++) {
|
|
str = str + String.fromCharCode(arr[i]);
|
|
}
|
|
|
|
message("Received message '" + str + "'");
|
|
//console.log("<< WebSockets.onmessage");
|
|
};
|
|
ws.onopen = function(e) {
|
|
console.log(">> WebSockets.onopen");
|
|
echo_ref = setInterval(send_msg, echoDelay);
|
|
console.log("<< WebSockets.onopen");
|
|
};
|
|
ws.onclose = function(e) {
|
|
console.log(">> WebSockets.onclose");
|
|
if (echo_ref) {
|
|
clearInterval(echo_ref);
|
|
echo_ref = null;
|
|
}
|
|
console.log("<< WebSockets.onclose");
|
|
};
|
|
ws.onerror = function(e) {
|
|
console.log(">> WebSockets.onerror");
|
|
if (echo_ref) {
|
|
clearInterval(echo_ref);
|
|
echo_ref = null;
|
|
}
|
|
console.log("<< WebSockets.onerror");
|
|
};
|
|
|
|
$D('connectButton').value = "Stop";
|
|
$D('connectButton').onclick = disconnect;
|
|
console.log("<< connect");
|
|
}
|
|
|
|
function disconnect() {
|
|
console.log(">> disconnect");
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
|
|
if (echo_ref) {
|
|
clearInterval(echo_ref);
|
|
}
|
|
|
|
$D('connectButton').value = "Start";
|
|
$D('connectButton').onclick = connect;
|
|
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];
|
|
}
|
|
</script>
|
|
|
|
</html>
|