Example #1
0
 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')
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
 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
Example #5
0
 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
Example #6
0
 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)
Example #7
0
    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
Example #8
0
 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",
     )
Example #9
0
 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
Example #10
0
 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
Example #11
0
 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
Example #12
0
 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
Example #13
0
 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")
Example #14
0
    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)
Example #15
0
 def test_to_bytes_2(self):
     header = MQTTFixedHeader(CONNECT, 0x00, 268435455)
     data = header.to_bytes()
     self.assertEqual(data, b'\x10\xff\xff\xff\x7f')
Example #16
0
 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))
Example #17
0
 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))
Example #18
0
 def test_to_bytes(self):
     header = MQTTFixedHeader(CONNECT, 0x00, 0)
     data = header.to_bytes()
     self.assertEqual(data, b'\x10\x00')
Example #19
0
 def test_to_bytes(self):
     header = MQTTFixedHeader(PacketType.CONNECT, 0x00, 0)
     data = header.to_bytes()
     self.assertEqual(data, b"\x10\x00")
Example #20
0
 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))
Example #21
0
    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()
Example #22
0
 def test_to_bytes_2(self):
     header = MQTTFixedHeader(CONNECT, 0x00, 268435455)
     data = header.to_bytes()
     self.assertEqual(data, b'\x10\xff\xff\xff\x7f')
Example #23
0
 def test_to_bytes(self):
     header = MQTTFixedHeader(CONNECT, 0x00, 0)
     data = header.to_bytes()
     self.assertEqual(data, b'\x10\x00')