Add server and client HTML echo test and mootools library
This commit is contained in:
commit
77c58e19ad
60
echo_local.html
Normal file
60
echo_local.html
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title>Web Sockets echo test</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<script src="mootools.js"></script>
|
||||||
|
<script src="mootools-more.js"></script>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var cnt = 0;
|
||||||
|
var s = null;
|
||||||
|
var timer = null;
|
||||||
|
|
||||||
|
function debug(str) {
|
||||||
|
cell = $('debug');
|
||||||
|
cell.innerHTML += str + "<br/>";
|
||||||
|
}
|
||||||
|
|
||||||
|
function send_data() {
|
||||||
|
debug(">> send_data: testing " + cnt);
|
||||||
|
s.send("testing " + cnt);
|
||||||
|
cnt ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
debug(">> window.onload");
|
||||||
|
var uri = new URI(window.location);
|
||||||
|
var host = uri.getData("host");
|
||||||
|
var port = uri.getData("port");
|
||||||
|
if ((!host) || (!port)) {
|
||||||
|
debug("must set host and port");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var location = "ws://" + host + ":" + port
|
||||||
|
debug("connecting to " + location);
|
||||||
|
s = new WebSocket(location);
|
||||||
|
s.onmessage = function(e) {
|
||||||
|
debug(">> onmessage: " + e.data);
|
||||||
|
};
|
||||||
|
s.onopen = function(e) {
|
||||||
|
debug(">> onopen" + e);
|
||||||
|
timer = send_data.periodical(1000);
|
||||||
|
};
|
||||||
|
s.onclose = function(e) {
|
||||||
|
if (timer) {
|
||||||
|
timer = $clear(timer);
|
||||||
|
}
|
||||||
|
debug("<< onclose: " + e);
|
||||||
|
}
|
||||||
|
debug("<< window.onload");
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
Debug:
|
||||||
|
<div id="debug" style="width:600px;height:300px"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
4329
mootools-1.2.4-core-nc.js
vendored
Normal file
4329
mootools-1.2.4-core-nc.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
241
mootools-1.2.4.4-more.js
Normal file
241
mootools-1.2.4.4-more.js
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2009 Aaron Newton <http://clientcide.com/>, Valerio Proietti <http://mad4milk.net> & the MooTools team <http://mootools.net/developers>, MIT Style License.
|
||||||
|
|
||||||
|
/*
|
||||||
|
---
|
||||||
|
|
||||||
|
script: More.js
|
||||||
|
|
||||||
|
description: MooTools More
|
||||||
|
|
||||||
|
license: MIT-style license
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- Guillermo Rauch
|
||||||
|
- Thomas Aylott
|
||||||
|
- Scott Kyle
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- core:1.2.4/MooTools
|
||||||
|
|
||||||
|
provides: [MooTools.More]
|
||||||
|
|
||||||
|
...
|
||||||
|
*/
|
||||||
|
|
||||||
|
MooTools.More = {
|
||||||
|
'version': '1.2.4.4',
|
||||||
|
'build': '6f6057dc645fdb7547689183b2311063bd653ddf'
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
---
|
||||||
|
|
||||||
|
script: String.QueryString.js
|
||||||
|
|
||||||
|
description: Methods for dealing with URI query strings.
|
||||||
|
|
||||||
|
license: MIT-style license
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- Sebastian Markbåge, Aaron Newton, Lennart Pilon, Valerio Proietti
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- core:1.2.4/Array
|
||||||
|
- core:1.2.4/String
|
||||||
|
- /MooTools.More
|
||||||
|
|
||||||
|
provides: [String.QueryString]
|
||||||
|
|
||||||
|
...
|
||||||
|
*/
|
||||||
|
|
||||||
|
String.implement({
|
||||||
|
|
||||||
|
parseQueryString: function(){
|
||||||
|
var vars = this.split(/[&;]/), res = {};
|
||||||
|
if (vars.length) vars.each(function(val){
|
||||||
|
var index = val.indexOf('='),
|
||||||
|
keys = index < 0 ? [''] : val.substr(0, index).match(/[^\]\[]+/g),
|
||||||
|
value = decodeURIComponent(val.substr(index + 1)),
|
||||||
|
obj = res;
|
||||||
|
keys.each(function(key, i){
|
||||||
|
var current = obj[key];
|
||||||
|
if(i < keys.length - 1)
|
||||||
|
obj = obj[key] = current || {};
|
||||||
|
else if($type(current) == 'array')
|
||||||
|
current.push(value);
|
||||||
|
else
|
||||||
|
obj[key] = $defined(current) ? [current, value] : value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
cleanQueryString: function(method){
|
||||||
|
return this.split('&').filter(function(val){
|
||||||
|
var index = val.indexOf('='),
|
||||||
|
key = index < 0 ? '' : val.substr(0, index),
|
||||||
|
value = val.substr(index + 1);
|
||||||
|
return method ? method.run([key, value]) : $chk(value);
|
||||||
|
}).join('&');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
---
|
||||||
|
|
||||||
|
script: URI.js
|
||||||
|
|
||||||
|
description: Provides methods useful in managing the window location and uris.
|
||||||
|
|
||||||
|
license: MIT-style license
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- Sebastian Markbåge
|
||||||
|
- Aaron Newton
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- core:1.2.4/Selectors
|
||||||
|
- /String.QueryString
|
||||||
|
|
||||||
|
provides: URI
|
||||||
|
|
||||||
|
...
|
||||||
|
*/
|
||||||
|
|
||||||
|
var URI = new Class({
|
||||||
|
|
||||||
|
Implements: Options,
|
||||||
|
|
||||||
|
options: {
|
||||||
|
/*base: false*/
|
||||||
|
},
|
||||||
|
|
||||||
|
regex: /^(?:(\w+):)?(?:\/\/(?:(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/,
|
||||||
|
parts: ['scheme', 'user', 'password', 'host', 'port', 'directory', 'file', 'query', 'fragment'],
|
||||||
|
schemes: {http: 80, https: 443, ftp: 21, rtsp: 554, mms: 1755, file: 0},
|
||||||
|
|
||||||
|
initialize: function(uri, options){
|
||||||
|
this.setOptions(options);
|
||||||
|
var base = this.options.base || URI.base;
|
||||||
|
if(!uri) uri = base;
|
||||||
|
|
||||||
|
if (uri && uri.parsed) this.parsed = $unlink(uri.parsed);
|
||||||
|
else this.set('value', uri.href || uri.toString(), base ? new URI(base) : false);
|
||||||
|
},
|
||||||
|
|
||||||
|
parse: function(value, base){
|
||||||
|
var bits = value.match(this.regex);
|
||||||
|
if (!bits) return false;
|
||||||
|
bits.shift();
|
||||||
|
return this.merge(bits.associate(this.parts), base);
|
||||||
|
},
|
||||||
|
|
||||||
|
merge: function(bits, base){
|
||||||
|
if ((!bits || !bits.scheme) && (!base || !base.scheme)) return false;
|
||||||
|
if (base){
|
||||||
|
this.parts.every(function(part){
|
||||||
|
if (bits[part]) return false;
|
||||||
|
bits[part] = base[part] || '';
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
bits.port = bits.port || this.schemes[bits.scheme.toLowerCase()];
|
||||||
|
bits.directory = bits.directory ? this.parseDirectory(bits.directory, base ? base.directory : '') : '/';
|
||||||
|
return bits;
|
||||||
|
},
|
||||||
|
|
||||||
|
parseDirectory: function(directory, baseDirectory) {
|
||||||
|
directory = (directory.substr(0, 1) == '/' ? '' : (baseDirectory || '/')) + directory;
|
||||||
|
if (!directory.test(URI.regs.directoryDot)) return directory;
|
||||||
|
var result = [];
|
||||||
|
directory.replace(URI.regs.endSlash, '').split('/').each(function(dir){
|
||||||
|
if (dir == '..' && result.length > 0) result.pop();
|
||||||
|
else if (dir != '.') result.push(dir);
|
||||||
|
});
|
||||||
|
return result.join('/') + '/';
|
||||||
|
},
|
||||||
|
|
||||||
|
combine: function(bits){
|
||||||
|
return bits.value || bits.scheme + '://' +
|
||||||
|
(bits.user ? bits.user + (bits.password ? ':' + bits.password : '') + '@' : '') +
|
||||||
|
(bits.host || '') + (bits.port && bits.port != this.schemes[bits.scheme] ? ':' + bits.port : '') +
|
||||||
|
(bits.directory || '/') + (bits.file || '') +
|
||||||
|
(bits.query ? '?' + bits.query : '') +
|
||||||
|
(bits.fragment ? '#' + bits.fragment : '');
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(part, value, base){
|
||||||
|
if (part == 'value'){
|
||||||
|
var scheme = value.match(URI.regs.scheme);
|
||||||
|
if (scheme) scheme = scheme[1];
|
||||||
|
if (scheme && !$defined(this.schemes[scheme.toLowerCase()])) this.parsed = { scheme: scheme, value: value };
|
||||||
|
else this.parsed = this.parse(value, (base || this).parsed) || (scheme ? { scheme: scheme, value: value } : { value: value });
|
||||||
|
} else if (part == 'data') {
|
||||||
|
this.setData(value);
|
||||||
|
} else {
|
||||||
|
this.parsed[part] = value;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
get: function(part, base){
|
||||||
|
switch(part){
|
||||||
|
case 'value': return this.combine(this.parsed, base ? base.parsed : false);
|
||||||
|
case 'data' : return this.getData();
|
||||||
|
}
|
||||||
|
return this.parsed[part] || '';
|
||||||
|
},
|
||||||
|
|
||||||
|
go: function(){
|
||||||
|
document.location.href = this.toString();
|
||||||
|
},
|
||||||
|
|
||||||
|
toURI: function(){
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
getData: function(key, part){
|
||||||
|
var qs = this.get(part || 'query');
|
||||||
|
if (!$chk(qs)) return key ? null : {};
|
||||||
|
var obj = qs.parseQueryString();
|
||||||
|
return key ? obj[key] : obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
setData: function(values, merge, part){
|
||||||
|
if (typeof values == 'string'){
|
||||||
|
data = this.getData();
|
||||||
|
data[arguments[0]] = arguments[1];
|
||||||
|
values = data;
|
||||||
|
} else if (merge) {
|
||||||
|
values = $merge(this.getData(), values);
|
||||||
|
}
|
||||||
|
return this.set(part || 'query', Hash.toQueryString(values));
|
||||||
|
},
|
||||||
|
|
||||||
|
clearData: function(part){
|
||||||
|
return this.set(part || 'query', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
URI.prototype.toString = URI.prototype.valueOf = function(){
|
||||||
|
return this.get('value');
|
||||||
|
};
|
||||||
|
|
||||||
|
URI.regs = {
|
||||||
|
endSlash: /\/$/,
|
||||||
|
scheme: /^(\w+):/,
|
||||||
|
directoryDot: /\.\/|\.$/
|
||||||
|
};
|
||||||
|
|
||||||
|
URI.base = new URI(document.getElements('base[href]', true).getLast(), {base: document.location});
|
||||||
|
|
||||||
|
String.implement({
|
||||||
|
|
||||||
|
toURI: function(options){
|
||||||
|
return new URI(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
1
mootools-more.js
Symbolic link
1
mootools-more.js
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
mootools-1.2.4.4-more.js
|
1
mootools.js
Symbolic link
1
mootools.js
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
mootools-1.2.4-core-nc.js
|
78
ws_echo.py
Executable file
78
ws_echo.py
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# File: asynchat-example-1.py
|
||||||
|
|
||||||
|
import asyncore, asynchat
|
||||||
|
import sys, os, socket, string
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
|
||||||
|
class WSChannel(asynchat.async_chat):
|
||||||
|
|
||||||
|
def __init__(self, server, sock, addr):
|
||||||
|
print ">> WSChannel.__init__"
|
||||||
|
asynchat.async_chat.__init__(self, sock)
|
||||||
|
self.set_terminator("\r\n\r\n")
|
||||||
|
self.handshake = None
|
||||||
|
self.data = ""
|
||||||
|
self.shutdown = 0
|
||||||
|
|
||||||
|
def collect_incoming_data(self, data):
|
||||||
|
#print ">> WSChannel.collect_incoming_data"
|
||||||
|
self.data = self.data + data
|
||||||
|
|
||||||
|
def found_terminator(self):
|
||||||
|
#print ">> WSChannel.found_terminator"
|
||||||
|
if not self.handshake:
|
||||||
|
# got the client handshake lines
|
||||||
|
self.handshake = self.data
|
||||||
|
req_lines = self.handshake.split("\r\n")
|
||||||
|
_, path, _ = req_lines[0].split(" ")
|
||||||
|
_, origin = req_lines[4].split(" ")
|
||||||
|
_, host = req_lines[3].split(" ")
|
||||||
|
print "*** got handshake:\n%s" % self.handshake
|
||||||
|
print "*** origin: %s, location: ws://%s%s" % (origin, host, path)
|
||||||
|
self.push(server_handshake % (origin, host, path))
|
||||||
|
# self.push("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
|
||||||
|
# self.push("Upgrade: WebSocket\r\n")
|
||||||
|
# self.push("Connection: Upgrade\r\n")
|
||||||
|
# self.push("WebSocket-Origin: %s\r\n" % origin)
|
||||||
|
# self.push("WebSocket-Location: ws://%s%s\r\n" % (host, path))
|
||||||
|
# self.push("WebSocket-Protocol: sample\r\n")
|
||||||
|
# self.push("\r\n")
|
||||||
|
self.set_terminator("\xff") # look for frame terminators
|
||||||
|
else:
|
||||||
|
# return payload.
|
||||||
|
print "received: %s" % self.data
|
||||||
|
self.push("\x00 client sent: %s \xff" % self.data)
|
||||||
|
|
||||||
|
self.data = ""
|
||||||
|
|
||||||
|
class WSServer(asyncore.dispatcher):
|
||||||
|
|
||||||
|
def __init__(self, port):
|
||||||
|
asyncore.dispatcher.__init__(self)
|
||||||
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.bind(("", port))
|
||||||
|
self.listen(5)
|
||||||
|
print "<< WSServer.__init__"
|
||||||
|
|
||||||
|
def handle_accept(self):
|
||||||
|
print ">> WSServer.handle_accept"
|
||||||
|
conn, addr = self.accept()
|
||||||
|
WSChannel(self, conn, addr)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print "Usage: %s <port>" % sys.argv[0]
|
||||||
|
sys.exit(2)
|
||||||
|
PORT = int(sys.argv[1])
|
||||||
|
s = WSServer(PORT)
|
||||||
|
print "serving Web Socket at port", PORT, "..."
|
||||||
|
asyncore.loop()
|
Loading…
x
Reference in New Issue
Block a user