Эх сурвалжийг харах

Add WebSockets test frontend and backend.

Joel Martin 15 жил өмнө
parent
commit
89fbd66fa9
2 өөрчлөгдсөн 324 нэмэгдсэн , 0 устгасан
  1. 182 0
      wstest.html
  2. 142 0
      wstest.py

+ 182 - 0
wstest.html

@@ -0,0 +1,182 @@
+<html>
+
+    <head><title>WebSockets Test</title></head>
+
+    <body>
+
+        Host: <input id='host' style='width:100'>&nbsp;
+        Port: <input id='port' style='width:50'>&nbsp;
+        Send Delay (ms): <input id='sendDelay' style='width:50' value="100">&nbsp;
+        <input id='connectButton' type='button' value='Start' style='width:100px'
+            onclick="connect();">&nbsp;
+
+        <br><br>
+        <table border=1>
+            <tr>
+                <th align="right">Packets sent:</th>
+                <td align="right"><div id='sent'>0</div></td>
+            </tr><tr>
+                <th align="right">Good Packets Received:</th>
+                <td align="right"><div id='received'>0</div></td>
+            </tr><tr>
+                <th align="right">Errors (Bad Packets Received:)</th>
+                <td align="right"><div id='errors'>0</div></td>
+            </tr>
+        </table>
+
+    </body>
+
+    <script src="include/mootools.js"></script>
+    <script src="include/base64.js"></script>
+    <script src="include/util.js"></script>
+
+    <script>
+
+        var host = null, port = null, sendDelay = 0;
+        var ws = null, update_ref = null, send_ref = null;
+        var sent = 0, received = 0, errors = 0;
+
+        Array.prototype.pushStr = function (str) {
+            var n = str.length;
+            for (var i=0; i < n; i++) {
+                this.push(str.charCodeAt(i));
+            }
+        }
+
+
+
+        function add (x,y) {
+            return parseInt(x,10)+parseInt(y,10);
+        }
+
+        function check_respond(data) {
+            //console.log(">> check_respond");
+            var decoded, str, length, chksum, nums, arr;
+            decoded = Base64.decode(data);
+            arr = decoded.map(function(num) {
+                    return String.fromCharCode(num); 
+                } ).join('').split(':');
+            length = arr[0];
+            chksum = arr[1];
+            nums = arr[2];
+            //console.log("   length:" + length + " chksum:" + chksum + " nums:" + nums);
+            if (nums.length != length) {
+                console.error("Real length " + nums.length + " is not " + length);
+                errors++;
+                return;
+            }
+            real_chksum = nums.split('').reduce(add);
+            if (real_chksum != chksum) {
+                console.error("Real chksum " + real_chksum + " is not " + chksum);
+                errors++
+                return;
+            }
+            received++;
+            //console.log("   Packet checks out: length:" + length + " chksum:" + chksum);
+            //console.log("<< check_respond");
+        }
+
+        function send() {
+            var length = Math.floor(Math.random()*1991) + 10; // 10 - 2000
+            var numlist = [], arr = [];
+            for (var i=0; i < length; i++) {
+                numlist.push( Math.floor(Math.random()*10) );
+            }
+            chksum = numlist.reduce(add);
+            var nums = numlist.join('');
+            arr.pushStr(length + ":" + chksum + ":" + nums)
+            ws.send(Base64.encode(arr));
+            sent++;
+        }
+
+        function update_stats() {
+            $('sent').innerHTML = sent;
+            $('received').innerHTML = received;
+            $('errors').innerHTML = errors;
+        }
+
+        function init_ws() {
+            console.log(">> init_ws");
+            var uri = "ws://" + host + ":" + port;
+            console.log("connecting to " + uri);
+            ws = new WebSocket(uri);
+            ws.onmessage = function(e) {
+                //console.log(">> WebSockets.onmessage");
+                check_respond(e.data);
+                //console.log("<< WebSockets.onmessage");
+            };
+            ws.onopen = function(e) {
+                console.log(">> WebSockets.onopen");
+                send_ref = send.periodical(sendDelay);
+                console.log("<< WebSockets.onopen");
+            };
+            ws.onclose = function(e) {
+                console.log(">> WebSockets.onclose");
+                console.log("<< WebSockets.onclose");
+            };
+            ws.onerror = function(e) {
+                console.log(">> WebSockets.onerror");
+                console.log("   " + e);
+                console.log("<< WebSockets.onerror");
+            };
+
+            console.log("<< init_ws");
+        }
+
+        function connect() {
+            console.log(">> connect");
+            host = $('host').value;
+            port = $('port').value;
+            sendDelay = parseInt($('sendDelay').value, 10);
+            if ((!host) || (!port)) {
+                console.log("must set host and port");
+                return;
+            }
+
+            if (ws) {
+                ws.close();
+            }
+            init_ws();
+            update_ref = update_stats.periodical(1);
+
+            $('connectButton').value = "Stop";
+            $('connectButton').onclick = disconnect;
+            console.log("<< connect");
+        }
+
+        function disconnect() {
+            console.log(">> disconnect");
+            if (ws) {
+                ws.close();
+            }
+
+            $clear(update_ref);
+            update_stats(); // Final numbers
+
+            $clear(send_ref);
+
+            $('connectButton').value = "Start";
+            $('connectButton').onclick = connect;
+            console.log("<< disconnect");
+        }
+
+
+        /* If no builtin websockets then load web_socket.js */
+        if (! window.WebSocket) {
+            console.log("Loading web-socket-js flash bridge");
+            var extra = "<script src='web-socket-js/swfobject.js'><\/script>";
+            extra += "<script src='web-socket-js/FABridge.js'><\/script>";
+            extra += "<script src='web-socket-js/web_socket.js'><\/script>";
+            document.write(extra);
+        }
+
+        window.onload = function() {
+            WebSocket.__swfLocation = "web-socket-js/WebSocketMain.swf";
+            console.log("onload");
+            var url = document.location.href;
+            $('host').value = (url.match(/host=([^&#]*)/) || ['',''])[1];
+            $('port').value = (url.match(/port=([^&#]*)/) || ['',''])[1];
+        }
+    </script>
+
+</html>

+ 142 - 0
wstest.py

@@ -0,0 +1,142 @@
+#!/usr/bin/python
+
+import sys, os, socket, time, traceback, random, time
+from base64 import b64encode, b64decode
+from select import select
+
+buffer_size = 65536
+
+server_handshake = """HTTP/1.1 101 Web Socket Protocol Handshake\r
+Upgrade: WebSocket\r
+Connection: Upgrade\r
+WebSocket-Origin: %s\r
+WebSocket-Location: ws://%s%s\r
+WebSocket-Protocol: sample\r
+\r
+"""
+
+policy_response = """<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>"""
+
+def handshake(client):
+    handshake = client.recv(1024)
+    print "Handshake [%s]" % handshake
+    if handshake.startswith("<policy-file-request/>"):
+        print "Sending:", policy_response
+        client.send(policy_response)
+        handshake = client.recv(1024)
+        print "Handshake [%s]" % handshake
+    req_lines = handshake.split("\r\n")
+    _, path, _ = req_lines[0].split(" ")
+    _, origin = req_lines[4].split(" ")
+    _, host = req_lines[3].split(" ")
+    client.send(server_handshake % (origin, host, path))
+
+def traffic(token="."):
+    sys.stdout.write(token)
+    sys.stdout.flush()
+
+def check(buf):
+    try:
+        data = b64decode(buf[1:-1])
+    except:
+        return "Failed to decode"
+
+    try:
+        length, chksum, nums = data.split(':')
+        length = int(length)
+        chksum = int(chksum)
+    except:
+        return "Invalid data format"
+
+    if len(nums) != length:
+        return "Real length %d is not %d" % (len(nums), length)
+
+    inv = nums.translate(None, "0123456789")
+    if inv:
+        return "Invalid characters found: %s" % inv
+
+    real_chksum = 0
+    for num in nums:
+        real_chksum += int(num)
+
+    if real_chksum != chksum:
+        return "Real checksum %d is not %d" % (real_chksum, chksum)
+
+
+def generate():
+    length = random.randint(10, 2000)
+    numlist = []
+    for i in range(0, length):
+        numlist.append(random.randint(0, 9))
+    chksum = sum(numlist)
+    nums = "".join( [str(n) for n in numlist] )
+    data = "%d:%d:%s" % (length, chksum, nums)
+
+    buf = "\x00" + b64encode(data) + "\xff"
+    return buf
+
+def responder(client, delay=500):
+    global errors
+    cqueue = []
+    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(buffer_size)
+            if len(buf) == 0: raise Exception("Client closed")
+            #print "Client recv: %s (%d)" % (repr(buf[1:-1]), len(buf))
+            err = check(buf)
+            if err:
+                traffic("}")
+                errors = errors + 1
+                print err
+            else:
+                traffic(">")
+
+        now = time.time() * 1000
+        if client in outs and now > (last_send + delay):
+            last_send = now
+            #print "Client send: %s" % repr(cqueue[0])
+            client.send(generate())
+            traffic("<")
+
+def start_server(listen_port, delay=500):
+    global errors
+    lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    lsock.bind(('', listen_port))
+    lsock.listen(100)
+    while True:
+        try:
+            csock = None
+            print 'listening on port %s' % listen_port
+            csock, address = lsock.accept()
+            print 'Got client connection from %s' % address[0]
+            handshake(csock)
+
+            responder(csock, delay=delay)
+
+        except Exception:
+            print "accumulated errors:", errors
+            errors = 0
+            print "Ignoring exception:"
+            print traceback.format_exc()
+            if csock: csock.close()
+
+if __name__ == '__main__':
+    errors = 0
+    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 = 500
+    except:
+        print "Usage: <listen_port> [delay_ms]"
+        sys.exit(1)
+    start_server(listen_port, delay=delay)