def test_keepalive_canceled_on_lost_connection(self): """ If a client connects with a timeout, and disconnects themselves, we will remove the timeout. """ sessions = {} h = BasicHandler() r = Clock() t = StringTransport() p = MQTTServerTwistedProtocol(h, r, sessions) p.makeConnection(t) data = ( # CONNECT, with keepalive of 2 b"101300044d51545404020002000774657374313233") for x in iterbytes(unhexlify(data)): p.dataReceived(x) self.assertEqual(len(r.calls), 1) self.assertEqual(r.calls[0].getTime(), 3.0) timeout = r.calls[0] # Clean connection lost p.connectionLost(None) self.assertEqual(len(r.calls), 0) self.assertTrue(timeout.cancelled) self.assertFalse(timeout.called)
def test_allow_connects_with_same_id_if_disconnected(self): """ If a client connects and there is an existing session which is disconnected, it may connect. """ sessions = {} h = BasicHandler() r = Clock() t = StringTransport() p = MQTTServerTwistedProtocol(h, r, sessions) cp = MQTTClientParser() p.makeConnection(t) data = (Connect(client_id=u"test123", flags=ConnectFlags(clean_session=False)).serialise()) for x in iterbytes(data): p.dataReceived(x) self.assertFalse(t.disconnecting) events = cp.data_received(t.value()) self.assertEqual(len(events), 1) self.assertEqual(attr.asdict(events[0]), { 'return_code': 0, 'session_present': False, }) p.connectionLost(None) # New session r2 = Clock() t2 = StringTransport() p2 = MQTTServerTwistedProtocol(h, r2, sessions) cp2 = MQTTClientParser() p2.makeConnection(t2) # Send the same connect, with the same client ID for x in iterbytes(data): p2.dataReceived(x) # Connection allowed events = cp2.data_received(t2.value()) self.assertEqual(len(events), 1) self.assertEqual(attr.asdict(events[0]), { 'return_code': 0, 'session_present': True, }) # Same session self.assertEqual(p.session, p2.session)
def test_clean_session_destroys_session(self): """ Setting the clean_session flag to True when connecting means that any existing session for that user ID will be destroyed. Compliance statement MQTT-3.2.2-1 """ sessions = {} h = BasicHandler() r = Clock() t = StringTransport() p = MQTTServerTwistedProtocol(h, r, sessions) p.makeConnection(t) data = (Connect(client_id=u"test123", flags=ConnectFlags(clean_session=False)).serialise()) for x in iterbytes(data): p.dataReceived(x) self.assertFalse(t.disconnecting) self.assertEqual(list(sessions.keys()), [u"test123"]) old_session = sessions[u"test123"] # Close the connection p.connectionLost(None) # New session, clean_session=True data = (Connect(client_id=u"test123", flags=ConnectFlags(clean_session=True)).serialise()) r2 = Clock() t2 = StringTransport() p2 = MQTTServerTwistedProtocol(h, r2, sessions) cp2 = MQTTClientParser() p2.makeConnection(t2) # Send the same connect, with the same client ID for x in iterbytes(data): p2.dataReceived(x) # Connection allowed events = cp2.data_received(t2.value()) self.assertEqual(len(events), 1) self.assertEqual(attr.asdict(events[0]), { 'return_code': 0, 'session_present': False, }) self.assertEqual(list(sessions.keys()), [u"test123"]) new_session = sessions[u"test123"] # Brand new session, that won't survive self.assertIsNot(old_session, new_session) self.assertFalse(new_session.survives) # We close the connection, the session is destroyed p2.connectionLost(None) self.assertEqual(list(sessions.keys()), [])