def test_encode(self): header = MQTTFixedHeader(CONNECT, 0x00, 0) variable_header = ConnectVariableHeader(0xce, 0, 'MQTT', 4) payload = ConnectPayload('0123456789', 'WillTopic', b'WillMessage', 'user', 'password') message = ConnectPacket(header, variable_header, payload) encoded = message.to_bytes() self.assertEqual(encoded, b'\x10\x3e\x00\x04MQTT\x04\xce\x00\x00\x00\x0a0123456789\x00\x09WillTopic\x00\x0bWillMessage\x00\x04user\x00\x08password')
def test_from_bytes_with_length(self): stream = asyncio.StreamReader(loop=self.loop) stream.feed_data(b"\x10\xff\xff\xff\x7f") header = self.loop.run_until_complete(MQTTFixedHeader.from_stream(stream)) self.assertEqual(header.packet_type, PacketType.CONNECT) self.assertFalse(header.flags & 0x08) self.assertEqual((header.flags & 0x06) >> 1, 0) self.assertFalse(header.flags & 0x01) self.assertEqual(header.remaining_length, 268435455)
def test_from_bytes_with_length(self): data = b'\x10\xff\xff\xff\x7f' stream = BufferReader(data) header = self.loop.run_until_complete(MQTTFixedHeader.from_stream(stream)) self.assertEqual(header.packet_type, CONNECT) self.assertFalse(header.flags & 0x08) self.assertEqual((header.flags & 0x06) >> 1, 0) self.assertFalse(header.flags & 0x01) self.assertEqual(header.remaining_length, 268435455)
def __init__(self, fixed: MQTTFixedHeader=None, variable_header: PacketIdVariableHeader=None): if fixed is None: header = MQTTFixedHeader(PUBCOMP, 0x00) else: if fixed.packet_type is not PUBCOMP: raise HBMQTTException("Invalid fixed packet type %s for PubcompPacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = variable_header self.payload = None
def __init__(self, fixed: MQTTFixedHeader=None, variable_header: PacketIdVariableHeader=None): if fixed is None: header = MQTTFixedHeader(PUBREL, 0x02) # [MQTT-3.6.1-1] else: if fixed.packet_type is not PUBREL: raise HBMQTTException("Invalid fixed packet type %s for PubrelPacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = variable_header self.payload = None
def test_from_bytes_with_length(self): data = b'\x10\xff\xff\xff\x7f' stream = BufferReader(data) header = self.loop.run_until_complete( MQTTFixedHeader.from_stream(stream)) self.assertEqual(header.packet_type, CONNECT) self.assertFalse(header.flags & 0x08) self.assertEqual((header.flags & 0x06) >> 1, 0) self.assertFalse(header.flags & 0x01) self.assertEqual(header.remaining_length, 268435455)
def __init__(self, fixed: MQTTFixedHeader=None, variable_header: PacketIdVariableHeader=None, payload=None): if fixed is None: header = MQTTFixedHeader(SUBSCRIBE, 0x02) # [MQTT-3.8.1-1] else: if fixed.packet_type is not SUBSCRIBE: raise HBMQTTException("Invalid fixed packet type %s for SubscribePacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = variable_header self.payload = payload
def test_encode(self): header = MQTTFixedHeader(CONNECT, 0x00, 0) variable_header = ConnectVariableHeader(0xCE, 0, "MQTT", 4) payload = ConnectPayload( "0123456789", "WillTopic", b"WillMessage", "user", "password" ) message = ConnectPacket(header, variable_header, payload) encoded = message.to_bytes() self.assertEqual( encoded, b"\x10\x3e\x00\x04MQTT\x04\xce\x00\x00\x00\x0a0123456789\x00\x09WillTopic\x00\x0bWillMessage\x00\x04user\x00\x08password", )
def __init__(self, fixed: MQTTFixedHeader = None): if fixed is None: header = MQTTFixedHeader(PINGREQ, 0x00) else: if fixed.packet_type is not PINGREQ: raise HBMQTTException( "Invalid fixed packet type %s for PingReqPacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = None self.payload = None
def __init__(self, fixed: MQTTFixedHeader = None): if fixed is None: header = MQTTFixedHeader(DISCONNECT, 0x00) else: if fixed.packet_type is not DISCONNECT: raise HBMQTTException( "Invalid fixed packet type %s for DisconnectPacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = None self.payload = None
def __init__(self, fixed: MQTTFixedHeader = None, variable_header: ConnackVariableHeader = None, payload=None): if fixed is None: header = MQTTFixedHeader(CONNACK, 0x00) else: if fixed.packet_type is not CONNACK: raise HBMQTTException( "Invalid fixed packet type %s for ConnackPacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = variable_header self.payload = None
def __init__( self, fixed: MQTTFixedHeader = None, vh: ConnectVariableHeader = None, payload: ConnectPayload = None, ): if fixed is None: header = MQTTFixedHeader(CONNECT, 0x00) else: if fixed.packet_type is not CONNECT: raise HBMQTTException( "Invalid fixed packet type %s for ConnectPacket init" % fixed.packet_type) header = fixed super().__init__(header) self.variable_header = vh self.payload = payload
def _reader_coro(self): self.logger.debug("Starting reader coro") while self._running: try: self._reader_ready.set() fixed_header = yield from asyncio.wait_for(MQTTFixedHeader.from_stream(self.session.reader), 5) if fixed_header: cls = packet_class(fixed_header) packet = yield from cls.from_stream(self.session.reader, fixed_header=fixed_header) self.logger.debug(" <-in-- " + repr(packet)) yield from self.incoming_queues[packet.fixed_header.packet_type].put(packet) self.packet_received.send(packet) else: self.logger.debug("No more data, stopping reader coro") break except asyncio.TimeoutError: self.logger.debug("Input stream read timeout") except NoDataException as nde: self.logger.debug("No data available") except Exception as e: self.logger.warn("Unhandled exception in reader coro: %s" % e) break self.logger.debug("Reader coro stopped")
def client_connected(self, reader, writer): #handle connection and create session to add to the list of sessions #read connection packet from the client connect = yield from MQTTConnect.ConnectPacket.from_stream(reader) if (connect.payload.client_id is None): generate_id = True else: generate_id = False #send a connack packet to client depending on correct credentials connack = None if (connect.username == self._username and connect.password == self._password): connack = MQTTConnack.ConnackPacket.build( 0, MQTTConnack.CONNECTION_ACCEPTED) connected = True else: connack = MQTTConnack.ConnackPacket.build( 0, MQTTConnack.BAD_USERNAME_PASSWORD) connected = False writer.write(connack.to_bytes()) if (not connected): return new_session = Session() if (generate_id): new_session.client_id = new_session.generate_client_id() else: new_session.client_id = connect.client_id new_session.remote_address = writer.get_extra_info('peername') new_session.remote_port = writer.get_extra_info('socket') new_session.username = connect.username new_session.password = connect.password new_session.keep_alive = connect.keep_alive new_session.writer = writer new_session.reader = reader self._sessions[new_session.client_id] = new_session print("New client; %s connected from %s with keep_alive: %s" % (new_session.client_id, new_session.remote_address, new_session.keep_alive)) #received packets are checked and the corresponding method is used (publish, sub/unsub, disconnect) try: while connected: mqtt_header = yield from asyncio.wait_for( MQTTFixedHeader.from_stream(reader), new_session.keep_alive + 1, loop=self._loop) cls = packet_class(fixed_header=mqtt_header) packet = yield from cls.from_stream(reader, fixed_header=mqtt_header) if (packet.fixed_header.packet_type == SUBSCRIBE): for (topic, qos) in packet.payload.topics: if (qos != 0): print("QoS is different than expected") print(qos) self.add_subscription(topic, new_session) elif (packet.fixed_header.packet_type == UNSUBSCRIBE): for (topic, qos) in packet.payload.topics: if (qos != 0): print("QoS is different than expected") print(qos) self.del_subscription(topic, new_session) elif (packet.fixed_header.packet_type == PUBLISH): topic = packet.variable_header.topic_name message = packet.payload.data print("Broadcast; Topic: %s, Payload: %s" % (topic, message)) yield from self.broadcast_message(new_session, topic, message) elif (packet.fixed_header.packet_type == DISCONNECT): self.del_all_subscriptions(new_session) self.del_session(new_session.client_id) connected = False print("Client: %s disconnected" % (new_session.client_id)) elif (packet.fixed_header.packet_type == PINGREQ): pingresp_packet = PingRespPacket.build() writer.write(pingresp_packet.to_bytes()) else: print('Not yet supported packet received') except asyncio.TimeoutError: print("Client %s didn't respond; diconnecting" % new_session.client_id) self.del_session(new_session.client_id)
def test_to_bytes_2(self): header = MQTTFixedHeader(CONNECT, 0x00, 268435455) data = header.to_bytes() self.assertEqual(data, b'\x10\xff\xff\xff\x7f')
def test_from_bytes_ko_with_length(self): stream = asyncio.StreamReader(loop=self.loop) stream.feed_data(b"\x10\xff\xff\xff\xff\x7f") with self.assertRaises(MQTTException): self.loop.run_until_complete(MQTTFixedHeader.from_stream(stream))
def test_from_bytes_ko_with_length(self): data = b'\x10\xff\xff\xff\xff\x7f' stream = BufferReader(data) with self.assertRaises(MQTTException): self.loop.run_until_complete(MQTTFixedHeader.from_stream(stream))
def test_to_bytes(self): header = MQTTFixedHeader(CONNECT, 0x00, 0) data = header.to_bytes() self.assertEqual(data, b'\x10\x00')
def test_to_bytes(self): header = MQTTFixedHeader(PacketType.CONNECT, 0x00, 0) data = header.to_bytes() self.assertEqual(data, b"\x10\x00")
def _reader_loop(self): self.logger.debug("%s Starting reader coro" % self.session.client_id) running_tasks = collections.deque() keepalive_timeout = self.session.keep_alive if keepalive_timeout <= 0: keepalive_timeout = None while True: try: self._reader_ready.set() while running_tasks and running_tasks[0].done(): running_tasks.popleft() if len(running_tasks) > 1: self.logger.debug("handler running tasks: %d" % len(running_tasks)) fixed_header = yield from asyncio.wait_for( MQTTFixedHeader.from_stream(self.reader), keepalive_timeout, loop=self._loop) if fixed_header: if fixed_header.packet_type == RESERVED_0 or fixed_header.packet_type == RESERVED_15: self.logger.warning( "%s Received reserved packet, which is forbidden: closing connection" % (self.session.client_id)) yield from self.handle_connection_closed() else: cls = packet_class(fixed_header) packet = yield from cls.from_stream( self.reader, fixed_header=fixed_header) yield from self.plugins_manager.fire_event( EVENT_MQTT_PACKET_RECEIVED, packet=packet, session=self.session) task = None if packet.fixed_header.packet_type == CONNACK: task = asyncio.ensure_future( self.handle_connack(packet), loop=self._loop) elif packet.fixed_header.packet_type == SUBSCRIBE: task = asyncio.ensure_future( self.handle_subscribe(packet), loop=self._loop) elif packet.fixed_header.packet_type == UNSUBSCRIBE: task = asyncio.ensure_future( self.handle_unsubscribe(packet), loop=self._loop) elif packet.fixed_header.packet_type == SUBACK: task = asyncio.ensure_future( self.handle_suback(packet), loop=self._loop) elif packet.fixed_header.packet_type == UNSUBACK: task = asyncio.ensure_future( self.handle_unsuback(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBACK: task = asyncio.ensure_future( self.handle_puback(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBREC: task = asyncio.ensure_future( self.handle_pubrec(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBREL: task = asyncio.ensure_future( self.handle_pubrel(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBCOMP: task = asyncio.ensure_future( self.handle_pubcomp(packet), loop=self._loop) elif packet.fixed_header.packet_type == PINGREQ: task = asyncio.ensure_future( self.handle_pingreq(packet), loop=self._loop) elif packet.fixed_header.packet_type == PINGRESP: task = asyncio.ensure_future( self.handle_pingresp(packet), loop=self._loop) elif packet.fixed_header.packet_type == PUBLISH: task = asyncio.ensure_future( self.handle_publish(packet), loop=self._loop) elif packet.fixed_header.packet_type == DISCONNECT: task = asyncio.ensure_future( self.handle_disconnect(packet), loop=self._loop) elif packet.fixed_header.packet_type == CONNECT: self.handle_connect(packet) else: self.logger.warning( "%s Unhandled packet type: %s" % (self.session.client_id, packet.fixed_header.packet_type)) if task: running_tasks.append(task) else: self.logger.debug( "%s No more data (EOF received), stopping reader coro" % self.session.client_id) break except MQTTException: self.logger.debug("Message discarded") except asyncio.CancelledError: self.logger.debug("Task cancelled, reader loop ending") break except asyncio.TimeoutError: self.logger.debug("%s Input stream read timeout" % self.session.client_id) self.handle_read_timeout() except NoDataException: self.logger.debug("%s No data available" % self.session.client_id) except BaseException as e: self.logger.warning( "%s Unhandled exception in reader coro: %r" % (type(self).__name__, e)) break while running_tasks: running_tasks.popleft().cancel() yield from self.handle_connection_closed() self._reader_stopped.set() self.logger.debug("%s Reader coro stopped" % self.session.client_id) yield from self.stop()