Updated websocket example, made it a little more bulletproof; now it's almost like tissue paper at stopping bullets. :)

This commit is contained in:
Ryan Williams
2010-02-11 14:39:12 -08:00
parent 3d2c8b198e
commit 423183926b

View File

@@ -1,11 +1,13 @@
import collections import collections
import errno import errno
from eventlet import wsgi from eventlet import wsgi
from eventlet import pools
import eventlet import eventlet
class WebSocketApp(object): class WebSocketWSGI(object):
def __init__(self, handler): def __init__(self, handler, origin):
self.handler = handler self.handler = handler
self.origin = origin
def verify_client(self, ws): def verify_client(self, ws):
pass pass
@@ -14,7 +16,6 @@ class WebSocketApp(object):
if not (environ['HTTP_CONNECTION'] == 'Upgrade' and if not (environ['HTTP_CONNECTION'] == 'Upgrade' and
environ['HTTP_UPGRADE'] == 'WebSocket'): environ['HTTP_UPGRADE'] == 'WebSocket'):
# need to check a few more things here for true compliance # need to check a few more things here for true compliance
print 'Invalid websocket handshake'
start_response('400 Bad Request', [('Connection','close')]) start_response('400 Bad Request', [('Connection','close')])
return [] return []
@@ -29,7 +30,7 @@ class WebSocketApp(object):
"Connection: Upgrade\r\n" "Connection: Upgrade\r\n"
"WebSocket-Origin: %s\r\n" "WebSocket-Origin: %s\r\n"
"WebSocket-Location: ws://%s%s\r\n\r\n" % ( "WebSocket-Location: ws://%s%s\r\n\r\n" % (
ws.origin, self.origin,
environ.get('HTTP_HOST'), environ.get('HTTP_HOST'),
ws.path)) ws.path))
sock.sendall(handshake_reply) sock.sendall(handshake_reply)
@@ -79,10 +80,17 @@ class WebSocket(object):
self.path = path self.path = path
self._buf = "" self._buf = ""
self._msgs = collections.deque() self._msgs = collections.deque()
self._sendlock = pools.TokenPool(1)
def send(self, message): def send(self, message):
packed = format_message(message) packed = format_message(message)
# if two greenthreads are trying to send at the same time
# on the same socket, sendlock prevents interleaving and corruption
t = self._sendlock.get()
try:
self.sock.sendall(packed) self.sock.sendall(packed)
finally:
self._sendlock.put(t)
def wait(self): def wait(self):
while not self._msgs: while not self._msgs:
@@ -96,11 +104,10 @@ class WebSocket(object):
return self._msgs.popleft() return self._msgs.popleft()
if __name__ == "__main__": # demo app
# run an example app from the command line import os
import os import random
import random def handle(ws):
def handle(ws):
""" This is the websocket handler function. Note that we """ This is the websocket handler function. Note that we
can dispatch based on path in here, too.""" can dispatch based on path in here, too."""
if ws.path == '/echo': if ws.path == '/echo':
@@ -115,8 +122,8 @@ if __name__ == "__main__":
ws.send("0 %s %s\n" % (i, random.random())) ws.send("0 %s %s\n" % (i, random.random()))
eventlet.sleep(0.1) eventlet.sleep(0.1)
wsapp = WebSocketApp(handle) # the wsgi shim for websockets wsapp = WebSocketWSGI(handle, 'http://localhost:7000')
def dispatch(environ, start_response): def dispatch(environ, start_response):
""" This resolves to the web page or the websocket depending on """ This resolves to the web page or the websocket depending on
the path.""" the path."""
if environ['PATH_INFO'] == '/': if environ['PATH_INFO'] == '/':
@@ -127,6 +134,9 @@ if __name__ == "__main__":
else: else:
return wsapp(environ, start_response) return wsapp(environ, start_response)
if __name__ == "__main__":
# run an example app from the command line
from eventlet.green import socket from eventlet.green import socket
listener = socket.socket() listener = socket.socket()
listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)