@@ -73,9 +73,12 @@ def ws(self):
7373from cherrypy .process import plugins
7474from cherrypy .wsgiserver import HTTPConnection , HTTPRequest
7575
76+ import gevent
77+ from gevent .pool import Pool
78+
7679from ws4py import WS_KEY
7780from ws4py .exc import HandshakeError
78- from ws4py .server . handler . threadedhandler import WebSocketHandler
81+ from ws4py .websocket import WebSocket
7982
8083__all__ = ['WebSocketTool' , 'WebSocketPlugin' ]
8184
@@ -96,7 +99,7 @@ def _setup(self):
9699 hooks .attach ('on_end_request' , self .start_handler ,
97100 priority = 70 )
98101
99- def upgrade (self , protocols = None , extensions = None , version = 13 , handler_cls = WebSocketHandler ):
102+ def upgrade (self , protocols = None , extensions = None , version = 13 , handler_cls = WebSocket ):
100103 """
101104 Performs the upgrade of the connection to the WebSocket
102105 protocol.
@@ -194,8 +197,6 @@ def upgrade(self, protocols=None, extensions=None, version=13, handler_cls=WebSo
194197 addr = (request .remote .ip , request .remote .port )
195198 ws_conn = request .rfile .rfile ._sock
196199 request .ws_handler = handler_cls (ws_conn , ws_protocols , ws_extensions )
197- # Start tracking the handler
198- cherrypy .engine .publish ('handle-websocket' , request .ws_handler , addr )
199200
200201 def complete (self ):
201202 """
@@ -227,13 +228,17 @@ def start_handler(self):
227228 request = cherrypy .request
228229 if not hasattr (request , 'ws_handler' ):
229230 return
230-
231- request .ws_handler .opened ()
231+
232+ addr = (request .remote .ip , request .remote .port )
233+ ws_handler = request .ws_handler
232234 request .ws_handler = None
235+ delattr (request , 'ws_handler' )
233236 # By doing this we detach the socket from
234237 # the CherryPy stack avoiding memory leaks
235238 request .rfile .rfile ._sock = None
236239
240+ cherrypy .engine .publish ('handle-websocket' , ws_handler , addr )
241+
237242 def _set_internal_flags (self ):
238243 """
239244 CherryPy has two internal flags that we are interested in
@@ -269,20 +274,19 @@ def _set_internal_flags(self):
269274class WebSocketPlugin (plugins .SimplePlugin ):
270275 def __init__ (self , bus ):
271276 plugins .SimplePlugin .__init__ (self , bus )
272- self .handlers = []
277+ self .pool = Pool ()
273278
274279 def start (self ):
275280 cherrypy .log ("Starting WebSocket processing" )
276281 self .bus .subscribe ('handle-websocket' , self .handle )
277282 self .bus .subscribe ('websocket-broadcast' , self .broadcast )
278- self .bus .subscribe ('main' , self .cleanup )
279283
280284 def stop (self ):
281285 cherrypy .log ("Terminating WebSocket processing" )
282- self .bus .unsubscribe ('main' , self .cleanup )
286+ self .pool .kill ()
287+ self .pool .join ()
283288 self .bus .unsubscribe ('handle-websocket' , self .handle )
284289 self .bus .unsubscribe ('websocket-broadcast' , self .broadcast )
285- self .cleanup ()
286290
287291 def handle (self , ws_handler , peer_addr ):
288292 """
@@ -292,28 +296,13 @@ def handle(self, ws_handler, peer_addr):
292296 @param peer_addr: remote peer address for tracing purpose
293297 """
294298 cherrypy .log ("Managing WebSocket connection from %s:%d" % (peer_addr [0 ], peer_addr [1 ]))
295- self .handlers .append ((ws_handler , peer_addr ))
296-
297- def cleanup (self ):
298- """
299- Performs a bit of cleanup on tracked handlers
300- by closing connection of terminated streams then
301- removing them from the tracked list.
302- """
303- handlers = self .handlers [:]
304- for peer in handlers :
305- handler , addr = peer
306- if handler .terminated :
307- cherrypy .log ("Removing WebSocket connection from peer: %s:%d" % (addr [0 ], addr [1 ]))
308- try :
309- handler .close_connection ()
310- except :
311- cherrypy .log (traceback = True )
312- finally :
313- if handler ._th .is_alive ():
314- handler ._th .join ()
315- self .handlers .remove (peer )
299+ ws_handler .link (self .unhandle )
300+ self .pool .start (ws_handler )
316301
302+ def unhandle (self , ws_handler ):
303+ cherrypy .log ("Removing WebSocket connection" )
304+ self .pool .discard (ws_handler )
305+
317306 def broadcast (self , message , binary = False ):
318307 """
319308 Broadcasts a message to all connected clients known to
@@ -323,13 +312,8 @@ def broadcast(self, message, binary=False):
323312 of the connected handler.
324313 @param binary: whether or not the message is a binary one
325314 """
326- handlers = self .handlers [:]
327- for peer in handlers :
328- try :
329- handler , addr = peer
330- handler .send (message , binary )
331- except :
332- cherrypy .log (traceback = True )
315+ for ws_handler in self .pool :
316+ ws_handler .send (message , message .is_binary )
333317
334318if __name__ == '__main__' :
335319 import random
0 commit comments