Permalink
Browse files

Implement disconnect() for GlobalNS and for other namespaces.

Disconnecting the global namespaces closes the connection literally (closes
the websocket).  Closing a single namespace removes it from the socket,
and will be re-instantiated with the next message.

Also fixed test_socket (test_namespace needs to be revisited though),
not loading SocketIOServer from the right place.
  • Loading branch information...
abourget committed Mar 17, 2012
1 parent dc0847d commit 491d6faaeb510bf4ac4d44f36b43dc67a06595e4
Showing with 40 additions and 7 deletions.
  1. +24 −0 socketio/namespace.py
  2. +15 −6 socketio/virtsocket.py
  3. +1 −1 tests/test_socket.py
View
@@ -149,6 +149,9 @@ def process_packet(self, packet):
return callback(*(packet['args']))
except TypeError, e:
print "ERROR: Call to callback function failed", packet
elif packet_type == 'disconnect':
# Force a disconnect on the namespace.
self.disconnect(silent=True)
else:
print "Unprocessed packet", packet
# TODO: manage the other packet types: disconnect
@@ -339,6 +342,10 @@ def send(self, message, json=False, callback=None):
pkt['type'] = "json"
if callback:
# By passing ack=True, we use the old behavior of being returned
# an 'ack' packet, automatically triggered by the client-side
# with no user-code being run. The emit() version of the
# callback is more useful I think :) So migrate your code.
pkt['ack'] = True
pkt['id'] = msgid = self.socket._get_next_msgid()
self.socket._save_ack_callback(msgid, callback)
@@ -378,6 +385,8 @@ def emit(self, event, *args, **kwargs):
endpoint=self.ns_name)
if callback:
# By passing 'data', we indicate that we *want* an explicit ack
# by the client code, not an automatic as with send().
pkt['ack'] = 'data'
pkt['id'] = msgid = self.socket._get_next_msgid()
self.socket._save_ack_callback(msgid, callback)
@@ -396,6 +405,21 @@ def spawn(self, fn, *args, **kwargs):
self.jobs.append(new)
return new
def disconnect(self, silent=False):
"""Send a 'disconnect' packet, so that the user knows it has been
disconnected (booted actually). This will trigger an onDisconnect()
call on the client side.
Over here, we will kill all ``spawn``ed processes and remove the
namespace from the Socket object.
"""
if not silent:
packet = {"type": "disconnect",
"endpoint": self.ns_name}
self.socket.send_packet(packet)
self.socket.remove_namespace(self.ns_name)
self.kill_local_jobs()
def kill_local_jobs(self):
"""Kills all the jobs spawned with BaseNamespace.spawn() on a namespace
object.
View
@@ -238,13 +238,17 @@ def disconnect(self):
active Namespaces that were open, and remove them from the ``active_ns``
map.
"""
for ns_name, ns in self.active_ns.iteritems():
for ns_name, ns in list(self.active_ns.iteritems()):
if hasattr(ns, 'disconnect'):
ns.disconnect()
# TODO: Find a better way to remove the Namespace from the ``active_ns``
# zone. Have the Ns.disconnect() call remove itself from the
# underlying socket ?
self.active_ns = {}
def remove_namespace(self, namespace):
"""This removes a Namespace object from the socket.
This is usually called by ``BaseNamespace::disconnect()``.
"""
if namespace in self.active_ns:
del self.active_ns[namespace]
def send_packet(self, pkt):
"""Low-level interface to queue a packet on the wire (encoded as wire
@@ -283,6 +287,11 @@ def _receiver_loop(self):
# any incoming raw data arrives.
continue
if pkt['type'] == 'disconnect' and pkt['endpoint'] == '':
# On global namespace, we kill everything.
self.kill()
continue
endpoint = pkt['endpoint']
if endpoint not in self.namespaces:
@@ -303,7 +312,7 @@ def _receiver_loop(self):
# Has the client requested an 'ack' with the reply parameters ?
if pkt.get('ack') == "data" and pkt.get('id'):
returning_ack = dict(type='ack', ackId=str(pkt['id']),
returning_ack = dict(type='ack', ackId=pkt['id'],
args=retval,
endpoint=pkt.get('endpoint', ''))
self.send_packet(returning_ack)
View
@@ -1,6 +1,6 @@
from unittest import TestCase, main
from socketio import SocketIOServer
from socketio.server import SocketIOServer
from socketio.virtsocket import Socket

0 comments on commit 491d6fa

Please sign in to comment.