Permalink
Browse files

dead simple django chat app

git-svn-id: http://evserver.googlecode.com/svn/trunk@102 e9bb6d7e-af12-11dd-bad7-87afd3b02348
  • Loading branch information...
1 parent 1664235 commit dde5d447b83cc9f783078b92b3f9cc9de3a982b1 majek04 committed Mar 16, 2009
View
8 evserver/examples/django_chat/README
@@ -0,0 +1,8 @@
+requirements:
+ pyamqplib 0.6
+ rabbitmq server
+ django 1.0x
+
+
+Running:
+python manage.py runevserver
View
0 evserver/examples/django_chat/__init__.py
No changes.
View
41 evserver/examples/django_chat/broker.py
@@ -0,0 +1,41 @@
+import amqplib.client_0_8 as amqp
+import logging, os, os.path
+log = logging.getLogger(os.path.basename(__file__))
+logging.getLogger('amqplib').setLevel(logging.INFO) # ignore msgs from there
+
+cache = {}
+def send_amqp_message(key, msg_body):
+ if 'conn' in cache:
+ conn = cache['conn']
+ ch = cache['ch']
+ else:
+ log.info('connecting to amqp')
+ # conn should be cached
+ conn = amqp.Connection('localhost', userid='guest', password='guest')
+ ch = conn.channel()
+ ch.access_request('/data', active=True, write=True)
+ ch.exchange_declare(key, 'fanout',auto_delete=True)
+ ch.exchange_declare('render', 'fanout', auto_delete=False)
+ cache['conn'] = conn
+ cache['ch'] = ch
+
+ try:
+ msg = amqp.Message(msg_body, content_type='text/plain')
+ ch.basic_publish(msg, key)
+
+ except Exception:
+ log.info('connection to amqp failed')
+ try:
+ ch.close()
+ except Exception: pass
+ try:
+ conn.close()
+ except Exception: pass
+
+ ch.connection = None
+ conn.channels = {}
+ conn.connection = None
+ conn.transport = None
+ del cache['conn']
+ del cache['ch']
+ return send_amqp_message(key, msg_body)
View
105 evserver/examples/django_chat/index.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <script type="text/javascript" src="/static/comet.js"></script>
+ <style type="text/css">
+ body, select, input { font-family: arial, sans-serif;}
+ body, html{height:100%;}
+ body {
+ font-size: 83%;
+ font-family: arial, sans-serif;
+ border-collapse: separate;
+ }
+ #outputbox {border:1px solid grey;height:200px;overflow:scroll;}
+ #inputbox {border:1px solid black}
+ </style>
+
+</head>
+<body>
+ <pre id="outputbox">
+ </pre>
+ <input id="inputbox">
+
+<script>
+ var inputbox = document.getElementById("inputbox");
+ var outputbox = document.getElementById("outputbox");
+
+ inputbox.focus();
+ if(inputbox.addEventListener ) {
+ inputbox.addEventListener('keydown',this.keyHandler,false);
+ } else if(inputbox.attachEvent ) {
+ inputbox.attachEvent('onkeydown',this.keyHandler); /* damn IE hack */
+ }
+
+ var msgs = '';
+ function keyHandler(e) {
+ if(e.keyCode == 13) {
+ setTimeout(function(){
+ if(msgs)
+ msgs += '\n';
+ msgs += inputbox.value;
+ inputbox.value = '';
+ send();
+ },0)
+ if(e.preventDefault) {
+ e.preventDefault();
+ }
+ return false;
+ }
+ }
+
+ var waiting = false;
+ function send(){
+ if(!msgs)
+ return;
+ if(waiting)
+ return;
+ waiting = true;
+ var payload = msgs;
+ msgs = '';
+ send_ajax(payload, function(data){
+ waiting=false; send();
+ });
+ }
+
+ function send_ajax(payload, callback){
+ var payload = payload;
+ var xhr;
+ var ors = function(){
+ if(!xhr) return;
+ if(xhr.readyState==4){
+ var response = xhr.responseText;
+ if(xhr.status!=200){
+ comet_log('Fatal ajax error, retrying in few seconds. Payload: ' + payload);
+ setTimeout(function(){
+ xhr = comet_create_ajax('./push/', 'POST', payload, ors);
+ }, 8000);
+ return;
+ }
+ try{
+ xhr.abort();
+ }catch(e){};
+ delete(xhr);
+ xhr = null;
+ callback(response)
+ }
+ }
+ xhr = comet_create_ajax('./push/', 'POST', payload, ors);
+ }
+
+ function url(){
+ return "./pop/?a=" + (''+Math.random()).substr(2,6);
+ }
+
+ function user_callback(data){
+ if(data == 'ping')
+ return
+ outputbox.innerHTML = outputbox.innerHTML + '<br>'+ data;
+ outputbox.scrollTop = outputbox.scrollHeight;
+ }
+
+ var gc = comet_connection(url, user_callback);
+
+</script>
+</body>
+</html>
View
11 evserver/examples/django_chat/manage.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+from django.core.management import execute_manager
+try:
+ import settings # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
+ sys.exit(1)
+
+if __name__ == "__main__":
+ execute_manager(settings)
View
83 evserver/examples/django_chat/settings.py
@@ -0,0 +1,83 @@
+# Django settings for django_chat project.
+
+DEBUG = True
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+ # ('Your Name', 'your_email@domain.com'),
+)
+
+MANAGERS = ADMINS
+
+DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+DATABASE_NAME = '' # Or path to database file if using sqlite3.
+DATABASE_USER = '' # Not used with sqlite3.
+DATABASE_PASSWORD = '' # Not used with sqlite3.
+DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
+DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# Absolute path to the directory that holds media.
+# Example: "/home/media/media.lawrence.com/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash if there is a path component (optional in other cases).
+# Examples: "http://media.lawrence.com", "http://example.com/media/"
+MEDIA_URL = ''
+
+# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
+# trailing slash.
+# Examples: "http://foo.com/media/", "/media/".
+ADMIN_MEDIA_PREFIX = '/media/'
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = 'g&+%xv0uoi-5u*ws5$+4)4!jhcxd(re5w!!dllzm+eiy5p79m7'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+ 'django.template.loaders.filesystem.load_template_source',
+ 'django.template.loaders.app_directories.load_template_source',
+# 'django.template.loaders.eggs.load_template_source',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+)
+
+ROOT_URLCONF = 'django_chat.urls'
+
+from pkg_resources import resource_filename
+TEMPLATE_DIRS = (
+ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+ resource_filename(__name__, '.'),
+)
+
+
+INSTALLED_APPS = (
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'evserver',
+)
View
700 evserver/examples/django_chat/static/comet.js
@@ -0,0 +1,700 @@
+/*
+ Based on orbited.js from the Orbited project.
+*/
+
+/********************************************************************/
+/** settings **/
+/* how long to wait after the connection is lost (server died) */
+comet_restart_timeout = 8000; // 5 seconds
+/* if no keepalive in this time - reconnect */
+comet_keepalive_timeout = 76*1000; // 66 seconds with no data
+
+/********************************************************************/
+
+
+
+/********************************************************************/
+/** comet engines **/
+/*
+ parameters:
+ url - url string to connect to, should contain ? character
+ inside, we're going to append &transport= to it.
+ callback - user callback function
+ server_reconnect - the function that is going to be called
+ when the connection will be lost
+ return value:
+ - function that is going to destroy current conenction
+ for garbage collecting
+ */
+
+/* xhr stream, for firefox and safari */
+function schedule_connection_xhr(url, callback, server_reconnect) {
+ var boundary = '\r\n|O|\r\n';
+ var xhr = null;
+ var offset = 0;
+
+ var onreadystatechange = function(event) {
+ if(!xhr)
+ return;
+ if(xhr.readyState==4)
+ server_reconnect(true);
+ else if(xhr.readyState==3 && xhr.status==200) {
+ /* skip initial padding */
+ if(offset == 0){
+ offset = xhr.responseText.indexOf('\r\n\r\n');
+ if(offset == -1)
+ offset = 0;
+ else
+ offset += 4;
+ }
+ while(true){
+ if(!xhr || !xhr.responseText)
+ break;
+ var data = xhr.responseText.substr(offset);
+ var end = data.indexOf(boundary);
+ if(end == -1)
+ break;
+ offset = offset + end + boundary.length;
+ callback( decode_utf8(data.substr(0, end)) );
+ }
+ }
+ }
+ xhr = comet_create_ajax(url + '&transport=xhr', 'GET', null, onreadystatechange);
+
+ function xhr_gc(){
+ if(xhr){
+ try{
+ xhr.onreadystatechange=function () {};
+ xhr.abort();
+ }catch(e){};
+ delete(xhr);
+ delete(offset);
+ offset = null;
+ xhr = null;
+ }
+ };
+
+ comet_attach_unload_event(xhr_gc);
+ return xhr_gc;
+}
+
+
+/* long polling */
+function schedule_connection_longpoll(url, callback, server_reconnect) {
+ var xhr = null;
+ var eid = 0;
+ var schedule = function(){
+ if(xhr){
+ try{
+ xhr.onreadystatechange=function () {};
+ xhr.abort();
+ }catch(e){};
+ try{
+ delete(xhr);
+ }catch(e){};
+ }
+ var onreadystatechange = function() {
+ if(!xhr)
+ return;
+ if(xhr.readyState==4){
+ if(xhr.status==200){
+ eid += 1;
+ var data = xhr.responseText;
+ if(schedule)
+ schedule();
+
+ callback( data );
+ }else{
+ server_reconnect(true);
+ }
+ }
+ }
+ xhr = comet_create_ajax(url + '&transport=longpoll&eid=' + eid, 'GET', null, onreadystatechange)
+ };
+
+ schedule();
+
+ function xhr_gc(){
+ if(xhr){
+ try{
+ xhr.onreadystatechange=function () {};
+ xhr.abort();
+ }catch(e){};
+ }
+ delete(xhr);
+ xhr = null;
+ delete(schedule);
+ schedule = null;
+ };
+
+ return xhr_gc;
+}
+
+
+
+/* htmlfile, for ie */
+function schedule_connection_htmlfile(url, user_callback, server_reconnect) {
+ var i=0; while(window['c'+i] != undefined) i += 1;
+ var fname = 'c' + i;
+
+ function recon(){
+ server_reconnect(true);
+ }
+ window[fname] = user_callback;
+ window[fname + '_reconnect'] = recon;
+
+ var transferDoc = new ActiveXObject('htmlfile');
+ transferDoc.open();
+ transferDoc.write(
+ '<html><script>\n' +
+ ' document.domain = "' + document.domain + '";\n' +
+ '</script></html>\n');
+ transferDoc.close();
+ var ifrDiv = transferDoc.createElement("div");
+ transferDoc.parentWindow[fname] = user_callback;
+ transferDoc.parentWindow[fname +'_reconnect'] = recon;
+ transferDoc.body.appendChild(ifrDiv);
+ ifrDiv.innerHTML = "<iframe src='" + url +
+ '&transport=htmlfile'+
+ '&domain=' + document.domain +
+ '&callback=' + fname +
+ "' ></iframe>";
+
+ // for ie 6
+ kill_load_bar();
+ function htmlfile_close() {
+ window[fname] = function(){};
+ window[fname+'_reconnect'] = function(){};
+ if(transferDoc){
+ transferDoc.body.removeChild(ifrDiv);
+ delete(trasferDoc);
+ transferDoc = null;
+ }
+ if(ifrDiv){
+ delete(ifrDiv);
+ ifrDiv = null;
+ }
+ try{
+ CollectGarbage();
+ }catch(e){};
+ }
+ comet_attach_unload_event(htmlfile_close);
+ return htmlfile_close;
+}
+
+/* iframe, fallback for konqueror */
+function schedule_connection_iframe(url, user_callback, server_reconnect) {
+ var i=0; while(window['c'+i] != undefined) i += 1;
+ var fname = 'c' + i;
+ window[fname] = function (data){
+ user_callback(data);
+ kill_load_bar();
+ }
+ window[fname + '_reconnect'] = function(){
+ server_reconnect(true);
+ }
+
+ var ifr = document.createElement('iframe');
+ hide_iframe(ifr);
+ ifr.setAttribute('src', url +
+ '&transport=iframe'+
+ '&callback=' + fname );
+ document.body.appendChild(ifr);
+
+ kill_load_bar();
+ var gc = function () {
+ window[fname] = function(){};
+ window[fname+'_reconnect'] = function(){};
+ if(ifr){
+ document.body.removeChild(ifr);
+ delete(ifr);
+ ifr=null;
+ }
+ try{
+ CollectGarbage();
+ }catch(e){};
+ };
+ comet_attach_unload_event(gc);
+ return gc;
+}
+function hide_iframe(ifr) {
+ ifr.style.display = 'block';
+ ifr.style.width = '0';
+ ifr.style.height = '0';
+ ifr.style.border = '0';
+ ifr.style.margin = '0';
+ ifr.style.padding = '0';
+ ifr.style.overflow = 'hidden';
+ ifr.style.visibility = 'hidden';
+}
+
+
+
+
+/* server_sent_events for opera
+opera 9.60 is delivering messages _TWICE_.
+to fix that we need to keep track on messages. fuck.
+If they will fix it, it's going to be a huge memory drainer.
+*/
+function schedule_connection_sse(url, callback) {
+ var es = document.createElement('event-source');
+ es.setAttribute('src', url +"&transport=sse");
+ // without this check opera 9.5 would make two connections.
+ if (opera.version() < 9.5) {
+ document.body.appendChild(es);
+ }
+
+ var event_callback = function (event){
+ if(callback){
+ if(event.data)
+ callback(decode_utf8(unescape(event.data)));
+ }
+ };
+
+ es.addEventListener('payload', event_callback, false);
+
+
+ var gc = function () {
+ if(es){
+ es.removeEventListener('payload', event_callback, false);
+ if (opera.version() < 9.5) {
+ document.body.removeChild(es);
+ }
+ es.src='';
+ }
+ callback=null;
+ event_callback=null;
+ delete(es);
+ es = null;
+ };
+ return gc;
+}
+
+
+comet_transports = {
+ xhr: schedule_connection_xhr,
+ xhrstream: schedule_connection_xhr,
+ longpoll: schedule_connection_longpoll,
+ htmlfile: schedule_connection_htmlfile,
+ iframe: schedule_connection_iframe,
+ sse: schedule_connection_sse
+};
+/********************************************************************/
+/** find proper transport for current browser **/
+function guess_transport() {
+ // IF we're on IE 5.01/5.5/6/7 we want to use an htmlfile
+ try {
+ var test = ActiveXObject;
+ return 'htmlfile';
+ }catch (e) {}
+
+ // If the browser supports server-sent events, we should use those
+ if ((typeof window.addEventStream) == 'function') {
+ return 'sse';
+ }
+
+ if( navigator.userAgent.indexOf('Konqueror')!= -1)
+ return 'iframe';
+
+ if( navigator.userAgent.indexOf('Safari')!= -1 || navigator.userAgent.indexOf('Webkit')!= -1){
+ return 'xhrstream';
+ }
+
+ return 'xhrstream';
+}
+
+transport_global = guess_transport();
+
+
+
+function comet_connection(url, user_callback_o, transport_local) {
+ // due to safari bug, we need to do actual stuff after setTimeout
+ var gc; // closure
+ function foo(){
+ gc = comet_connection_original(url, user_callback_o, transport_local);
+ }
+ if(comet_after_load_event == false)
+ comet_attach_load_event(function(){setTimeout(foo,250);});
+ else
+ foo();
+
+ return function(){
+ if(gc)
+ gc();
+ else
+ comet_log("don't cancel connection so fast!");
+ }
+}
+
+/********************************************************************/
+/** The Most Important Function. schedule connection for user **/
+/*
+ url - static url or function that returns url
+ user_callback - callback function, is going to be called each time with
+ one parameter - data
+ */
+function comet_connection_original(url, user_callback_o, transport_local) {
+ var keepalive_timer = null;
+ var connect_function = null;
+ var garbage_function = null;
+ var comet_transport = '';
+ function get_url(url){
+ var c = url;
+ if(typeof(url) == "function")
+ c = url();
+
+ if(c.indexOf('?') == -1)
+ c = c + '?a=' + Math.random();
+ return c;
+ }
+ function user_callback(data){
+ /*
+ if(strip(data) == '' || data == 'ping'){
+ //comet_log('comet: got keepalive');
+ return;
+ }
+ */
+ //comet_log('comet: got data length:' + data.length);
+ if(typeof(data) != "string" && typeof(data)!="String")
+ data = '';
+ user_callback_o(data);
+ }
+ function server_reconnect(conn_broken) {
+ if(conn_broken == true){
+ if(garbage_function)
+ garbage_function();
+ garbage_function = null;
+
+ comet_log('comet: '+comet_transport +' conn broken, reconnecting in '+ comet_restart_timeout +'....');
+ setTimeout(function () {
+ garbage_function = connect_function(get_url(url), callback, server_reconnect);
+ }, comet_restart_timeout);
+ }else{
+ comet_log('comet: '+comet_transport +' no keepalive reconnecting now...');
+ if(garbage_function)
+ garbage_function();
+ garbage_function = null;
+ garbage_function = connect_function(get_url(url), callback, server_reconnect);
+ }
+ update_keepalive();
+ }
+ function update_keepalive() {
+ clearTimeout(keepalive_timer);
+ keepalive_timer = setTimeout( server_reconnect, comet_keepalive_timeout);
+ }
+ keepalive_timer = setTimeout( server_reconnect, comet_keepalive_timeout);
+
+ var callback = function (data){
+ update_keepalive();
+ user_callback(data);
+ };
+
+ if(!transport_local){
+ comet_transport = transport_global;
+ }else{
+ comet_transport = transport_local;
+ }
+ comet_log('comet: using transport:' + comet_transport +' restart_timeout:' + comet_restart_timeout + ' keepalive_timeout:' + comet_keepalive_timeout);
+ connect_function = comet_transports[comet_transport];
+
+ if(!connect_function){
+ comet_log('comet: bad transport: '+ comet_transport);
+ return null;
+ }
+
+ garbage_function = connect_function(get_url(url), callback, server_reconnect);
+ var xx = function (){
+ clearTimeout(keepalive_timer);
+ if(garbage_function)
+ garbage_function();
+ if(comet_log)
+ comet_log('comet: cleaning connection');
+ }
+ return xx;
+}
+
+
+
+
+/********************************************************************/
+function comet_crossdomain_connection(iframe_uri, comet_uri, user_callback, transport){
+ var i=0; while(window['c'+i] != undefined) i += 1;
+ var fname = 'c' + i;
+ var transportstr = '';
+ if(transport)
+ transportstr = '&transport=' + transport;
+
+ comet_log('cometcrossdomain: started');
+ window[fname] = user_callback;
+ window[fname + '_uri'] = comet_uri;
+
+ if(iframe_uri.indexOf('?') == -1)
+ iframe_uri = iframe_uri + '?a=' + Math.random()
+
+ var ifr = document.createElement('iframe');
+ hide_iframe(ifr);
+ ifr.setAttribute('src', iframe_uri +
+ '&callback=' + fname + transportstr);
+ document.body.appendChild(ifr);
+ function garbc(){
+ if(ifr){
+ comet_log('cometcrossdomain: stopped');
+ var doc = ifr.contentDocument;
+ if(doc == undefined || doc == null){
+ doc = null;
+ if(ifr.contentWindow)
+ doc = ifr.contentWindow.document;
+ }
+ try{
+ if(doc && doc.comet_garbage)
+ doc.comet_garbage();
+ }catch(e){};
+ document.body.removeChild(ifr);
+ delete(ifr);
+ ifr=null;
+ }
+ window[fname] = function(){};
+ window[fname + '_uri'] = null;
+ }
+ comet_attach_unload_event(garbc);
+ return garbc;
+}
+
+
+/********************************************************************/
+function comet_create_crossdomain_ajax(iframe_uri, ajax_uri, method, post_data, user_callback, mimetype) {
+ var queue_key = escape(iframe_uri) + '_queue';
+ var garbc_key = escape(iframe_uri) + '_garbc';
+ var push_key = escape(iframe_uri) + '_push';
+ if(window[queue_key] == undefined){
+ window[queue_key] = [];
+ window[push_key] = function(){};
+ }
+
+ var v = [ajax_uri, method, post_data, user_callback, mimetype];
+ window[queue_key] = ([v]).concat(window[queue_key]);
+ window[push_key]();
+
+ if(window[garbc_key] == undefined) {
+ window[garbc_key] = comet_create_crossdomain_ajax_iframe(iframe_uri);
+ }
+}
+
+function comet_create_crossdomain_ajax_iframe(iframe_uri) {
+ var i=0; while(window['ajc'+i] != undefined) i += 1;
+ var fname = 'ajc' + i;
+ var ifr;
+ window[fname] = escape(iframe_uri);
+ var queue_key = fname + '_data';
+
+
+ if(iframe_uri.indexOf('?') == -1)
+ iframe_uri = iframe_uri + '?a=' + Math.random()
+
+ ifr = document.createElement('iframe');
+ hide_iframe(ifr);
+ ifr.setAttribute('src', iframe_uri +
+ '&callback=' + fname);
+ document.body.appendChild(ifr);
+ kill_load_bar();
+
+ var garbc = function(){
+ if(ifr){
+ document.body.removeChild(ifr);
+ delete(ifr);
+ ifr=null;
+ }
+ window[fname] = null;
+ }
+ comet_attach_unload_event(garbc);
+ return garbc;
+}
+
+
+
+
+/********************************************************************/
+/** various helpers **/
+/********************************************************************/
+function strip(str) {
+ return str.replace(/^\s*(.*?)\s*$/, "$1");
+ return(str);
+}
+
+function getURLParam(strParamName){
+ var strReturn = "";
+ var strHref = window.location.href;
+ if ( strHref.indexOf("?") > -1 ){
+ var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();
+ var aQueryString = strQueryString.split("&");
+ for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
+ if(aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1 ){
+ var aParam = aQueryString[iParam].split("=");
+ strReturn = aParam[1];
+ break;
+ }
+ }
+ }
+ return unescape(strReturn);
+}
+
+
+function comet_log(arg){
+ arg = '' + arg;
+ arg = arg.substr(0, 512);
+ if (typeof window.console !== 'undefined') {
+ console.log(arg);
+ }
+ else if (typeof window.opera !== 'undefined') {
+ opera.postError(arg);
+ }else if (window['YAHOO'] && YAHOO.log){
+ YAHOO.log(arg, 'info');
+ }/*else
+ alert(arg);
+ */
+}
+
+function comet_raw_xhr() {
+ // also interesting: http://keelypavan.blogspot.com/2006/03/reusing-xmlhttprequest-object-in-ie.html
+ try { return new ActiveXObject('MSXML3.XMLHTTP'); } catch(e) {}
+ try { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); } catch(e) {}
+ try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
+ try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
+ try { return new XMLHttpRequest(); } catch(e) {}
+ throw new Error('Could not find XMLHttpRequest or an alternative.');
+}
+
+
+
+function comet_create_xhr() {
+ var xhr = comet_raw_xhr();
+ // stolen from http://blog.mibbit.com/?p=143
+ function safeSet(k, v) {
+ try {
+ xhr.setRequestHeader(k, v);
+ } catch(e) {}
+ }
+
+ safeSet("User-Agent", null);
+ safeSet("Accept", null);
+ safeSet("Accept-Language", null);
+ safeSet("Content-Type", "M");
+ safeSet("Connection", "keep-alive");
+ safeSet("Keep-Alive", null);
+ return(xhr);
+}
+
+function comet_create_ajax(url, method, data, onreadycallback, mimetype) {
+ var xhr = comet_create_xhr();
+
+ /*
+ try {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
+ } catch (ex) { }
+ */
+ xhr.open(method, url, true);
+ if(data){
+ if(!mimetype)
+ mimetype = "application/x-www-form-urlencoded";
+ try{
+ xhr.setRequestHeader("Content-type", mimetype);
+ }catch(e){};
+ try{
+ xhr.setRequestHeader("Content-length", data.length);
+ }catch(e){};
+ }
+ xhr.onreadystatechange = onreadycallback;
+ /*
+ function(){
+ if(onreadycallback)
+ onreadycallback();
+ if(xhr.readyState==4){
+ // especially for explorer
+ try{
+ xhr.abort();
+ }catch(e){};
+ delete(xhr);
+ xhr = null;
+ try{
+ CollectGarbage();
+ }catch(e){};
+ }
+ }
+ */
+
+ xhr.send(data);
+ return(xhr);
+}
+
+
+load_kill_ifr = null;
+function kill_load_bar() {
+ if (load_kill_ifr == null) {
+ load_kill_ifr = document.createElement('iframe');
+ hide_iframe(load_kill_ifr);
+ }
+ document.body.appendChild(load_kill_ifr);
+ load_kill_ifr.src = 'about:blank';
+ document.body.removeChild(load_kill_ifr);
+}
+
+function comet_attach_unload_event(foo){
+ if(window.addEventListener){
+ document.addEventListener('unload', foo, false);
+ window.addEventListener('unload', foo, false);
+ } else { // IE
+ document.attachEvent('onunload', foo);
+ window.attachEvent('onunload', foo);
+ }
+}
+
+// http://www.sitepoint.com/blogs/2004/05/26/closures-and-executing-javascript-on-page-load/
+function comet_attach_load_event(fn){
+ var oldfn = window.onload;
+ if (typeof window.onload != 'function'){
+ window.onload = fn;
+ }else{
+ window.onload = function(){
+ oldfn();
+ fn();
+ };
+ }
+}
+
+function extract_xss_domain(old_domain) {
+ var domain_pieces = old_domain.split('.');
+ if (domain_pieces.length === 4) {
+ var is_ip = !isNaN(Number(domain_pieces.join('')));
+ if (is_ip) {
+ return old_domain;
+ }
+ }
+ var new_domain = domain_pieces.slice(-2).join('.');
+ var colon = old_domain.split(':');
+ if(colon.length > 1)
+ return new_domain + ':' + colon[1];
+ return new_domain;
+}
+
+function encode_utf8( s )
+{
+ try{
+ return unescape( encodeURIComponent( s ) );
+ }catch(e){
+ return(s);
+ }
+}
+
+function decode_utf8( s )
+{
+ try{
+ return decodeURIComponent( escape( s ) );
+ }catch(e){
+ return(s);
+ }
+}
+
+comet_after_load_event = false;
+
+comet_attach_load_event(function(){comet_after_load_event=true});
+
View
17 evserver/examples/django_chat/urls.py
@@ -0,0 +1,17 @@
+from django.conf.urls.defaults import *
+from pkg_resources import resource_filename
+import os.path
+import django.views.static
+import django.views.generic.simple
+
+module_dir = resource_filename(__name__, '.')
+
+urlpatterns = patterns('views',
+ (r'^$', django.views.generic.simple.redirect_to, {'url':'start/'}),
+ (r'^static/(?P<path>.*)$', django.views.static.serve,
+ {'document_root': os.path.join(module_dir, 'static')}),
+ (r'^(?P<key>\w{3,32})/$', 'document'),
+ (r'^(?P<key>\w{3,32})/push/$', 'ajax_push'),
+ (r'^(?P<key>\w{3,32})/pop/$', 'comet'),
+)
+
View
107 evserver/examples/django_chat/views.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+from django.http import HttpResponse, HttpResponseRedirect
+
+import evserver.other.django
+import amqplib.client_0_8 as amqp
+from broker import send_amqp_message
+from django.shortcuts import render_to_response
+import urllib
+import socket
+
+
+def document(request, key):
+ key = urllib.quote(key)
+ context = {
+ 'key': key.replace('%',''),
+ }
+
+ return render_to_response('index.html', context)
+
+
+def index(request):
+ return HttpResponse('Hello World!', mimetype="text/plain")
+
+
+def ajax_push(request, key):
+ key = urllib.quote(key)
+ payload = request.raw_post_data
+ if not isinstance(payload, unicode):
+ payload = payload.encode('utf-8')
+
+ payload = payload.replace('<', '&lt;').replace('>','&gt;')
+
+ send_amqp_message(key, payload)
+
+ return HttpResponse('ok', mimetype="text/plain")
+
+
+
+def set_ridiculously_high_buffers(sd):
+ for flag in [socket.SO_SNDBUF, socket.SO_RCVBUF]:
+ for i in range(10):
+ bef = sd.getsockopt(socket.SOL_SOCKET, flag)
+ sd.setsockopt(socket.SOL_SOCKET, flag, bef*2)
+ aft = sd.getsockopt(socket.SOL_SOCKET, flag)
+ if aft <= bef or aft >= 16777216: # 16M
+ break
+
+
+@evserver.other.django.encapsulate_to_comet
+def comet(request, key):
+ key = urllib.quote(key)
+ # setup the amqp subscriber
+ msgs = []
+ def callback(msg):
+ msgs.append(msg.body)
+ msg.channel.basic_ack(msg.delivery_tag)
+
+ conn = amqp.Connection('localhost', userid='guest', password='guest')
+
+ ch = conn.channel()
+ ch.access_request('/data', active=True, read=True)
+
+ ch.exchange_declare(key, 'fanout', auto_delete=True)
+ qname, _, _ = ch.queue_declare()
+ ch.queue_bind(qname, key,)
+ ch.basic_consume(qname, callback=callback)
+
+ sd = conn.transport.sock
+ sd.setblocking(False)
+ set_ridiculously_high_buffers(sd)
+
+ def iterator():
+ try:
+ while ch.callbacks:
+ try:
+ while True: # until exception
+ ch.wait()
+ except (TypeError,), e:
+ pass
+
+ if not msgs:
+ yield 'ping'
+ while msgs:
+ msg = msgs.pop(0)
+ yield msg
+
+ yield request.environ['x-wsgiorg.fdevent.readable'](conn.transport.sock, 60)
+ except GeneratorExit:
+ pass
+
+ try:
+ ch.close()
+ except Exception:
+ pass
+ try:
+ conn.close()
+ except Exception:
+ pass
+
+ ch.connection = None
+ conn.channels = {}
+ conn.connection = None
+ conn.transport = None
+
+ return HttpResponse(iterator())
+
+
View
28 evserver/other/django.py
@@ -0,0 +1,28 @@
+import evserver.transports
+
+def encapsulate_to_comet(userfunction):
+ def wrapper(request, *args, **kwargs):
+ transport = evserver.transports.get_transport(
+ request.GET.get('transport','basic'),
+ callback=request.GET.get('callback','c0'),
+ domain=request.GET.get('domain',''))
+ response = userfunction(request, *args, **kwargs)
+ iterator = response._container
+ def wrapper2():
+ try:
+ yield transport.start()
+ for item in iterator:
+ if item:
+ yield transport.write(item)
+ else:
+ yield item
+ except GeneratorExit:
+ if getattr(iterator, 'close', None):
+ iterator.close()
+
+ response._container = wrapper2()
+ for k, v in transport.get_headers():
+ response[k] = v
+ return response
+
+ return wrapper
View
2 setup.py
@@ -11,7 +11,7 @@
find_packages = lambda:[r.replace('/','.') for r, d, _ in w if '.' not in r]
-version = "0.01"
+version = "0.10"
try:
proc = subprocess.Popen(["svn", "info"], stdout=subprocess.PIPE)

0 comments on commit dde5d44

Please sign in to comment.