Skip to content

Commit

Permalink
Updated server to work with websockets
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Hoffmann authored and Christian Hoffmann committed Apr 14, 2011
1 parent 32988ef commit b60f9d9
Showing 1 changed file with 22 additions and 72 deletions.
94 changes: 22 additions & 72 deletions cappuccino_x_tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,102 +20,51 @@
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.escape
import tornado.web
import tornado.websocket
import unicodedata
import uuid

from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)

LISTENERS = []
# This defines the applications routes
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", IndexHandler),
(r"/message", MessageHandler),
(r"/color", ColorHandler),
(r"/updates", UpdatesHandler),
(r"/websocket", RealtimeHandler),
]
settings = dict(
static_path=os.path.join(os.path.dirname(__file__), "static"),
)
settings = {
"static_path": os.path.join(os.path.dirname(__file__), "static"),
"debug": "True",
}
tornado.web.Application.__init__(self, handlers, **settings)

# This handles the Updates
class UpdateMixin(object):
waiters = []
cache = []
cache_size = 200
class RealtimeHandler(tornado.websocket.WebSocketHandler):
def open(self):
LISTENERS.append(self)

def wait_for_updates(self, callback, cursor=None):
cls = UpdateMixin
if cursor:
index = 0
for i in xrange(len(cls.cache)):
index = len(cls.cache) - i - 1
if cls.cache[index]["id"] == cursor: break
recent = cls.cache[index + 1:]
if recent:
callback(recent)
return
cls.waiters.append(callback)
def on_message(self, message):
JSONDict = tornado.escape.json_decode(message)
if(JSONDict['type']==u'message'):
for waiter in LISTENERS:
waiter.write_message(JSONDict)
elif(JSONDict['type']==u'color'):
for waiter in LISTENERS:
waiter.write_message(JSONDict)

def new_updates(self, updates):
cls = UpdateMixin
logging.info("Sending new update to %r listeners", len(cls.waiters))
for callback in cls.waiters:
try:
callback(updates)
except:
logging.error("Error in waiter callback", exc_info=True)
cls.waiters = []
cls.cache.extend(updates)
if len(cls.cache) > self.cache_size:
cls.cache = cls.cache[-self.cache_size:]
def on_close(self):
LISTENERS.remove(self)

# Redirects to the Cappuccino app
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.redirect("/static/index.html")

# Creates a new message and sends it to the updates handler
class MessageHandler(tornado.web.RequestHandler, UpdateMixin):
def post(self):
message = {
"type": self.get_argument("type"),
# Because we are not using a database we create an unique ID with uuid
"id": str(uuid.uuid4()),
"sender": self.get_argument("sender"),
"body": self.get_argument("body"),
}
self.new_updates([message])

# Creates a new color and sends it to the updates handler
class ColorHandler(tornado.web.RequestHandler, UpdateMixin):
def post(self):
color = {
"type": self.get_argument("type"),
# Because we are not using a database we create an unique ID with uuid
"id": str(uuid.uuid4()),
"color": self.get_argument("color"),
}
self.new_updates([color])

# Handles the updates and sends them to all clients
class UpdatesHandler(tornado.web.RequestHandler, UpdateMixin):
@tornado.web.asynchronous
def post(self):
cursor = self.get_argument("cursor", None)
self.wait_for_updates(self.async_callback(self.on_new_updates),
cursor=cursor)

def on_new_updates(self, updates):
# Closed client connection
if self.request.connection.stream.closed():
return
self.finish(dict(updates=updates))

def main():
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(Application())
Expand All @@ -124,3 +73,4 @@ def main():

if __name__ == "__main__":
main()

0 comments on commit b60f9d9

Please sign in to comment.