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…
Reference in New Issue
Block a user