def _test_basic_publish(self): reactor, router, server_factory, session_factory = build_mqtt_server() session, pump = connect_application_session( server_factory, ObservingSession, component_config=ComponentConfig(realm=u"mqtt")) client_transport, client_protocol, mqtt_pump = connect_mqtt_server(server_factory) client_transport.write( Connect(client_id=u"testclient", username=u"test123", password=u"password", flags=ConnectFlags(clean_session=False, username=True, password=True)).serialise()) mqtt_pump.flush() # We get a CONNECT self.assertEqual(client_protocol.data, ConnACK(session_present=False, return_code=0).serialise()) client_protocol.data = b"" client_transport.write( Publish(duplicate=False, qos_level=0, retain=False, topic_name=u"test", payload=b'{"kwargs": {"bar": "baz"}}').serialise()) mqtt_pump.flush() pump.flush() # This needs to be replaced with the real deal, see https://github.com/crossbario/crossbar/issues/885 self.assertEqual(len(session.events), 1) self.assertEqual( session.events, [{"args": tuple(), "kwargs": {u'bar': u'baz'}}])
def _test_retained(self): """ The MQTT client can set and receive retained messages. """ reactor, router, server_factory, session_factory = build_mqtt_server() client_transport, client_protocol, mqtt_pump = connect_mqtt_server( server_factory) client_transport.write( Connect(client_id=u"testclient", username=u"test123", password=u"password", flags=ConnectFlags(clean_session=False, username=True, password=True)).serialise()) client_transport.write( Publish(duplicate=False, qos_level=1, retain=True, topic_name=u"com/test/wamp", packet_identifier=123, payload=b'{}').serialise()) mqtt_pump.flush() self.assertEqual( client_protocol.data, (ConnACK(session_present=False, return_code=0).serialise() + PubACK(packet_identifier=123).serialise())) client_protocol.data = b"" client_transport.write( Subscribe(packet_identifier=1, topic_requests=[ SubscriptionTopicRequest( topic_filter=u"com/test/wamp", max_qos=0) ]).serialise()) mqtt_pump.flush() self.assertEqual( client_protocol.data, SubACK(packet_identifier=1, return_codes=[0]).serialise()) client_protocol.data = b"" reactor.advance(0.1) mqtt_pump.flush() # This needs to be replaced with the real deal, see https://github.com/crossbario/crossbar/issues/885 self.assertEqual( client_protocol.data, Publish(duplicate=False, qos_level=0, retain=True, topic_name=u"com/test/wamp", payload=json.dumps( {}, sort_keys=True).encode('utf8')).serialise())
class TestProtocol(Protocol): data = b"" expected = (ConnACK(session_present=False, return_code=0).serialise() + PubACK(packet_identifier=1).serialise()) def dataReceived(self_, data): self_.data = self_.data + data if len(self_.data) == len(self_.expected): self.assertEqual(self_.data, self_.expected) real_reactor.stop()
def _test_basic_subscribe(self): """ The MQTT client can subscribe to a WAMP topic and get messages. """ reactor, router, server_factory, session_factory = build_mqtt_server() client_transport, client_protocol, mqtt_pump = connect_mqtt_server( server_factory) session, pump = connect_application_session( server_factory, ApplicationSession, component_config=ComponentConfig(realm="mqtt", controller=MockContainer())) client_transport.write( Connect(client_id="testclient", username="******", password="******", flags=ConnectFlags(clean_session=False, username=True, password=True)).serialise()) client_transport.write( Subscribe(packet_identifier=1, topic_requests=[ SubscriptionTopicRequest( topic_filter="com/test/wamp", max_qos=0) ]).serialise()) mqtt_pump.flush() self.assertEqual( client_protocol.data, (ConnACK(session_present=False, return_code=0).serialise() + SubACK(packet_identifier=1, return_codes=[0]).serialise())) client_protocol.data = b"" session.publish("com.test.wamp", "bar") pump.flush() reactor.advance(0.1) mqtt_pump.flush() self.assertEqual( client_protocol.data, Publish(duplicate=False, qos_level=0, retain=False, topic_name="com/test/wamp", payload=b'{"args":["bar"]}').serialise())
def _test_lastwill(self): """ FIXME: reactivate this test. The MQTT client can set a last will message which will be published when it disconnects. """ reactor, router, server_factory, session_factory = build_mqtt_server() session, pump = connect_application_session( server_factory, ObservingSession, component_config=ComponentConfig(realm="mqtt", controller=MockContainer())) client_transport, client_protocol, mqtt_pump = connect_mqtt_server( server_factory) client_transport.write( Connect(client_id="testclient", username="******", password="******", will_topic="test", will_message=b'{"args":["foobar"]}', flags=ConnectFlags(clean_session=False, username=True, password=True, will=True)).serialise()) mqtt_pump.flush() # We get a CONNECT self.assertEqual( client_protocol.data, ConnACK(session_present=False, return_code=0).serialise()) client_protocol.data = b"" client_transport.write(Disconnect().serialise()) mqtt_pump.flush() pump.flush() self.assertEqual(client_transport.disconnected, True) # This needs to be replaced with the real deal, see https://github.com/crossbario/crossbar/issues/885 self.assertEqual(len(session.events), 1) self.assertEqual(session.events, [{"args": ["foobar"]}])
def test_tls_auth_denied(self): """ A MQTT client offering the wrong certificate won't be authenticated. """ reactor, router, server_factory, session_factory = build_mqtt_server() real_reactor = selectreactor.SelectReactor() logger = make_logger() session, pump = connect_application_session( server_factory, ObservingSession, component_config=ComponentConfig(realm=u"mqtt")) endpoint = create_listening_endpoint_from_config({ "type": "tcp", "port": 1099, "interface": "0.0.0.0", "tls": { "certificate": "server.crt", "key": "server.key", "dhparam": "dhparam", "ca_certificates": [ "ca.cert.pem", "intermediate.cert.pem" ]}, }, FilePath(__file__).sibling('certs').path, real_reactor, logger) client_endpoint = create_connecting_endpoint_from_config({ "type": "tcp", "host": "127.0.0.1", "port": 1099, "tls": { # BAD key: trusted by the CA, but wrong ID "certificate": "client_1.crt", "hostname": u"localhost", "key": "client_1.key", "ca_certificates": [ "ca.cert.pem", "intermediate.cert.pem" ]}, }, FilePath(__file__).sibling('certs').path, real_reactor, logger) p = [] l = endpoint.listen(server_factory) class TestProtocol(Protocol): data = b"" expected = ( ConnACK(session_present=False, return_code=1).serialise()) def dataReceived(self_, data): self_.data = self_.data + data if len(self_.data) == len(self_.expected): self.assertEqual(self_.data, self_.expected) real_reactor.stop() @l.addCallback def _listening(factory): d = client_endpoint.connect(Factory.forProtocol(TestProtocol)) @d.addCallback def _(proto): p.append(proto) proto.transport.write( Connect(client_id=u"test123", flags=ConnectFlags(clean_session=False)).serialise()) proto.transport.write( Publish(duplicate=False, qos_level=1, retain=False, topic_name=u"test", payload=b"{}", packet_identifier=1).serialise()) lc = LoopingCall(pump.flush) lc.clock = real_reactor lc.start(0.01) def timeout(): print("Timing out :(") real_reactor.stop() print(self.logs.log_text.getvalue()) # Timeout, just in case real_reactor.callLater(10, timeout) real_reactor.run() client_protocol = p[0] # We get a CONNECT self.assertEqual(client_protocol.data, ConnACK(session_present=False, return_code=1).serialise()) client_protocol.data = b"" pump.flush() # No events! self.assertEqual(len(session.events), 0)
def _test_tls_auth(self): """ A MQTT client can connect using mutually authenticated TLS authentication. """ reactor, router, server_factory, session_factory = build_mqtt_server() real_reactor = selectreactor.SelectReactor() logger = make_logger() session, pump = connect_application_session( server_factory, ObservingSession, component_config=ComponentConfig(realm="mqtt", controller=MockContainer())) endpoint = create_listening_endpoint_from_config( { "type": "tcp", "port": 1099, "interface": "0.0.0.0", "tls": { "certificate": "server.crt", "key": "server.key", "dhparam": "dhparam", "ca_certificates": ["ca.cert.pem", "intermediate.cert.pem"] }, }, FilePath(__file__).sibling('certs').path, real_reactor, logger) client_endpoint = create_connecting_endpoint_from_config( { "type": "tcp", "host": "127.0.0.1", "port": 1099, "tls": { "certificate": "client.crt", "hostname": "localhost", "key": "client.key", "ca_certificates": ["ca.cert.pem", "intermediate.cert.pem"] }, }, FilePath(__file__).sibling('certs').path, real_reactor, logger) p = [] l = endpoint.listen(server_factory) class TestProtocol(Protocol): data = b"" expected = ( ConnACK(session_present=False, return_code=0).serialise() + PubACK(packet_identifier=1).serialise()) def dataReceived(self_, data): self_.data = self_.data + data if len(self_.data) == len(self_.expected): self.assertEqual(self_.data, self_.expected) real_reactor.stop() @l.addCallback def _listening(factory): d = client_endpoint.connect(Factory.forProtocol(TestProtocol)) @d.addCallback def _(proto): p.append(proto) proto.transport.write( Connect( client_id="test123", flags=ConnectFlags(clean_session=False)).serialise()) proto.transport.write( Publish(duplicate=False, qos_level=1, retain=False, topic_name="test", payload=b"{}", packet_identifier=1).serialise()) lc = LoopingCall(pump.flush) lc.clock = real_reactor lc.start(0.01) def timeout(): print("Timing out :(") real_reactor.stop() print(self.logs.log_text.getvalue()) # Timeout, just in case real_reactor.callLater(10, timeout) real_reactor.run() client_protocol = p[0] # We get a CONNECT self.assertEqual( client_protocol.data, ConnACK(session_present=False, return_code=0).serialise() + PubACK(packet_identifier=1).serialise()) client_protocol.data = b"" pump.flush() # This needs to be replaced with the real deal, see https://github.com/crossbario/crossbar/issues/885 self.assertEqual(len(session.events), 1) self.assertEqual(session.events, [{"args": tuple(), "kwargs": {}}])