diff --git a/src/socketio/base_manager.py b/src/socketio/base_manager.py index 49e9e98..0d6e1a9 100644 --- a/src/socketio/base_manager.py +++ b/src/socketio/base_manager.py @@ -1,7 +1,7 @@ import itertools import logging -from bidict import bidict +from bidict import bidict, ValueDuplicationError default_logger = logging.getLogger('socketio') @@ -51,7 +51,11 @@ class BaseManager(object): def connect(self, eio_sid, namespace): """Register a client connection to a namespace.""" sid = self.server.eio.generate_id() - self.enter_room(sid, namespace, None, eio_sid=eio_sid) + try: + self.enter_room(sid, namespace, None, eio_sid=eio_sid) + except ValueDuplicationError: + # already connected + return None self.enter_room(sid, namespace, sid, eio_sid=eio_sid) return sid diff --git a/src/socketio/server.py b/src/socketio/server.py index 9084120..95c7134 100644 --- a/src/socketio/server.py +++ b/src/socketio/server.py @@ -641,6 +641,12 @@ class Server(object): """Handle a client connection request.""" namespace = namespace or '/' sid = self.manager.connect(eio_sid, namespace) + if sid is None: + self._send_packet(eio_sid, self.packet_class( + packet.CONNECT_ERROR, data='Unable to connect', + namespace=namespace)) + return + if self.always_connect: self._send_packet(eio_sid, self.packet_class( packet.CONNECT, {'sid': sid}, namespace=namespace)) diff --git a/tests/common/test_server.py b/tests/common/test_server.py index 3325fcb..1bdac11 100644 --- a/tests/common/test_server.py +++ b/tests/common/test_server.py @@ -366,6 +366,19 @@ class TestServer(unittest.TestCase): handler.assert_called_once_with('1', 'environ') s.eio.send.assert_called_once_with('123', '0/foo,{"sid":"1"}') + def test_handle_connect_namespace_twice(self, eio): + s = server.Server() + handler = mock.MagicMock() + s.on('connect', handler, namespace='/foo') + s._handle_eio_connect('123', 'environ') + s._handle_eio_message('123', '0/foo,') + s._handle_eio_message('123', '0/foo,') + assert s.manager.is_connected('1', '/foo') + handler.assert_called_once_with('1', 'environ') + s.eio.send.assert_any_call('123', '0/foo,{"sid":"1"}') + print(s.eio.send.call_args_list) + s.eio.send.assert_any_call('123', '4/foo,"Unable to connect"') + def test_handle_connect_always_connect(self, eio): s = server.Server(always_connect=True) s.manager.initialize = mock.MagicMock()